服务(Service)是Android中实现程序后台运行的解决方案,它非常适合去执行那些不需要和用户交互而且还要求长期运行的任务。服务的运行不依赖于任何用户界面,即使程序被切换到后台,或者用户打开了另外一个应用程序,服务仍然能够保持正常运行。
不过需要注意的是,服务并不是运行在一个独立的进程当中的,而是依赖于创建服务时所在的应用程序进程。当某个应用程序进程被杀掉时,所有依赖于该进程的服务也会停止运行。
另外,也不要被服务的后台概念所迷惑,实际上服务并不会自动开启线程,所有的代码都是默认运行在主线程当中的。也就是说,我们需要在服务的内部手动创建子线程,并在这里执行具体的任务,否则就有可能出现主线程被阻塞住的情况。
以上摘自第一行代码第二版10.1
生命周期
服务是单例模式,结合代码浅析服务的生命周期。
class MyService extend Service{
//创建服务,当启动或绑定一个服务时,若该服务尚未创建,则会执行该方法
@Override
public void onCreate();
//启动服务,创建服务后,如果服务没有被销毁,那每次调用服务不再执行onCreate而是该方法
@Override
public int onStartCommand(Intent intent, int flags, int startId);
//绑定服务,调用Context.bindService()绑定服务至Activity以便二者通信,若一个服务被绑定,则不会执行onStart方法
@Override
public IBinder onBind(Intent intent) ;
//解绑服务
@Override
public boolean onUnbind(Intent intent);
//销毁服务,销毁服务,下次调用服务时会执行onCreate方法
@Override
public void onDestroy();
}
官方图解
Tips
通过绑定启动的服务在解绑时会自动销毁
2021-09-30 14:27:28.346 3414-3414/com.tsaigee.aidldemo E/com.tsaigee.demosdk.BookManagerService: onCreate
2021-09-30 14:27:28.346 3414-3414/com.tsaigee.aidldemo E/com.tsaigee.demosdk.BookManagerService: onBind
2021-09-30 14:27:30.811 3414-3414/com.tsaigee.aidldemo E/com.tsaigee.demosdk.BookManagerService: onUnbind
2021-09-30 14:27:30.812 3414-3414/com.tsaigee.aidldemo E/com.tsaigee.demosdk.BookManagerService: onDestroy绑定已经启动的服务,在解绑时服务不会自动销毁。
2021-09-30 14:25:04.355 3323-3323/com.tsaigee.aidldemo E/com.tsaigee.demosdk.BookManagerService: onCreate
2021-09-30 14:25:04.355 3323-3323/com.tsaigee.aidldemo E/com.tsaigee.demosdk.BookManagerService: onStartCommand
2021-09-30 14:25:04.355 3323-3323/com.tsaigee.aidldemo E/com.tsaigee.demosdk.BookManagerService: onStart
2021-09-30 14:25:11.980 3323-3323/com.tsaigee.aidldemo E/com.tsaigee.demosdk.BookManagerService: onBind
2021-09-30 14:25:13.551 3323-3323/com.tsaigee.aidldemo E/com.tsaigee.demosdk.BookManagerService: onUnbind
服务的启停
和启动Activity一样,我们通过Intent可以简单的控制服务的开始和停止,或者说是创建和销毁。
//Serivce,注意:通过Android Studio New的Service可以在AndroidManifest.xml自动注册
public class MyService extends Service {
private static final String TAG = MyService.class.getName();
public MyService() {
super();
}
@Override
public void onCreate() {
Log.e(TAG, "onCreate: ");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG, "onStartCommand: ");
return super.onStartCommand(intent, flags, startId);
}
@Override
public IBinder onBind(Intent intent) {
Log.e(TAG, "onBind: ");
return null;
}
@Override
public boolean onUnbind(Intent intent) {
Log.e(TAG, "onUnbind: ");
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
Log.e(TAG, "onDestroy: ");
super.onDestroy();
}
}
//Activity
public class MainActivity extends AppCompatActivity {
@Override
public void onCreate() {
...
//声明Intent
Intent intent = new Intent(this,MyService.class);
//开启服务,若服务第一次开启则会走服务的onCreate,否则走onStartCommand,log看上节末尾
startService(intent);
...
//销毁服务
stopService(intent);
}
}
绑定服务
如果我们用startService(new Intent)的话,服务是被开启了,但是Activity和服务好像各玩各的没什么联系,为了给他俩创造联系系,安卓中还有一个绑定服务的方式。
学习绑定服务,需要了解下Binder。
Binder学习指南
Android进程间通信(IPC)机制Binder简要介绍和学习计划
上面两篇文章,假设你看完了第一个,那么你应该对于Binder有一个大致的了解:
- 通常意义下,Binder指的是一种通信机制;我们说AIDL使用Binder进行通信,指的就是Binder这种IPC机制。
- 对于Server进程来说,Binder指的是Binder本地对象。
- 对于Client来说,Binder指的是Binder代理对象,它只是Binder本地对象的一个远程代理;对这个Binder代理对象的操作,会通过驱动最终转发到Binder本地对象上去完成;对于一个拥有Binder对象的使用者而言,它无须关心这是一个Binder代理对象还是Binder本地对象;对于代理对象的操作和对本地对象的操作对它来说没有区别。
- 对于传输过程而言,Binder是可以进行跨进程传递的对象;Binder驱动会对具有跨进程传递能力的对象做特殊处理:自动完成代理对象和本地对象的转换。
AIDL我们会在文末进行简单的介绍。
使用绑定服务,我们需要在Service中(也就是Server端)创建一个Binder对象,当Activity(Client端)绑定服务时,Service将返回这个Binder对象;Activity或获得这个Binder对象后通过调用该对象内的方法进行跨进程操作。
纸上谈来终觉浅,看下代码吧:
//服务端
public class MyService extends Service {
private final String TAG = MyService.class.getName();
private MyBinder myBinder;
public MyService() {
}
//定义了一个Binder类
public class MyBinder extends Binder {
private final String TAG = MyBinder.class.getName();
void outLog() {
Log.e(TAG, "outLog: Hello World~!");
}
}
@Override
public IBinder onBind(Intent intent) {
//绑定服务时传递Binder对象
if (myBinder == null) {
myBinder = new MyBinder();
}
return myBinder;
}
@Override
public boolean onUnbind(Intent intent) {
Log.e(TAG, "onUnbind: ");
return super.onUnbind(intent);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.e(TAG, "onDestroy: ");
}
}
//在客户端(比如一个Activity),定义一个ServiceConnection对象获取Binder对象
private final ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
if (!isConnect) {
Log.e(TAG, "onServiceConnected: Service connected successfully");
mMyBinder = (MyService.MyBinder) iBinder;
isConnect = true;
}
else {
Log.e(TAG, "onServiceConnected: Service has been already connected" );
}
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
Log.e(TAG, "onServiceDisconnected: ");
isConnect = false;
}
};
启动服务:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//按下按钮,绑定服务
bindServiceButton.setOnClickListener(view -> {
Intent intent = new Intent(this, MyService.class);
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
});
//调用Binder对象中的方法
outLogButton.setOnClickListener(view -> {
if (mMyBinder != null) {
mMyBinder.outLog();
}
});
}
- 输出Log
**通过log可以看到绑定服务时调用lServiceConnection的onServiceConnected
方法获取Binder对象,而后就可以调用Binder对象中的方法了。**
...MainActivity: onServiceConnected: Service connected successfully
...MyService$MyBinder: outLog: Hello World~!
...MyService: onUnbind:
...MyService: onDestroy:
- Demo
服务绑定Demo
评论 (0)