IntentService源码分析

来源:互联网 发布:淘宝全屏首页怎么做 编辑:程序博客网 时间:2024/05/22 08:04

接触过Android的同学都应该知道Service,Android四大组件之一嘛,应该都很熟悉了,咋一看IntentService那又是什么鬼呢?

其实IntentService也是一个Service,是用来处异步任务的,比如说下载一个文件,处理耗时操作,当任务处理完成后这个Service会自动关闭。那么为什么需要IntentService呢?我们知道Service虽然被大家经常说是后台服务,但是Service所运行的线程其实还是主线程,不能执行耗时操作,会出现ANR导致应用卡死的假象,给用户不好的体验。所以如果我们要在Service里面处理耗时操作那就要手动去开启一个线程,google为了方便我们,就开发了IntentService给我们解决了自己手动开启线程的问题。下面我将带领大家一起来分析下IntentService

IntentService的使用

下面简单的模拟一个文件下载的操作,比如我们应用中经常使用到软件更新,当检测到软件更新的时候,自动下载apk,然后安装,这个场景最适合使用IntentService,因为下载apk的Service是一次性的,下载完成后就没必要存在可。所以我们新建一个UpdateService.java,代码如下:

package com.wms.github.intentservice;import android.app.IntentService;import android.content.Intent;import android.support.annotation.Nullable;import android.util.Log;/** * Created by 王梦思 on 2017/5/26. */public class UpdateService extends IntentService {    private static final String TAG = "UpdateService";    public UpdateService(String name) {        super(name);    }    public UpdateService() {        super("");    }    @Override    protected void onHandleIntent(@Nullable Intent intent) {        Log.e("UpdateService","onHandleIntent...");        if (intent != null) {            String path = intent.getStringExtra("apkFilePath");            downloadApk(path);        }    }    private void downloadApk(String path) {        Log.e("UpdateService",path);        //模拟耗时操作,这里就不真的下载文件了        try {            Thread.sleep(5000);        } catch (InterruptedException e) {            e.printStackTrace();        }        //这里代码执行完成后,Service就停止了    }    @Override    public void onCreate() {        super.onCreate();        Log.e(TAG, "onCreate...");    }    @Override    public void onDestroy() {        super.onDestroy();        Log.e(TAG, "onDestroy...");    }}

MainActivity.java代码如下:

package com.wms.github.intentservice;import android.content.Intent;import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.view.View;/** * Created by 王梦思 on 2017/5/26. */public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        findViewById(R.id.start_service).setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Intent intent = new Intent(MainActivity.this, UpdateService.class);                intent.putExtra("apkFilePath","http://www.baidu.com/apk/demo.apk");                startService(intent);            }        });    }}

布局文件activity_main.xml代码如下:

<?xml version="1.0" encoding="utf-8"?><RelativeLayout    xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context="com.wms.github.intentservice.MainActivity">    <Button        android:id="@+id/start_service"        android:layout_width="match_parent"        android:layout_height="50dp"        android:layout_centerInParent="true"        android:text="下载apk"/></RelativeLayout>

当我们点击下载apk按钮的时候,则会开启UpdateService,先看下UpdateService执行的时候的日志。

05-26 10:39:42.573 21936-21936/com.wms.github.intentservice E/UpdateService: onCreate...05-26 10:39:42.574 21936-22017/com.wms.github.intentservice E/UpdateService: onHandleIntent...05-26 10:39:42.575 21936-22017/com.wms.github.intentservice E/UpdateService: http://www.baidu.com/apk/demo.apk05-26 10:39:42.575 21936-22017/com.wms.github.intentservice E/UpdateService: 正在下载安装包...05-26 10:39:47.576 21936-22017/com.wms.github.intentservice E/UpdateService: 安装包下载完成...05-26 10:39:47.581 21936-21936/com.wms.github.intentservice E/UpdateService: onDestroy...

分析下UpdateService的执行顺序,顺序依次是onCreate–>onHandleIntent–>执行任务代码–>onDestroy,所以我们一般的处理异步任务的逻辑都是在onHandleIntent里面去做的,当这里面的任务逻辑处理完成后,服务就自动销毁了,将不会占用任何的系统资源。

通过上面的简单分析,相信大家已经知道IntentService是怎么使用的,但是我们要作为一个合格的程序员,应该知其然知其所以然,下面将从源码的角度来分析下IntentService。

源码分析IntentService

由于IntentService源码比较简单,我索性把他的源码贴出来,方便查看,这里我将注释都去掉了:

public abstract class IntentService extends Service {    private volatile Looper mServiceLooper;    private volatile ServiceHandler mServiceHandler;    private String mName;    private boolean mRedelivery;    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 IntentService(String name) {        super();        mName = name;    }    public void setIntentRedelivery(boolean enabled) {        mRedelivery = enabled;    }    @Override    public void onCreate() {        super.onCreate();        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");        thread.start();        mServiceLooper = thread.getLooper();        mServiceHandler = new ServiceHandler(mServiceLooper);    }    @Override    public void onStart(@Nullable Intent intent, int startId) {        Message msg = mServiceHandler.obtainMessage();        msg.arg1 = startId;        msg.obj = intent;        mServiceHandler.sendMessage(msg);    }    @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() {        mServiceLooper.quit();    }    @Override    @Nullable    public IBinder onBind(Intent intent) {        return null;    }    @WorkerThread    protected abstract void onHandleIntent(@Nullable Intent intent);}

可以看出IntentService的代码其实也就不到100行,还是很简单的。
当我们开启服务的时候,第一个执行的方法是onCreate方法,所以我们看下IntentService的onCreate方法里面创建了一个HandlerThread,HandlerThread其实就是一个继承Thread的类,只不过里面给我们新建了一个Looper。然后实例化了mServiceHandler,其实就是一个包含了Looper的Handler,我们一般创建一个Handler的时候都没有传递Looper,其实默认就是传递了主线程的Looper,这个主线程的Looper是在哪里创建的呢?其实是在我们应用开启的时候ActivityThread.java中的main方法里面创建的。这里扯远了,就不多说了。

当onCreate执行完成之后,就会调用onStart方法,在onStart方法里面创建了一个消息对象,通过onCreate实例化的mServiceHandler发送一个消息,这时候就会调用到IntentService 中静态内部类ServiceHandler的handleMessage方法,我们所说的onHandleIntent就是在handleMessage里面,onHandleIntent是一个抽象方法,所以这就是为什么我们继承IntentService的时候为什么需要重新onHandleIntent方法了。

当onHandleIntent执行完成之后,我们回到上面所说的handleMessage方法内部,在onHandleIntent下面还有一行代码就是stopSelf(),stopSelf就是停止当前的Service,这也就是为什么我们的异步任务处理完成后Service会自动停止了。

当Service停止时,就会调用onDestroy方法咯,整个流程到这里就讲解清楚了。总结一下,其实ItentService没什么神奇的地方,就是结合了Handler + Looper + Messeage来完成的,这个其实我们早就滚瓜烂熟了。

代码传送门:http://github.com/wms1993/blog_intentservice_demo

原创粉丝点击