Service
概念
后台组件,没有界面,进行一些耗时操作
生命周期
startService
startService()--->onCreate()--->onStartCommand()--->stopService()--->onDestory()
bindService
bindService()--->onCreate()--->onBind()--->connection--->onUnbind()--->onDestory()
方法
onBind()
启动状态和绑定状态下都要重写的方法,但是在启动状态下,直接返回null值
当一个组件调用bindService()与服务绑定,系统就调用此方法,在这个方法中,必须返回一个IBinder接口的实现类,供客户端用来与服务进行通信
onStartCommand()
使用startService()请求启动服务时,调用此方法,一旦执行,服务即会启动并可在后台无限期运行,如果自己实现,则需要在工作完成后,通过调用stopSelf()或stopService()来停止
启动方式
startService
Intent intent = new Intent(MainActivity.this,MyService.class);
startService(intent);
stopService(intent);
bindService
拓展Binder类
概念
应用和服务处于同一应用和进程中,不执行任何跨进程编组
实现
bindService()—>onBind()返回binder实例—>onServiceConnected()获取Service实例—>可调用其公共方法
步骤
1.创建BindService服务端(MyService.java),继承自Service并在类中创建一个实现IBinder接口的实例对象(内部类MyBinder),创建公共方法(getCount)以便给客户端调用
2.从onBind()回调方法中返回Binder实例
3.在客户端中,绑定服务bindService(),从onServiceConnected()回调方法接收Binder,即可调用其公共方法(myServie.getCount())
客户端
private ServiceConnection connection = new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name,IBinder service){
MyService.MyBinder binder = (MyServie.MyBinder) service;
myService = binder.getService();
}
@Override
public void onServiceDisconnected(ComponentName name){
myService = null;
}
};
Intent intent = new Intent(MainActivity.this,MyService.class);
case R.id.bind_service:
bindService(intent);
break;
case R.id.unbind_service:
if(myService!=null){
myService = null;
unbindService(intent);
}
break;
case R.id.get_data:
if(myService != null){
Log.i(TAG,"count is: " + myService.getCount());
}else{
Log.i(TAG,"no connection with service");
}
服务端
public MyBinder extends Binder{
MyService getService(){
return MyService.this;
}
}
private MyBinder binder = new MyBinder();
public IBinder onBind(Intent intent){
return binder;
}
public int getCount(){
return count;
}
Messenger
不同进程间通信,使用Messenger服务提供通信接口,使用handler进行消息处理
Context.BIND_AUTO_CREATE与Service.BIND_AUTO_CREATE的区别
没有区别,因为Service.BIND_AUTO_CREATE调用的其实是Context.BIND_AUTO_CREATE
步骤
服务端发送给客户端
1.客户端bindService()绑定服务
bindService(intent,connection,Context.BIND_AUTO_CREATE);
2.创建服务端(MessengerService.java),构建内部类(IncomingHandler)继承自Handler,用来处理客户端发送的消息
class IncomingHandler extends Handler{
@Override
public void handleMessage(@NonNUll Message msg){
switch(msg.what){
case MSG_SAY_HELLO:
Log.i(TAG,"Service had received message!");
break;
default:
super.handleMessage(msg);
}
}
}
2.实例化Messenger对象,并在onBind()方法中返回给客户端一个Messenger底层的Binder
final Messenger mMessenger = new Messenger(new IncomingHandler());
@Override
@Nullable
public IBinder onBind(Intent intent){
return mMessenger.getBinder();
}
3.客户端onServiceConnected()回调方法构造出与服务端进行交互的Messenger对象
connection = new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName name,IBinder service){
mService = new Messenger(service);
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName name){
mService = null;
mBound = false;
}
}
4.创建与服务端交互的消息实例Message
public void sayHello(View v){
if(!mBound) return;
Message msg = Message.obtain(null,MessengerService.MSG_SAY_HELLO,0,0);
try{
mService.send(msg);
}catch(RemoteException e){
e.printStackTrace();
}
}
5.模拟不同进程之间通信
<service
android:name=".Service.MessengerService"
android:process=":remote"
/>
服务端回应客户端
1.在服务端新建Messenger对象,并采用对应消息的msg.replyTo初始化
Messenger client = msg.replyTo;
2.新建返回的消息Message对象
Message replayMsg = Message.obtain(null,MessengerService.MSG_SAY_HELLO);
3.新建返回的数据Bundle
Bundle bundle = new Bundle();
bundle.putString("replay","I have received message from you!");
4.将bundle和message绑定
replayMsg.setData(bundle);
5.发送消息
try{
client.send(replayMsg);
}catch(RemoteException e){
e.printStackTrace();
}
注
1.一个服务可以绑定多个客户端,但是,系统仅在第一个客户端绑定时调用服务的onBind()方法,此后的绑定,只会返回已存在的IBinder对象
2.不要在onResume和onPause方法中绑定服务和取消绑定,因为生命周期转换调用最频繁
启动状态和绑定状态的转换
先绑定后启动
以绑定状态运行,再以启动状态运行,就会转换为启动状态,即只有在收到停止服务命令(stopSelf/stopService)或内存不足时才会销毁该服务
先启动后绑定
仍然会以启动状态运行
结论
1.启动状态级别比绑定状态高
2.如果服务要执行耗时操作,需要另开线程来完成,因为服务是运行在主线程中,不会创建自己的线程,也不会创建新的进程(除非有指定)
AIDL
待定