IntentService源码分析

接触过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.apk
05-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

你可能感兴趣的:(android)