Android开发之低调的Service
锲而舍之,朽木不折;锲而不舍,金石可镂。——荀况
今天学习了一下Service的用法就和大家一起来讨论Android中Service的相关知识点,如有谬误,欢迎批评指正,如有疑问欢迎留言。
一、Service用途
Service在Android中和Activity是属于同一级别上的组件,Android中的Service,其意思是“服务”,它在后台运行不可交互。Service自己不能运行,需要通过某一个Activity或者其它Context对象来调用,Context.startService()和Context.bindService()两种方式启动
Service 。 Service在Android中和Activity是属于同一级别上的组件,Android 中的Service ,其意思是“服务”,它是在后台运行,不可交互的。Service自己不能运行,需要通过某一个Activity或者其它Context对象来调用,Context.startService()和Context.bindService()两种方式启动 Service 。
Android 中的服务,它与 Activity不同,它是不能与用户交互的,不能自己启动的,运行在后台的程序(干着重的工作,却连个界面也没有,因此我说它低调),如果我们退出应用时, Service进程并没有结束,它仍然在后台运行,那我们什么时候会用到Service呢?比如我们播放音乐的时候,有可能想边听音乐边干些其他事情,当我们退出播放音乐的应用,如果不用 Service,我们就听不到歌了,所以这时候就得用到Service了,又比如当我们一个应用的数据是通过网络获取的,不同时间(一段时间)的数据是不同的,这时候我们可以用
Service在后台定时更新,而不用每打开应用的时候在去获取。如果在 Service的 onCreate或者 onStart方法中做一些很耗时的动作,最好是启动一个新线程来运行这个 Service,因为,如果 Service运行在主线程中,会影响到程序的 UI操作或者阻塞主线程中的其它事情。
二、Service的生命周期
首先来看官网给出的Service的生命周期图
2.onStart(Intent intent, int startId) 启动Service
4.onDestroy() 销毁Service
5.onBind() 返回一个IBinder接口对象给Service
package com.example.servicepractice; import android.app.Service; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.util.Log; public class MyService extends Service { private static final String TAG = "MyService"; @Override public void onCreate() { super.onCreate(); Log. i(TAG,"onCreate called" ); } @Override public void onStart(Intent intent, int startId) { super. onStart(intent, startId); Log. i(TAG,"onStart called" ); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log. i(TAG,"onStartCommand called" ); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); Log. i(TAG,"onDestroy called" ); } @Override public IBinder onBind(Intent intent) { Log. i(TAG,"onBind called" ); return null; } @Override public boolean onUnbind(Intent intent) { Log. i(TAG,"onUnbind called" ); return super.onUnbind(intent); } }2.MainActivity的代码
package com.example.servicepractice; import android.os.Bundle; import android.os.IBinder; import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.util.Log; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup.LayoutParams; import android.widget.Button; public class MainActivity extends Activity { protected static final String TAG = "MyService"; private Button btn_start; private Button btn_stop; private Button btn_bind; private Button btn_unbind; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout. activity_main); findViews(); setClick(); } private void findViews() { btn_start=(Button) findViewById(R.id. btn_start); btn_stop=(Button) findViewById(R.id. btn_stop); btn_bind=(Button) findViewById(R.id. btn_bind); btn_unbind=(Button) findViewById(R.id. btn_unbind); } private void setClick() { //采用startService启动服务 btn_start.setOnClickListener( new OnClickListener() { public void onClick(View v) { Intent intent= new Intent(MainActivity.this,MyService.class ); startService(intent); } }); //销毁服务 btn_stop.setOnClickListener( new OnClickListener() { public void onClick(View v) { Intent intent= new Intent(MainActivity.this,MyService.class ); stopService(intent); } }); //绑定服务 btn_bind.setOnClickListener( new OnClickListener() { public void onClick(View v) { Intent intent = new Intent(MainActivity.this,MyService.class ); bindService(intent, conn,Context. BIND_AUTO_CREATE); } }); //解除绑定 btn_unbind.setOnClickListener( new OnClickListener() { public void onClick(View v) { unbindService( conn); } }); } private ServiceConnection conn=new ServiceConnection() { public void onServiceConnected(ComponentName name, IBinder service) { //connected Log. i(TAG,"onServiceConnection called." ); } public void onServiceDisconnected(ComponentName name) { } }; }
<service android:name="com.example.servicepractice.MyService" > <intent-filter> <action android:name="com.example.service" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </service>
//采用startService启动服务 btn_start.setOnClickListener( new OnClickListener() { public void onClick(View v) { Intent intent= new Intent(MainActivity.this,MyService.class ); startService(intent); } }); //销毁服务 btn_stop.setOnClickListener( new OnClickListener() { public void onClick(View v) { Intent intent=new Intent(MainActivity.this,MyService. class); stopService(intent); } });首先我们点击启动按钮打印日志如下
我们发现再次启动时系统并没有重新实例化这个Service,因为系统发现这个服务已经启动了,此时它会直接调用onStartCommand方法,在onStartCommand方法中会调用onStart方法
onStartCommand方法的源码:
/* @param intent The Intent supplied to {@link android.content.Context#startService}, * as given. This may be null if the service is being restarted after * its process has gone away, and it had previously returned anything * except {@link #START_STICKY_COMPATIBILITY}. * @param flags Additional data about this start request. Currently either * 0, {@link #START_FLAG_REDELIVERY}, or {@link #START_FLAG_RETRY}. * @param startId A unique integer representing this specific request to * start. Use with {@link #stopSelfResult(int)}. * * @return The return value indicates what semantics the system should * use for the service's current started state. It may be one of the * constants associated with the {@link #START_CONTINUATION_MASK} bits. * * @see #stopSelfResult(int) */ public int onStartCommand(Intent intent, int flags, int startId) { onStart(intent , startId); return mStartCompatibility ? START_STICKY_COMPATIBILITY : START_STICKY; }操作完启动服务按钮后我们接着点击销毁服务按钮打印日志如下
发现当调用 stopService(intent)这个方法是会调用Service的onDestroy方法从而销毁服务。
2."绑定服务"和"解除绑定"的学习
//绑定服务 btn_bind.setOnClickListener( new OnClickListener() { public void onClick(View v) { Intent intent = new Intent(MainActivity.this,MyService.class ); bindService(intent, conn,Context. BIND_AUTO_CREATE); } }); //解除绑定 btn_unbind.setOnClickListener( new OnClickListener() { public void onClick(View v) { unbindService( conn); } });
private ServiceConnection conn= new ServiceConnection() { /** * Called when a connection to the Service has been established, with * the {@link android.os.IBinder} of the communication channel to the * Service. * * @param name The concrete component name of the service that has * been connected. * * @param service The IBinder of the Service's communication channel, * which you can now make calls on. */ public void onServiceConnected(ComponentName name, IBinder service) { //connected Log. i( TAG,"onServiceConnection called." ); } /** * Called when a connection to the Service has been lost. This typically * happens when the process hosting the service has crashed or been killed. * This does <em>not </em> remove the ServiceConnection itself -- this * binding to the service will remain active, and you will receive a call * to {@link #onServiceConnected} when the Service is next running. * * @param name The concrete component name of the service whose * connection has been lost. */ public void onServiceDisconnected(ComponentName name) { } };到这我们还差一步就可以绑定服务了,因为在前面服务中的onBind方法返回值为null,这样是不行的,要想实现绑定操作,必须返回一个实现了IBinder接口类型的实例,该接口描述了与远程对象进行交互的抽象协议,有了它我们才能与服务进行交互。所以我们要修改代码
@Override public IBinder onBind(Intent intent) { Log. i(TAG,"onBind called" ); return new Binder(){}; }
//定义一个变量,标识这个服务是否处于绑定状态 private boolean binded; //定义一个绑定服务的方法 private void unbindService(){ if( binded){ unbindService( conn); binded= false; } } //解除绑定 btn_unbind.setOnClickListener( new OnClickListener() { public void onClick(View v) { unbindService(); } }); //在onDestroy方法中调用解除绑定的方法 protected void onDestroy() { unbindService(); };这样上面两种错误就解决了,也体现了我们写代码的严谨性。
1、在调用 bindService 绑定到Service的时候,你就应当保证在某处调用 unbindService 解除绑定(尽管 Activity 被 finish 的时候绑定会自动解除,并且Service会自动停止);
2、在使用 startService 启动服务之后,一定要使用 stopService停止服务,不管你是否使用bindService;
3、同时使用 startService 与 bindService 要注意到,Service 的终止,需要unbindService与stopService同时调用,才能终止 Service,不管 startService 与 bindService 的调用顺序,如果先调用 unbindService 此时服务不会自动终止,再调用 stopService 之后服务才会停止,如果先调用 stopService 此时服务也不会终止,而再调用 unbindService 或者 之前调用 bindService 的 Context 不存在了(如Activity 被 finish 的时候)之后服务才会自动停止;
4、当在旋转手机屏幕的时候,当手机屏幕在“横”“竖”变换时,此时如果你的Activity 如果会自动旋转的话,旋转其实是 Activity 的重新创建,因此旋转之前的使用 bindService 建立的连接便会断开(Context 不存在了),对应服务的生命周期与上述相同。
5、在 sdk 2.0 及其以后的版本中,对应的 onStart 已经被否决变为了 onStartCommand,不过之前的 onStart 任然有效。这意味着,如果你开发的应用程序用的 sdk 为 2.0 及其以后的版本,那么你应当使用 onStartCommand 而不是 onStart。
6、startService 启动服务想要用startService启动服务,不管Local (本地)还是 Remote(远程) 我们需要做的工作都是一样简单。当然要记得在Androidmanifest.xml 中注册 service。
好了这一篇就到这里了,欢迎大家留言交流,批评指正。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。