IntentService 从使用到源码分析
来源:互联网 发布:mac系统电脑玩英雄联盟 编辑:程序博客网 时间:2024/06/07 13:54
1. 基本使用
1.1 什么是IntentService
IntentService是继承于Service并处理异步请求的一个类,在IntentService内有一个工作线程来处理耗时操作,启动IntentService的方式和启动传统Service一样,同时,当任务执行完后,IntentService会自动停止,而不需要我们去手动控制。另外,可以启动IntentService多次,而每一个耗时操作会以工作队列的方式在IntentService的onHandleIntent回调方法中执行,并且,每次只会执行一个工作线程,执行完第一个再执行第二个,以此类推。
所有请求都在一个单线程中,不会阻塞应用程序的主线程(UI Thread),同一时间只处理一个请求。
1.2 IntentService 的好处
- 自动开启线程处理耗时任务.
- 操作完成时自动销毁Service.
1.3 基本使用
- 创建
IntentService
的子类.
/** * @author : Brian */public class MyIntentService extends IntentService { private static final String TAG = "MyIntentService"; /** * 默认构造 */ public MyIntentService(){ this("MyIntentService"); } /** * 父类构造方法 */ public MyIntentService(String name) { super(name); } @Override protected void onHandleIntent(@Nullable Intent intent) { Log.d(TAG, "onHandleIntent: "); String opType = intent.getExtras().getString("param"); // 分辨任务 Log.d(TAG, "任务 : " + opType); // 延时 3s SystemClock.sleep(3 * 1000); } /** * Unless you provide binding for your service, * you don't need to implement this method, * because the default implementation returns null. */ @Nullable @Override public IBinder onBind(Intent intent) { Log.d(TAG, "onBind: "); return super.onBind(intent); } /** * Called by the system when the service is first created. */ @Override public void onCreate() { Log.d(TAG, "onCreate: "); super.onCreate(); } /** * Called by the system to notify a Service that * it is no longer used and is being removed. */ @Override public void onDestroy() { Log.d(TAG, "onDestroy: "); super.onDestroy(); } /** * You should not override this method for your IntentService. */ @Override public int onStartCommand(@Nullable Intent intent, int flags, int startId) { Log.d(TAG, "onStartCommand: "); return super.onStartCommand(intent, flags, startId); } /** * Sets intent redelivery preferences. */ @Override public void setIntentRedelivery(boolean enabled) { Log.d(TAG, "setIntentRedelivery: "); super.setIntentRedelivery(enabled); }}
- 在
AndroidMenifest.xml
中注册Service
<!-- 注册Intent Service --><service android:name="com.brain.interview.intent_service.MyIntentService"> <intent-filter> <action android:name="com.brain.intentservice"/> </intent-filter></service>
- 编写测试代码
/** * 启动 */public void startIntentService1() { // 操作一 Intent intent = new Intent(); intent.setAction("com.brain.intentservice"); intent.setPackage(getPackageName()); Bundle bundle = new Bundle(); bundle.putString("param", "打球"); intent.putExtras(bundle); startService(intent); // 操作二 Intent intent2 = new Intent(); intent2.setAction("com.brain.intentservice"); intent2.setPackage(getPackageName()); Bundle bundle2 = new Bundle(); bundle2.putString("param", "吃饭"); intent2.putExtras(bundle2); startService(intent2);}
- 输出
onCreate: onStartCommand: onStartCommand: onHandleIntent: 任务 : 打球onHandleIntent: 任务 : 吃饭onDestroy:
从输出可以看出, 在执行完所有的任务后, 销毁了Service.
2. 源码分析
IntentService 源码并不复杂其实, 就是封装了 Handler + ThreadHandler
2.1 HandlerThread
普通的Thread主要用于进行耗时操作.HandlerThread内部常见了消息队列,外界需要通过Handler的消息方式通知HandlerThread来执行一个任务.由于HandlerThread的run() 是一个无限循环(Looper.loop()),因此当明确不需要时需要主动调用,quit() 或者 quitSafely() 来终止线程的执行.
HandlerThread 的run方法的源码如下 :
@Overridepublic void run() { mTid = Process.myTid(); // 创建和当前线程绑定的Looper对象 Looper.prepare(); // 保存当前线程的Looper的一个引用 synchronized (this) { mLooper = Looper.myLooper(); notifyAll(); } Process.setThreadPriority(mPriority); // 使用者,可以重写这个方法进行消息循环开启前的设置. onLooperPrepared(); // 开启消息循环 Looper.loop(); mTid = -1;}
HandlerThread的好处就是他带有Looper, 不用我们手动开启Looper, 有了Looper我们就可以绑定Handler了
2.2 IntentService
- 首先在来看
onCreate()
方法
@Overridepublic void onCreate() { // TODO: It would be nice to have an option to hold a partial wakelock // during processing, and to have a static startService(Context, Intent) // method that would launch the service & hand off a wakelock. super.onCreate(); // 创建一个 HandlerThread 并启动, HandlerThread 内部维护这一个Looper. // 可以利用这个Looper来使用Handler机制.. HandlerThread thread = new HandlerThread("IntentService[" + mName + "]"); thread.start(); // 保存Looper的引用, 便于在Service退出时.退出Looper mServiceLooper = thread.getLooper(); // 创建Handler mServiceHandler = new ServiceHandler(mServiceLooper);}
- 首先创建了一个HandlerThread对象, 并且启动了该对象.
- 然后保存了HandlerThread中的Looper对象的一个引用, 便于在IntentService销毁时对出Looper. 否则该子线程将会一直运行.
- 创建了一个Handler和创年的HandlerThread绑定在一起.
通过上面的三步就实现了. 一个可以接收msg的Handler, 并且在绑定的子线程中执行消息处理.之后我们只需要通过Handler发送消息, 通过Intent传送数据就可以实现在子线程中处理数据了.
- 再看,Service每次启动都会调用的
onStartCommand()和onStart()
方法,主要看onStart
@Overridepublic void onStart(@Nullable Intent intent, int startId) { // 发送消息.切换线程执行, 将Service的startId 发送过去, 便于stop Service Message msg = mServiceHandler.obtainMessage(); msg.arg1 = startId; msg.obj = intent; mServiceHandler.sendMessage(msg);}
我们可以看出在onStart()
中的实现也是十分简单, 就是通过之前创建的Handler发送了一个消息.将intent数据发送过去, 同时还携带了一个参数startId . 之所以要携带这个id是因为在Handler中需要调用stopSelf()方法来停止Service, (下面的话有点通俗) 只有当所有的startdid都stop了, Service才会真正的退出.
- 再来看, Handler的实现
private final class ServiceHandler extends Handler { public ServiceHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { // 这个方法需要使用者实现.字节的逻辑, 在子线程中执行 onHandleIntent((Intent)msg.obj); // 这个方法不会立即将Service结束掉, 会等到所有的onStart // 注意1 : msg.arg1中保存的Service的startId stopSelf(msg.arg1); }}
- 首先会调用
onHandleIntent(intent)
方法,并将数据传送进去.onHandleIntent(intent)
方发是一个虚方法需要子类实现, 使用者的业务逻辑也是写在这个方法中的, 前面说过改Handler是和创建的HandlerThread对象的Looper绑定在一起的因此,次方法在子线程中执行. - 当
onHandleIntent(intent)
方法执行完后, 就会调用stopSelf(msg.arg1)
, 通过前面的分析可知msg.arg1 中存放给的是startId. 当所有的startId都被stop后Service也就结束了.
- 继续
onDestroy()
方法
@Overridepublic void onDestroy() { // Service 烧毁时, 退出线程 mServiceLooper.quit(); super.onDestroy();}
Service结束后, 对于Service中启动的子线程是没有影响的.在这HandlerThread中有Looper因此不会自动退出, 需要手动调用quit方法.
IntentService注释版本代码如下
/** * @author : Brian * @date : 2017/6/29 */public abstract class IntentService extends Service { private static final String TAG = "IntentService"; /** * HandlerThread中获取的Looper, 便于在Service销毁时,退出线程. */ private volatile Looper mServiceLooper; /** * 该Handler和HandlerThread的Looper线程绑定在一起, * 也就是说会在那个线程中执行消息处理. */ private volatile ServiceHandler mServiceHandler; /** * 线程名称 */ private String mName; private boolean mRedelivery; /** * Handler */ private final class ServiceHandler extends Handler { public ServiceHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { // 这个方法需要使用者实现.字节的逻辑, 在子线程中执行 onHandleIntent((Intent)msg.obj); // 这个方法不会立即将Service结束掉, 会等到所有的onStart // 注意1 : msg.arg1中保存的Service的startId stopSelf(msg.arg1); } } /** * 子类构造方法调用 */ public IntentService(String name) { super(); mName = name; } /** * */ public void setIntentRedelivery(boolean enabled) { mRedelivery = enabled; } @Override public void onCreate() { // TODO: It would be nice to have an option to hold a partial wakelock // during processing, and to have a static startService(Context, Intent) // method that would launch the service & hand off a wakelock. super.onCreate(); // 创建一个 HandlerThread 并启动, HandlerThread 内部维护这一个Looper. // 可以利用这个Looper来使用Handler机制.. HandlerThread thread = new HandlerThread("IntentService[" + mName + "]"); thread.start(); // 保存Looper的引用, 便于在Service退出时.退出Looper mServiceLooper = thread.getLooper(); // 创建Handler mServiceHandler = new ServiceHandler(mServiceLooper); } @Override public void onStart(@Nullable Intent intent, int startId) { // 发送消息.切换线程执行, 将Service的startId 发送过去, 便于stop Service Message msg = mServiceHandler.obtainMessage(); msg.arg1 = startId; msg.obj = intent; mServiceHandler.sendMessage(msg); } /** * 每次启动Service都会调用这个方法. */ @Override public int onStartCommand(@Nullable Intent intent, int flags, int startId) { onStart(intent, startId); return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY; } @Override public void onDestroy() { // Service 烧毁时, 退出线程 mServiceLooper.quit(); } /** * Unless you provide binding for your service, you don't need to implement this * method, because the default implementation returns null. * @see android.app.Service#onBind */ @Override @Nullable public IBinder onBind(Intent intent) { return null; } /** * 这个方法在子线程中被调用, 同一时刻只会有一个Intent请求被处理. 在逻辑上处理过程 * 在一个独立的子线程中执行.一次如果这个方法中的处理时间太长就会阻塞在同一个IntentService * 发起的其他请求. 当所有的请求都处理结束后,IntentService会自动销毁. 因此不需要调用者 * 手动调用stopSelf()方法 */ @WorkerThread protected abstract void onHandleIntent(@Nullable Intent intent);}
- IntentService 从使用到源码分析
- IntentService 详解(从使用到源码撸一遍)
- 从源码分析IntentService
- IntentService 从源码分析
- IntentService使用及源码分析
- Android开发:IntentService使用(源码分析)
- Android IntentService的使用和源码分析
- Android IntentService的使用和源码分析
- Android中IntentService源码分析及其使用
- Android之IntentService使用及源码分析
- IntentService从源码解析
- IntentService源码分析
- IntentService源码分析
- IntentService源码分析
- IntentService源码分析
- IntentService源码分析
- IntentService源码分析
- IntentService源码分析
- servlet3.0新特性 Annotation注解配置
- 重写ImageView设置圆角
- 线程安全和可重入函数
- Fiddler的使用
- web开发所需注意优化性能细节
- IntentService 从使用到源码分析
- Android开发--开发调试Root权限的获取以及用adb 抓取log
- 66. Plus One
- <NOIP> 8 . P1035 级数求和
- 第六章 彩色图像处理
- space-vim IDE 编辑器
- 解决IllegalStateException: Can not perform this action after onSaveInstanceState
- 2017-06-30 oracle MERGE INTO 单表查询
- Android--自定义View加载网络图片,实现缩放,圆形剪裁