将高级service开发简单化
来源:互联网 发布:淘宝店铺退款怎么退款 编辑:程序博客网 时间:2024/05/18 01:01
作为Android四大组件之一,各位大咖已经将service的外衣扒得体无完肤了,但是为什么还要来炒冷饭呢?这是十大未解之谜之一。我不管,看完本篇博文,你将学会以下内容(敲黑板!!!!)且看:
摘要
service即服务,隐形的,不可见的。为什么Google会把service作为四大组件之一呢?看看我国的四大产业架构,再看看Android的架构,你就会明白,服务业是必不可少的一大产业,它与人们的生活息息相关。没有服务,你找谁做饭(别说有女票,有女票也得自己做),你怎么出行?(好吧,身为程序员,我编不下去了~~),总之,service是灰常重要滴!!!!!有了service你可以边玩游戏边听歌,还能下载电影,不瞎扯,上干(gou)粮!!
一、service 的生命周期
service的生命周期很简单,就那么几个常用的:onCreate、onStartCommand,onBind、onUnbind、onDestroy,是不是很简单?在oncreate方法里面完成任务的初始化工作,在onBind获取整个service的实例(稍后讲解),在unBind方法将service解除绑定,在onDestroy方法里面将资源回收,完美!(额外再说一下,oncreate方法只在service没启动的时候走,onstartCommand是每一次startService都会调用,onBind只会在没有绑定的时候调用,同理onUnBind也只会调用一次,再次调用会报没有注册service的错, OnDestroy也只会走一次),如图,其中MyService是我们的service,ServiceView是一个activity
如果是直接绑定一个service,其生命周期为onCreate(),onBind(),unBind(),onDestroy(),与直接启动service还是有点区别的,直接绑定一个service,默认不走onStartCommand()方法的,并且在解除绑定时候,service直接被destroy掉,不需要我们额外的stopService。
至于service能不能执行耗时操作,我就上一张图好了,显然service与宿主activity是同一个thread
二、service的启动
启动service与启动一个activity是一样一样的只要两行(其实一行就就可以启动)代码:
Intent serviceInt = new Intent(this, MyService.class); startService(serviceInt);关闭service只要一行代码,不能再少了,除非砸手机
stopService(serviceInt);当然,上面的做法是不负责任的表现,就像女票一样,追到手了不能不管他呀!你还需要管理他的事务,与他沟通,说白了就是要与service成为同一条船上的蚂蚱。于是就有下面的操作:
Intent serviceInt = new Intent(this, MyService.class); bindService(serviceInt, connet, Service.BIND_AUTO_CREATE);将当前activity与service绑定在一起,他们就在一起了。该bindService方法中第一个参数就是一个Intent,与上面一致,第二个是一个ServiceConnection接口,我们通过该接口获取service的实例,第三个就是启动的标志,我们常说的,某某某在此立下flag,启动不了service誓不罢休。当service启动成功了,就会回调我们传进去的接口,来看看怎么实现这个接口
private MyService myService; private ServiceConnection connet = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { myService = ((MyService.LocalBinder) service).getService(); } @Override public void onServiceDisconnected(ComponentName name) { } };现在大家能想象MyService长什么样么?估计泥萌猜出来了,对,就是这样
public class MyService extends Service { private final IBinder mBinder = new LocalBinder(); @Override public void onCreate() { super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); } public class LocalBinder extends Binder { public MyService getService() { Log.i(TAG, "getService: "); return MyService.this; } } @Nullable @Override public IBinder onBind(Intent intent) { return mBinder; } @Override public boolean onUnbind(Intent intent) { return super.onUnbind(intent); } @Override public void sendBroadcast(Intent intent) { super.sendBroadcast(intent); } @Override public boolean stopService(Intent name) { return super.stopService(name); }}我们重写了onBind方法并返回Binder的子类LocalBinder,我们可以在activity通过这个子类来获取service的实例,然后我们想让service干嘛就干嘛了~~比如让它自取灭亡
myService.stopService(serviceInt);就看你怎么玩了~~
三、activity与service通信之一(Binder)
获取binder如上,不再赘述,上面我们通过重写Binder获取service的实例,然后activity就可以通过该实例与service进行通信了,那么,service怎么与activity通信呢?很简单,就按照常见的手法——接口,我们就定义一个接口获得service启动后的生命周期,定义如下
public interface ServiceLiftCycle { void onCreate(); void onStartCommand(); void onBind(); void unBind(); void onDestory(); void onStopService();}修改一下service
public class MyService extends Service { private final IBinder mBinder = new LocalBinder(); public ServiceLiftCycle myServiceLiftCycle ; public void setServiceLiftCycle(ServiceLiftCycle listener){ this.myServiceLiftCycle = listener; } @Override public void onCreate() { super.onCreate(); if(myServiceLiftCycle != null) myServiceLiftCycle.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { if (myServiceLiftCycle != null) myServiceLiftCycle.onStartCommand(); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); if (myServiceLiftCycle != null) myServiceLiftCycle.onDestory(); } public class LocalBinder extends Binder { public MyService getService() { return MyService.this; } } @Nullable @Override public IBinder onBind(Intent intent) { return mBinder; } @Override public boolean onUnbind(Intent intent) { if (myServiceLiftCycle != null) myServiceLiftCycle.unBind(); return super.onUnbind(intent); } @Override public void sendBroadcast(Intent intent) { super.sendBroadcast(intent); } @Override public boolean stopService(Intent name) { if (myServiceLiftCycle != null) myServiceLiftCycle.onStopService(); return super.stopService(name); }}实现ServiceLiftCycle 接口
private class MyServiceLiftCycle implements ServiceLiftCycle { @Override public void onCreate() { Log.i(TAG, "onCreate:-------------- "); } @Override public void onStartCommand() { Log.i(TAG, "onStartCommand: --------------"); } @Override public void onBind() { Log.i(TAG, "onBind: --------------"); } @Override public void unBind() { Log.i(TAG, "unBind: --------------"); } @Override public void onDestory() { Log.i(TAG, "onDestory: --------------"); } @Override public void onStopService() { Log.i(TAG, "onStopService: --------------"); } }ServiceConnection修改如下
private MyService myService; private ServiceConnection connet = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { myService = ((MyService.LocalBinder) service).getService(); myService.setServiceLiftCycle(new MyServiceLiftCycle()); } @Override public void onServiceDisconnected(ComponentName name) { unbind = true; } };这样就可以在activity里面监听到service的生命周期了,当然,是activity与service绑定后的了,毕竟在绑定前myServiceLiftCycle为null的,这里只是提供一个思路,怎么玩就看各位看官了,总之,binder加上接口就可以实现一般业务的需求。什么?对binder不了解?没事,广播总有了解吧?四大组件之二!!!
四、activity与service的通信之二(broadcast)
身为四大猛将之一,大家对这个包租婆(高音喇叭)应该有了解。如有不了解的,请出去左拐,看看其他大神的巨作~~我们重新创建一个servicepublic class BroadCastService extends Service{ private String TAG = "BroadCastService"; public static final String SERVICE_INTENTFILTER = "com.android.broadcastService.intentFilter."; @Override public void onCreate() { super.onCreate(); Log.i(TAG, "onCreate: "); IntentFilter filter = new IntentFilter (); filter.addAction(SERVICE_INTENTFILTER); registerReceiver(MyReceiver ,filter); } boolean isSend = false; BroadcastReceiver MyReceiver = new BroadcastReceiver(){ @Override public void onReceive(Context context, Intent intent) { Log.i(TAG, "onReceive: 我收到来自activity那个傻蛋的消息了"); Intent intent1 = new Intent(ACTIIVTY_INTENTFILTER); sendBroadcast(intent1); Log.i(TAG, "onReceive: 我转发消息给activity了"); } }; @Override public void onDestroy() { super.onDestroy(); unregisterReceiver(MyReceiver); } @Nullable @Override public IBinder onBind(Intent intent) { return null; }}在activity加如下代码
public static final String ACTIIVTY_INTENTFILTER = "com.android.broadcastActivity.intentFilter."; public void service(View view) { Log.i(TAG, "service: "); Intent serviceInt = new Intent(this, BroadCastService.class); startService(serviceInt); IntentFilter filter = new IntentFilter (); filter.addAction(ACTIIVTY_INTENTFILTER); registerReceiver(receiver ,filter); } activityReceiver receiver = new activityReceiver(); class activityReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { Log.i(TAG, "onReceive: 我收到service发来的消息了"); } };
public void send(View view) { Intent intent1 = new Intent(SERVICE_INTENTFILTER); sendBroadcast(intent1); Log.i(TAG, "service: 我发消息给service了");}
结果如下
五、activity与service的通信之三(messenger)
有些时候需要在service中执行繁重的任务,如果直接在应用所在的进程创建,容易导致crash,这时候我们为service创建新的进程,在配置文件上修改如下:
<service android:name=".service.MessengerService" android:process=":MessengerService"/>
这个时候activity与service之间的通信再用第一种方式显然不行,毕竟跨进程了。用上面的广播可以实现跨进程通信,但有些时候并不希望其他应用也能截获广播,这时候可以考虑使用messenger来实现activity与service的通信问题我们创建新的service对象:
public class MessengerService extends Service{ private String TAG = "MessengerService "; public int mValue = 0; public static final int MSG_REGISTER_CLIENT = 1; public static final int MSG_UNREGISTER_CLIENT = 2; public static final int MSG_SET_VALUE = 3; public ArrayList<Messenger> mClients = new ArrayList<Messenger>(); class mServiceHandler extends Handler { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_REGISTER_CLIENT: Log.i(TAG, "handleMessage: 我收到了 MSG_REGISTER_CLIENT"); mClients.add(msg.replyTo); break; case MSG_UNREGISTER_CLIENT: mClients.remove(msg.replyTo); break; case MSG_SET_VALUE: Log.i(TAG, "handleMessage: 我收到了 MSG_SET_VALUE "); mValue = msg.arg1; for (int i=mClients.size()-1; i>=0; i--) { try { mClients.get(i).send(Message.obtain(null, MSG_SET_VALUE, mValue, 0)); } catch (RemoteException e) { mClients.remove(i); } } break; default: super.handleMessage(msg); } } } final Messenger mServiceMessenger = new Messenger(new mServiceHandler()); @Override public void onCreate() { super.onCreate(); } @Override public void onStart(Intent intent, int startId) { super.onStart(intent, startId); } @Override public int onStartCommand(Intent intent, int flags, int startId) { return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); Toast.makeText(this, R.string.cancel , Toast.LENGTH_SHORT).show(); } @Nullable @Override public IBinder onBind(Intent intent) { return mServiceMessenger.getBinder(); } @Override public boolean onUnbind(Intent intent) { return super.onUnbind(intent); }}
修改activity的内容
boolean mIsBound = false; Messenger mServiceMes = null; class mClientHandler extends Handler { @Override public void handleMessage(Message msg) { switch (msg.what) { case MessengerService.MSG_SET_VALUE: Log.i(TAG, "handleMessage: 我收到来自遥远的service端的消息了"); break; default: super.handleMessage(msg); } } } final Messenger mClientMessenger = new Messenger(new mClientHandler()); private ServiceConnection mMesConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { mIsBound = true; Messenger mServiceMes = new Messenger(service);//获取MessengerService 里面的Messenger try { Message msg = Message.obtain(null, MessengerService.MSG_REGISTER_CLIENT); msg.replyTo = mClientMessenger; mServiceMes.send(msg); msg = Message.obtain(null, MessengerService.MSG_SET_VALUE, this.hashCode(), 0); mServiceMes.send(msg); } catch (RemoteException e) { } Toast.makeText(ServiceView.this, "远程service已经连接上", Toast.LENGTH_SHORT).show(); } public void onServiceDisconnected(ComponentName className) { Log.i(TAG, "onServiceDisconnected: MessengerService"); mServiceMes = null; Toast.makeText(ServiceView.this, "断开连接", Toast.LENGTH_SHORT).show(); } }; public void bindMesService(View view){ bindService(new Intent(ServiceView.this, MessengerService.class), mMesConnection, Context.BIND_AUTO_CREATE); }
MessengerService端收到的消息
这里面涉及到三个知识:messenger,message,handler。messenger充当信息员,负责实现跨进程通信,即把message从本地进程携带到远程进程,message就是一个信封,里面包含了通信的信息,handler就是收信人,读取从messenger邮寄过来的message
先说client端(activity端)
在接口ServiceConnection的onServiceConnected方法里面我们拿到了远程的IBinder对象(准确的说IBinder是一个接口,将所有跨进程通信类都抽象出来了),我们通过IBinder对象获取到远程service端的messenger这样。我们就可以通过这个messenger对象向远程service 发消息了。首先,我们在client端拿到messenger
public void onServiceConnected(ComponentName className, IBinder service) { Messenger mServiceMes = new Messenger(service);//获取MessengerService 里面的Messenger }然后构建一个message对象,让mServiceMes 对象将message发送给service端
Message msg = Message.obtain(null, MessengerService.MSG_REGISTER_CLIENT); mServiceMes.send(msg);各位看官不免会有疑问,系统怎么知道mServiceMes发送message到哪里呢?且慢,喝口茶。
接着来
把刚刚的问题放一边。
在service端,我们先创建一个handler,即收件人,与我们平常创建的handler大同小异
class mServiceHandler extends Handler { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_REGISTER_CLIENT: Log.i(TAG, "handleMessage: 我收到了 MSG_REGISTER_CLIENT"); mClients.add(msg.replyTo); break; } } }
然后我们通过这个handler来唯一创建一个mServiceMessenger ,表明该mServiceMessenger发送的所有消息,都会由该handler来处理,这下问题明了了
final Messenger mServiceMessenger = new Messenger(new mServiceHandler());
接着,我们重写service端的Onbind方法,把mMessenger的IBinder返回给client端
@Nullable @Override public IBinder onBind(Intent intent) { return mServcieMessenger.getBinder(); }
通过上面的代码,我们就可以很顺利的拿到了service端的mMessengermServiceMessenger ,这样,我们在client端就可以通过messengermServiceMes 来给service端发消息了。
说完client端,我们再来看看service端是怎么获取到client端的messenger
细心的看官也许已经发现了,且看
同样,我们首先在client端创建一个handler对象
class mClientHandler extends Handler { @Override public void handleMessage(Message msg) { switch (msg.what) { case MessengerService.MSG_SET_VALUE: Log.i(TAG, "handleMessage: 我收到来自遥远的service端的消息了"); break; default: super.handleMessage(msg); } } }
与service端一样,通过handler创建唯一的messenger
final Messenger mClientMessenger = new Messenger(new mClientHandler());
这样,只要是mClientMessenger 发消息,我们的mClientHandler都可以处理(也只有他能处理),问题来了,我们在绑定service端的时候可以通过ServiceConnection回调里面的方法来获取一个Ibinder ,从而获取service端的messenger,那么service端是怎么获取client端的messenger的呢?
我们注意到下面两行代码
Message msg = Message.obtain(null, MessengerService.MSG_REGISTER_CLIENT); msg.replyTo = mClientMessenger;
这里,我们把在client端创建的mClientMessenger作为一个回复,返回给service端,就可以通过service端的mServiceHandler对象来拿到这个mClientMessenger,这里,我们用到ArrayList来保存client端的messenger,因为service可能对应多个client端
public ArrayList<Messenger> mClients = new ArrayList<Messenger>(); class mServiceHandler extends Handler { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_REGISTER_CLIENT: Log.i(TAG, "handleMessage: 我收到了 MSG_REGISTER_CLIENT"); mClients.add(msg.replyTo); break; } } }
这样,service端也就顺利的拿到了client端的mClientMessenger对象,这样就意味着我们也可以在service端对client端发消息了
mClients.get(i).send(Message.obtain(null, MSG_SET_VALUE, mValue, 0));需要解除绑定,只需要调用该方法
unbindService(mMesConnection);如果service端用list维护着多个messenger,client端还需要通知service解除messenger
Message msg = Message.obtain(null, MessengerService.MSG_UNREGISTER_CLIENT); msg.replyTo = mClientMessenger; mServiceMes.send(msg);service端将messenger解除即可
case MSG_UNREGISTER_CLIENT: mClients.remove(msg.replyTo); break;
至此,已经顺利打通了client端与service端的跨进程通信问题,框架已经打好,至于怎么玩出花样,且看下回分解
阅读全文
1 0
- 将高级service开发简单化
- Unity3D开发简单化
- asp.net简单化开发工-----Web Martix
- Android快速开发控件---简单化的RecyclerView
- Android高级开发第四讲--API之Service
- Service高级进阶
- 委托与事件使用精简案例—将复杂问题简单化
- service开发
- IntentService和Service高级应用
- 将Tomcat Service化
- 失效分析有感-怎样有效的将各种复杂的问题简单化,同时又能不失去相互的联系
- [Axis2与Eclipse整合开发Web Service系列之一] 生成Web Service Client(将WSDl 转化成 Java代码)
- Axis Web Service开发之旅 (三) --将Spring的装配JavaBean发布成WebService
- Axis Web Service开发之旅 (三) --将Spring的装配JavaBean发布成WebService
- KISS--简单化20060809
- KISS--简单化20060809
- 复杂面试简单化
- 简单化搭建 Docker 数据中心
- Nginx反向代理实现负载均衡总结
- Mongodb从0到1系列三: 条件查询、大小写
- js动态改变css样式
- threeSum
- 最简单的模拟spring容器例子
- 将高级service开发简单化
- 关于代码审查的一点想法
- Python2与Python3中的list异同
- 09基于对象编程风格
- HDU
- kali linux 下python3.6.2+pip3配置安装
- HDU-6039 Gear Up(线段树+DFS序)
- HDU6053-TrickGCD 容斥原理+莫比乌斯反演
- 《大话数据结构》第三章 线性表