这是我参与「第四届青训营」笔记创作活动的的第3天
Service组件是什么
相当一个没有界面的Activity,在后台运行的程序,并且可以与其他组件进行交互。
- 与Activity相比同样可以开辟线程、数据存储和访问网络等
- 可以在后台处理耗时操作(文件下载、音乐播放等)
- 不受Activity生命周期的影响(Activity销毁了Service仍可以运行)
Service的创建
- 类似Activity,创建Service类
public class MyService extends Service {
public static final String TAG = "TAG";
public MyService() {
}
@Override
public void onBind() {
super.onCreate();
}
}
- AndroidManifest.xml配置组件注册
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<service
android:name=".MyService"
android:enabled="true"
android:exported="true"></service>
</application>
Service生命周期
两种状态
- 启动服务 流程图
注意点: 当服务已经被创建并激活启动后,继续startService()该服务则不会调用onCreate(),而会调用onStartCommand(),除非stopService()停止后再startService()服务,才会重新onCreate()。 简单实现Activity中启动Service
public class ServiceCode_Activity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_service_code_);
}
// 按钮事件处理
public void handleService(View v){
switch(v.getId()){
case R.id.startSerivce:{
Intent t1 = new Intent(this, MyService.class); //连接当前Activity与指定服务
startService(t1); //启动服务
};break;
case R.id.stopSerivce:{
Intent t2 = new Intent(this,MyService.class); //与上面指向的时同一个服务
stopService(t2); //停止服务 虽然Intent对象不同但是指向的时同一个服务,所以停止同一个服务
};break;
}
- 绑定服务 流程图
注意点: 只绑定服务,则服务的生命周期会随着activity销毁而结束,绑定并启动服务存在两种情况
- 绑定服务前没有启动服务:bindService()时会调用onCreate()—>onBind(),但是后台不会启动运行服务,此时,如果要启动服务则需要startService()后调用onStartCommand(),服务运行,unbindService()解绑服务时只会unBind(),服务不会被销毁,只能stopService()或系统停止(并非退出app)服务才会被销毁,并且只能unbindService()解绑后才能stopService()停止服务;如果不启动服务,unbindService()解绑服务或退出Activity时会unBind()—>onDestory();
- 绑定服务前服务已经启动:startServicce()调用onCrete()->onStartCommand(),bindService()只会调用onBind(),unbindService()解绑服务时只会unBind(),服务不会被销毁,stopService()或系统停止 服务才会被销毁;
简单实现Activity绑定Service
public class ServiceCode_Activity extends AppCompatActivity {
ServiceConnection conn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_service_code_);
conn = new ServiceConnection() { //该类对象用于客户端与服务进行关联
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
}
// 按钮事件处理
public void handleService(View v){
switch(v.getId()){
case R.id.bindSerivce:{
Intent t3 = new Intent(this,MyService.class);
// 绑定服务
bindService(t3,conn,BIND_AUTO_CREATE);
};break;
case R.id.unbindSerivce:{
// 解绑服务
unbindService(conn);
};
}
}
}
简单实现获取后台进度
IBinder 接口的实现
可以发现Service生命周期中onBind()方法返回值是一个IBinder对象,而这个IBinder作用是Android实现远程操作的基本接口,而这里我们返回IBinder对象用于将Service中数据暴露出去。
Binder类
Binder类是IBinder接口的实现类,因为IBinder接口中只有一些定义抽象的方法,而onBind()返回一个IBinder接口需要实现里面的方法,而正常情况下我们是不需要这些方法的,Binder类已经空实现了IBInder接口中的方法,我们只需要返回一个自定义Binder子类,写入暴露的数据即可。
ServiceConnection类
可以观察到bindService()绑定服务是,用到的其中一个参数就是ServiceConnection对象,该类用于客户端与服务之间的连接,因为绑定运行的服务时,onBind()和onUnbind()只会调用一次,解绑后再次bindService()和unbindService()则表示客户端与服务建立连接和连接丢失,则不会再调用onBind()和onUnbind(),而是继续回调ServiceConnection类中的onServiceConnected()和onServiceConnected()。