美文网首页
Android IntentService 源码解析

Android IntentService 源码解析

作者: SunnyGL | 来源:发表于2020-12-08 11:23 被阅读0次

    IntentService 是一种特殊的 Service,它继承了 Service 并且它是一个抽象类,因此必须创建它的子类才能使用 IntentService。IntentService 可用于执行后台耗时的任务,当任务执行结束后它会自动停止,同时由于 IntentService 是服务的原因,这导致它的优先级比单纯的线程要高很多,所以 IntentService 比较适合执行一些高优先级的后台任务,因为它优先级高不容易被系统杀死。

    一、源码剖析
    1. IntentService 是 Service 的子类,所以 IntentService 也是一个服务
    public abstract class IntentService extends Service {
        ······
    }
    
    2. IntentService 内部会创建 HandlerThread 和 Handler 实例,并将 HandlerThread 内的 Looper 作为 Handler 的 Looper,服务销毁时退出 Looper
    @Override
    public void onCreate() {
        super.onCreate();
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();
     
        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }
    
    @Override
    public void onDestroy() {
        mServiceLooper.quit();
    }
    
    3. 外部发送的事件会被依次传递到 Handler 中
    @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;
    }
    
    4. 在 Handler 内会调用 onHandleIntent 方法
    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);
        }
    }
    

    当 onHandleIntent 方法执行结束后,IntentService 会通过 stopSelf(int startId) 方法来尝试停止服务。这里之所以采用 stopSelf(int startId) 而不是 stopSelf() 来停止服务,那是因为 stopSelf() 会立刻停止服务,而这个时候可能还有其他消息未处理,stopSelf(int startId) 则会等待所有的消息都处理完毕后才终止服务。一般来说,stopSelf(int startId) 在尝试停止服务之前会判断最近启动服务的次数是否和 startId 相等,如果相等就立刻停止服务,不相等则不停止服务,这个策略可以从 AMS 的 stopServiceToken 方法的实现中找到依据。

    二、使用案例
    1. 继承 IntentService
    public class LocalIntentService extends IntentService {
    
        private static final String TAG = "LocalIntentService";
    
        public LocalIntentService() {
            super(TAG);
        }
    
        @Override
        protected void onHandleIntent(Intent intent) {
            String action = intent.getStringExtra("task_action");
            Log.d(TAG, "handle task: " + action);
            SystemClock.sleep(2000);
        }
    
        @Override
        public void onDestroy() {
            Log.d(TAG, "service destroyed");
            super.onDestroy();
        }
    }
    
    2. 调用
    Intent service = new Intent(this, LocalIntentService.class);
    service.putExtra("task_action", "TASK1");
    startService(service);
    service.putExtra("task_action","TASK2"); 
    startService(service);
    

    Log 日志:

    2020-12-08 13:18:43.606 D/LocalIntentService: handle task: TASK1
    2020-12-08 13:18:45.606 D/LocalIntentService: handle task: TASK2
    2020-12-08 13:18:47.608 D/LocalIntentService: service destroyed
    

    相关文章

      网友评论

          本文标题:Android IntentService 源码解析

          本文链接:https://www.haomeiwen.com/subject/anyfgktx.html