描述
Service通常总是称之为“后台服务”,其中“后台”一词是相对于前台而言的,具体是指其本身的运行并不依赖于用户可视的UI界面;
因此,从实际业务需求上来理解,Service的适用场景应该具备以下条件:
1、并不依赖于用户可视的UI界面(当然,这一条其实也不是绝对的,如前台Service就是与Notification界面结合使用的);
2、具有较长时间的运行特性。
Service特性
1、Service本身都是运行在其所在进程的主线程(如果Service与Clinet同属于一个进程,则是运行于UI线程),但Service一般都是需要进行”长期“操作,所以经常写法是在自定义Service中处理”长期“操作时需要新建线程,以免阻塞UI线程或导致ANR;
2、Service一旦创建,需要停止时都需要显示调用相应的方法(startService需要调用stopService()或Service本身调用stopSelf(..);
bindService需要调用unbindService(),否则对于startService将处于一直运行状态,对于bindService,当Client生命周期结束时也将因此问题。也就是说,Service执行完毕后,必须人为的去停止它。
startService
startService()启动Service后,此时Service的生命周期与Client本身的什么周期是没有任何关系的;
使用步骤如下:
1、创建Service子类,继承自Service
2、在AndroidManifest文件中注册Service:
项目中的每一个Service都必须在AndroidManifest.xml中注册才能生效。
3、启动Service:
当第一次启动Service的时候,会调用该Service中的onCreate()和onStartCommand(Intent intent, int flags, int startId)方法。若再次启动Service,onCreate()不会被调用,只有onStartCommand(Intent intent, int flags, int startId)方法才会调用。其中参数flags默认情况下是0,对应的常量名为START_STICKY_COMPATIBILITY。startId是一个唯一的整型,用于表示此次Client执行startService(...)的请求请求标识,在多次startService(...)的情况下,呈现0,1,2....递增。
4、销毁Service:
无论多少次的startService,只需要一次stopService()即可将此Service终止,执行onDestroy()函数(其实很好理解,因为onDestroy()与onCreate()回调是相对的)。
5、注意点:
5.1、当用户强制kill掉进程时,onDestroy()是不会执行的。
5.2、对于同一个Service,Service实例一次永远只存在一个,而不管Client是否是相同的组件,也不管Client是否处于相同的进程中。
5.3、Service通过startService(..)启动Service后,此时Service的生命周期与Client本身的什么周期是没有任何关系的,只有Client调用stopService(..)或Service本身调用stopSelf(..)才能停止此Service。当然,当用户强制kill掉Service进程或系统因内存不足也可能kill掉此Service。
5.4、Client A 通过startService()启动Service后,可以在其他Client(如Client B、Client C)通过调用stopService()结束此Service。
5.5、Client调用stopService()时,如果当前Service没有启动,也不会出现任何报错或问题,也就是说,stopService()无需做当前Service是否有效的判断。
5.6、当Service需要运行在单独的进程中,AndroidManifest.xml声明时需要通过android:process指明此进程名称,当此Service需要对其他App开放时,android:exported属性值需要设置为true(当然,在有intent-filter时默认值就是true)。
自定义Service
public class MyService extends Service {
public static final String TAG = "MyService";
@Override
public void onCreate() {
super.onCreate();
Log.e(TAG, "onCreate() executed");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG, "onStartCommand() executed");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.e(TAG, "onDestroy() executed");
}
//返回具体的IBind对象
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
在AndroidManifest文件中注册Service
android:name=".MyService"
android:exported="false">
startService
public class ServiceTestOneActivity extends BaseActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_service_test);
Log.e("ServiceTestOneActivity",
"ServiceTestOneActivity thread id is " + Thread.currentThread().getId());
findViewById(R.id.bt_start).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent startIntent = new Intent(ServiceTestOneActivity.this, MyService.class);
startService(startIntent);
}
});
findViewById(R.id.bt_stop).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent stopIntent = new Intent(ServiceTestOneActivity.this, MyService.class);
stopService(stopIntent);
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
}
}
bindService
bindService的主要特性在于Service的生命周期是依附于Client的生命周期的,当Client销毁时,bindService将执行onDestroy。
同时通过Service中的Binder对象可以较为方便进行Client-Service通信。bindService一般使用过程如下:
1、创建Service子类,继承自Service,并重写onBind(Intent intent)方法,此方法中需要返回具体的Binder对象。
2、Client通过实现Serv