Android四大组件之Service
android开发的四大组件分别是:Activity(活动),活动,与用户交互界面; Service(服务),Content Provider(内容提供器),Broadcast Receiver(广播)。
今天介绍一下Service(服务)。
Service的生命周期
Service有两种不同的创建方式,两种方式的生命周期(回调的方法)也不一样
被启动(startService)的服务的生命周期:
- 如果一个Service被某个Activity调用Context.startService 方法启动,不管是否有Activity使用bindService(绑定)或unbindService(解除绑定)到该Service,该Service都在后台运行。
- 如果一个Service被startService 方法多次启动,
onCreate方法只会调用一次,而onStartCommand每次启动都会被调用,并且系统只会创建Service的一个实例(同时只需要调用一次stopService)
。该Service会一直在后台运行,不管对应程序的Activity是否在运行,直到被调用stopService或自身的stopSelf方法。当然如果系统资源不足,android系统也可能结束服务。
被绑定(bindService)的服务的生命周期:
- 如果一个Service被某个Activity调用Context.bindService方法绑定启动,
不管调用bindService 调用几次,onCreate和onBind方法都只会调用一次,同时onStartCommand方法始终不会被调用
。 - 当连接建立之后,Service将会一直运行,除非调用Context.unbindService (该方法调用的是onUnbind和onDestroy)断开连接或者之前调用bindService的Context不存在了(如Activity被finish),系统将会自动停止Service。
被启动又被绑定的服务的生命周期:
- 如果一个Service又被启动又被绑定,则该Service会一直在后台运行。
- 不管调用startService启动多少次Service,onCreate始终只会调用一次,onStartCommand每次启动都会被调用。
- 调用unbindService不会停止Service,必须同时调用unbindService与stopService才能停止服务。
小提示:
不管是什么原因导致Service被终止,onDestroy方法都会被调用,在这里应当做一些清除工作,如停止在Service中创建并运行的线程。
实例
理论知识说完之后咱们也要动动手,撸几行代码试验一下,实验才是检验真理的唯一标准。
布局
我们在activity_main.xml中放置四个Button按钮“startService”、“stopService”、“bondService”、“unbindService”,分别调用四个方法。
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/bnt_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="startService"
android:textAllCaps="false" />
<Button
android:id="@+id/bnt_destroy"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="stopService"
android:textAllCaps="false" />
<Button
android:id="@+id/bnt_bond"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="bondService"
android:textAllCaps="false" />
<Button
android:id="@+id/bnt_unbond"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="unbindService"
android:textAllCaps="false" />
</LinearLayout>
创建Service类
先说一下创建类的方法吧。
方法一:
自己创建一个类继承Service类,并重写一系列方法
注意:这种方式创建完成之后要在AndroidManifest.xml中声明注册Service类
方法二:
Android Studio可以直接创建Service类,如下图所示:
为了方便,我们建立两个Service类,一个用于学习startService()方式启动服务的StartService,另一个用于bondService()方式绑定服务的BindService。
StartService类
public class StartService extends Service {
public StartService() {
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
//当Service第一次创建时,回调该方法(只一次),除非Service被销毁重新创建
@Override
public void onCreate() {
super.onCreate();
Log.e("调用方法:", "onCreate");
}
//当其他组件调用startService()方法请求启动Service时,该方法被回调(每次)。
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("调用方法:", "onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
//当Service被销毁时回调,释放占用的资源
@Override
public void onDestroy() {
super.onDestroy();
Log.e("调用方法:", "onDestroy");
}
}
BindService类
public class BindService extends Service {
public BindService() {
}
//绑定服务时才会调用,必须要实现的方法
@Override
public IBinder onBind(Intent intent) {
Log.e("调用方法:", "onBind");
return new MyBinder();//通过binder实现调用者client与Service之间的通信
}
@Override
public boolean onUnbind(Intent intent) {
Log.e("调用方法:", "onUnbind");
return super.onUnbind(intent);
}
//当Service第一次创建时,回调该方法(只一次),除非Service被销毁重新创建
@Override
public void onCreate() {
super.onCreate();
Log.e("调用方法:", "onCreate");
}
//当调用startService()方法请求启动Service时,该方法被回调(每次)。
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e("调用方法:", "onStartCommand");
return super.onStartCommand(intent, flags, startId);
}
//当Service被销毁时回调,释放占用的资源
@Override
public void onDestroy() {
super.onDestroy();
Log.e("调用方法:", "onDestroy");
}
class MyBinder extends Binder {
public BindService getService() {
System.out.println("绑定服务");
return BindService.this;
}
}
private final Random generator = new Random();
//getRandomNumber是Service供client调用的公共方法
public int getRandomNumber() {
return generator.nextInt();
}
}
启动Service
startService()方式启动Service,stopService()方式停止Service
bnt_start = findViewById(R.id.bnt_start);
bnt_destroy = findViewById(R.id.bnt_destroy);
bnt_start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, StartService.class);
startService(intent);
}
});
bnt_destroy.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, StartService.class);
stopService(intent);
}
});
bindService()方式绑定Service,unbindService()解绑停止Service
bnt_bond = findViewById(R.id.bnt_bond);
bnt_unbond = findViewById(R.id.bnt_unbond)
bnt_bond.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this, BindService.class);
/**
* 这里传入BIND_AUTO_CREATE,表示在Activity和Service关联后自动创建Service
* 这会使得MyService中的onCreate()方法得到执行,但onStartCommand()方法不会执行
*/
bindService(intent, conn, BIND_AUTO_CREATE);
}
});
bnt_unbond.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
/**
* 如果没有绑定服务就执行unbindService就会报错
* java.lang.IllegalArgumentException: Service not registered: com.example.servicedemo.MainActivity$1@3f402f68
*/
unbindService(conn);
}
});
效果:
从gif图中可以检验出我们的理论是正确的,如果你也做到这里了,毫不犹豫地给自己一个赞吧,鼓励一下自己。
Demo下载
Service的基本使用就分享到这里,提供一下代码和大家分享学习一下:GitHub下载代码