Android四大组件之Service
来源:互联网 发布:h.323端口 编辑:程序博客网 时间:2024/05/23 16:17
一、Service是什么
相信做android开发的同学们都或多或少的接触过Service,作为Android的四大组件之一,service主要使用在处理后台任务(即不依赖于UI界面),或者去执行一个需要长期运行的任务,譬如说播放音乐,下载等都可以放在service中做。service相对于activity来说,最大了区别在于,它处于后台运行,没有UI界面,当然你也可以将他与Notification一起使用,将service从后台转到前台。
二、Service的生命周期
Service和Activity一样具有生命周期。首先我们来看看Service的使用方法。
//service需要在AndroidManifest.xml中注册public class AidlService extends Service{ public AidlService() { } @Override public IBinder onBind(Intent intent) { return null; } @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(); } @Override public boolean onUnbind(Intent intent) { return super.onUnbind(intent); }}
在上述的代码中,我们发现了与Activity生命周期相似的函数。毫无疑问,这就是Service的生命周期。其实Service的生命周期函数没有Activity与Fragment那么多。由上面代码可知主要包括onCreate,onStartCommand,onBind,onUnbind,onDestroy。那么是不是每一次启动Service都会执行这几个周期函数呢?其实不是,这与如何启动service有关。
Context.startService()
startService的作用是启动一个service,启动后这个service与当前的调用者(Activity,BroadCast等)没有关联,调用者将不知道service的运行情况,即使当前调用者退出,service也可以一直运行下去,直到调用stopServiceS(),或者stopSelf()函数。内存不足,也将优先回收后台进程。这种情况下,生命周期的执行步骤是onCreate()–onStartCommand()–onDestroy()。但如果启动的这个Servicer已经存在了,那么将不会执行onCreate()函数,只会执行onStartCommand()。
Intent intent=new Intent(MainActivity.this,AidlService.class); startService(intent);
Context.bindService()
bindService()如它的名字来说是将调用者与服务绑定在一起,当调用者退出时,绑定的Service也将跟着销毁。因为调用者与服务绑定在一块,因此调用者可以知道服务的运行情况,并且能够与Service进行通信。这时候生命周期的执行为onCreate()–onBind()–onUnbind–onDestroy()。如果service以及存在,上述生命周期都不会再执行。
而且bindService也可以进行跨进程的通信。通过AIDL远程调用另一个进程中的Service,并得到另一个Service中的的信息。
Intent intent=new Intent(MainActivity.this,AidlService.class);//bindService()一共有三个参数,第一个为Intent,第二个是ServiceConnection,这个需要自己创建,重写他的onServiceConnected()方法和onServiceDisconnected()方法,在onServiceConnected()函数中将得到service中onBindi函数中返回的IBinder,通过这个来与Service进行通信。第三个参数为标志位。bindService(intent,mServiceConnection,BIND_AUTO_CREATE);private ServiceConnection mServiceConnection=new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { } @Override public void onServiceDisconnected(ComponentName name) { } };
注意:如果你先startService再bindService或者先bindService再startService。那么单独的调用stopService和unbindService都将不会将service销毁,只用两个同时调用才能够销毁service。
三、对Service的误解
很多时候有人会想,同样是用来执行后台任务,同样是用来执行耗时任务,那么Service与Thread是不是一样呢?什么时候选择Service,什么时候又选择Thread呢?其实Service与Thread没有关系,Service更像Activity,因为Service与Activity都是运行在主线程中的,而Thread是重新开启一个子线程。而且注意!!!在service中不能够执行耗时的操作,如果超过20秒,将会报ANR。看到ANR是不是很熟悉,没错在Activity中如果执行耗时任务也会出现ANR。因此在Service的使用时一般会结合Thread一起使用,这样只要service存在那么线程也将运行,而且service不受Activity的销毁的影响,保证了耗时任务执行成功。
四、IntentService的使用
如果每次使用Service都去新创建一个Thread执行耗时任务,这样难免有些愚蠢,并且Thread与Service的通信也需要自己来完成。Android为我们提供了一个叫IntentService的类。它继承了Service,并且在内部包含了Thread和Handler。用户可以直接使用这个类来完成耗时的操作。
如何使用IntentService
public class MyIntentService extends IntentService{ public MyIntentService() { super("MyIntentService"); } @Override public void onCreate() { super.onCreate(); } @Override public int onStartCommand(@Nullable Intent intent, int flags, int startId) { return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); } @Override protected void onHandleIntent(Intent intent) { //执行耗时操作,该方法运行在工作线程中,而不是在主线程中。 //执行网络操作等。 }}
由上面代码可以看到比service多了一个 onHandleIntent()方法。这个方法就是用来执行耗时操作的地方。它不是运行在主线程中,所以不会造成ANR。值得注意的是IntentService在执行完onHandleIntent()函数中的代码后,intentService将自己销毁掉自己,不会像service一样需要手动结束,不会一直运行下去。
其实查看IntentService源码,你会发现里面也只是运用了Thread与Handler。
private final class ServiceHandler extends Handler { public ServiceHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { onHandleIntent((Intent)msg.obj); stopSelf(msg.arg1); } }public void onCreate() { super.onCreate(); //HandlerThread是一个Thread,在它的run方法中,声明了一个Looper。 HandlerThread thread = new HandlerThread("IntentService[" + mName + "]"); //线程开启 thread.start(); //将service中的looper赋值给ServiceHandler,因此ServiceHandler在发出Message后,会在 HandlerThread的run方法中取出消息。而重写的ServiceHandler的handleMessage方法,将会得到执行。而且我们发现ServiceHandler的handleMessage中有一个 onHandleIntent((Intent)msg.obj);这便是需要我们在继承IntentService时重写的。 mServiceLooper = thread.getLooper(); mServiceHandler = new ServiceHandler(mServiceLooper); } @Override public void onStart(@Nullable Intent intent, int startId) { //发送Message后,将会在HandlerThread的run方法中取出。 Message msg = mServiceHandler.obtainMessage(); msg.arg1 = startId; msg.obj = intent; mServiceHandler.sendMessage(msg); }
如果不是很明白IntentService的工作方式,建议先了解一下Handler机制。
五、结语
service在android开发中十分重要,我对它的理解其实也停留在很粗浅的层面。希望读者有什么观点,或者文章有什么错误,欢迎指正。
- Android四大组件之 Service
- Android四大组件之 Service
- Android四大组件之 Service
- android四大组件之Service
- android四大组件之Service
- android四大组件之Service
- Android四大组件之Service
- Android四大组件之service
- Android四大组件之Service
- Android四大组件之 Service
- Android四大组件之Service
- Android四大组件之Service
- Android四大组件之service
- Android四大组件之Service
- Android四大组件之Service
- android四大组件之Service
- android四大组件之Service
- Android 四大组件之 Service
- strcmp在不同系统/编译器下的结果不同
- 系统测试流程
- SSM项目——列表删除功能实现
- 浅谈单片机应用程序架构
- java基础(11)- java的输入/输出(IO)包(1)
- Android四大组件之Service
- Android 大小两个Surface切换
- hibernate配置
- 机器学习(5)Bagging和Boosting 概念及区别
- IntelliJ Idea 常用快捷键列表
- C# json 序列化 匿名对象序列号 指定对象序列化
- STM32L152 基本定时器使用学习
- 【论文阅读笔记】Deepr: A Convolutional Net for Medical Records
- VisualSVN Server的配置和使用方法【服务器端】