我们来看看android 上著名的一次性 Service IntentService ,IntentService 自带一个线程,内部使用 HandlerThread 提供多线程服务。android 里面除了 AsyncTask ,其他的多线程基本都是用的 handle 、 looper 消息来做的,IntentService 也不例外啊,这样我们更容易理解源码。

IntentService 的使用


IntentService 需要我们去继承,然后重写 onHandleIntent 方法,接受我们发送过来的参数

public class MyIntentService extends IntentService {    public MyIntentService(String name) {        super(name);    }    @Override    protected void onHandleIntent(@Nullable Intent intent) {        String value = intent.getExtras().getString("AAA");        if ("AAA".equals(value)) {            Log.d("AAA", Thread.currentThread().getName() + "接受到消息" + System.currentTimeMillis());        }    }}

UI 线程启动 IntentService 服务

Intent i = new Intent(this,MyIntentService.class);Bundle bundle = new Bundle();bundle.putString("taskName", "task1");i.putExtras(bundle);startService(i);

IntentService 因为里面用的也是 handle,looper 技术,所以也是可以接收多个消息的,我们可以多次执行上面的代码来穿参数给 IntentService 对象,此时会触发 IntentService 的 onStartCommand() 方法

翻翻源码吧


既然 IntentService 用的 handle,那么源码就不难理解了。

IntentService 声明的成员变量,可以看到有一个 looper 消息队列和给 looper 发送消息的 handle

public abstract class IntentService extends Service {private volatile Looper mServiceLooper;private volatile ServiceHandler mServiceHandler;private String mName;private boolean mRedelivery;

构造方法没干什么事

    public IntentService(String name) {        super();        mName = name;    }

onCreate 初始化函数

    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 thread = new HandlerThread("IntentService[" + mName + "]");        thread.start();        mServiceLooper = thread.getLooper();        mServiceHandler = new ServiceHandler(mServiceLooper);    }

onCreate 里面启动了一个 HandlerThread 的线程,然后用 HandlerThread 的 looper 构建了用于内部通信的 handle 出来

onStartCommand 函数会调用 onStart 函数,把 intent 作为参数包装成一个 message 消息,然后用这个内部通信的 handle ,把这个 message 发送到内部线程 HandlerThread 的消息队列里面去执行

    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {        onStart(intent, startId);        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;    }    public void onStart(@Nullable Intent intent, int startId) {        Message msg = mServiceHandler.obtainMessage();        msg.arg1 = startId;        msg.obj = intent;        mServiceHandler.sendMessage(msg);    }

然后我们来看看 IntentService 内部定义的这个用于信息通信的 handle 类型

    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);        }    }

我们可以看到 ServiceHandler 在接受到消息时会执行我们重写的 onHandleIntent 方法,在方法执行完成后,会尝试关闭当前所在服务,但是任务队列不为 null 的话是不会关闭服务的,这里就得去看 service 的源码了,stopSelf 是 service 提供的方法

这是 IntentService 的工作流程图


944365-fa5bfe6dffa531ce.png

IntentService 有人不建议用 bindService 启动,因为不会走 onStartcommand 函数,不会往内内部 HandlerThread 线程的消息队列里添加任务,需要我们自己手动添加。

最后了,感觉 IntentService 现在使用的场景很少啊, 也就看到有人用在版本更新上,但是要是需要对版本更新的后太 Service 有更多操作的话, IntentService 是不太适合的,自己写一个 Service 服务,然后在里面用 Rxjava 跑多线程任务要比 IntentService 灵活的多,还能用 binder 和 service 单向通信。

参考资料:


  • Android 多线程 解析:IntentService(含源码解析)

更多相关文章

  1. android 动画学习系列(一)
  2. Android消息机制
  3. Android子线程其实也可以刷新UI。。。。
  4. android 自定义通知消息设置背景色不生效,导致部分机型显示白色字
  5. android延迟进入主界面和点击按钮进入主界面代码
  6. Android(安卓)Audio System 之二:AudioFlinger
  7. Android(安卓)Bander设计与实现 - 设计篇
  8. OpenGL ES教程I之创建OpenGL视图(原文对照)
  9. Android架构组件WorkManager详解

随机推荐

  1. Android RadioGroup 设置默认值之后 Radi
  2. 微信ANDROID客户端-会话速度提升70%的背
  3. View类的XML属性、相关方法及说明
  4. Android(安卓)仿淘宝选中商品不同尺寸的
  5. [Android]Android FTP Server
  6. android fragment ontouch 事件
  7. 一次偶然机遇找到一个不错的关于Android
  8. Android锁屏 DevicePolicyManager介绍
  9. [Android] 如何查看当前分支
  10. Android:interpolator用法