Android:IntentService的学习

Android的四大组件中,Service排行老二,在Android中的主要作用是后台服务,进行与界面无关的操作。由于Service运行在主线程,所以进行异步操作需要在子线进行。为此Android为我们提供了IntentService
IntentService是一个抽象类,继承至Service,主要方便我们新建工作线程进行异步操作。提交任务到IntentService时,异步任务以串行方式进行处理,意味着工作线程一次只处理一个任务。而且当所有任务都完成之后,会自动停止Service,不需要我们手动停止。

IntentService 的使用

  1. 我们定义DownloadService类并继承至IntentService。来模拟网络下载的过程。
public class DownloadService extends IntentService {

    private static int count = 0;

    /**
     * 主要用于调用服务类构造器
     *
     * @param name 用于区分不同任务
     */
    public DownloadService(String name) {
        super(name);
    }

    /**
     * AndroidManifest.xml配置清单需要配置
     *
     * @param
     */
    public DownloadService() {
        super("action");
    }

    /**
    *主要重写该方法,在该方法内进行异步操作。
    **/
    @Override
    protected void onHandleIntent(Intent intent) {
        Log.i("Download", "onHandleIntent" + count);
        count++;

        String name = intent.getStringExtra("action");

        if (name.equals("download")) {
            for (int i = 0; i < 5; i++) {

                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    return;
                }

                Log.i("Download", "download:" + count);
            }
        }
    }
    //以下方法的重写,仅仅为了打印日志
    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.i("Download", "onDestroy");

    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i("Download", "onCreate");
    }

    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);

        Log.i("Download", "onStart");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("Download", "onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }
}

  1. 在AndroidManifest.xml配置DownloadService
<service android:name=".DownloadService"/>
  1. 在MainActivity类中循环调用Service,启动多循环任务。
 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Intent intent=new Intent(this,DownloadService.class);
        for (int i =0;i<3;i++){

            intent.putExtra("action","download");
            intent.putExtra("count",""+i);
            startService(intent);

        }
    }
  1. 运行结果
2376425-7785680aac2f9d82
image

分析:
从运行结果知道,IntentService在运行多个任务情况下,只调用一次onCreate,调用多次onStartCommand,跟Service的生命周期一致。但,只有在运行完download:1之后才会去运行download:2,接着是download:3。最后所有任务结束后会自动调用onDestroy,停止服务。在这里需要注意的是,和Service并不同,Service需要我们手动停止服务。对于结果的回调,可以采用接口回调,广播,EventBus

那么,IntentService是如何在Service中实现异步操作和串行处理任务的呢?

IntentService内部实现

  1. 查看IntentService的onCreate方法
 @Override
    public void onCreate() {
        super.onCreate();
        //分析一
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

        mServiceLooper = thread.getLooper();
        分析二
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

分析一

HandThread继承Thread,通过start方法创建工作线程,内部建立Looper来达到消息循环,通过Hanlder消息机制来达到串行的效果和处理多任务。HandThreadHandler消息机制,可以另外查看文章。

分析二

ServiceHandler继承Handler,与普通的Handler并没有区别,在其内容处理handleMessage。即调用IntentServiceonHandleIntent

  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);
        }
    }
  1. 那么,当我们在Activity中重复调用startService方法时,只会多次调用onStartCommand方法,并不会重复调用onCreate方法。我们看看onStartComamnd方法的实现。
    @Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

可以看得出,调用了onStart方法了。而onStart方法只是将我们的Intent包装成Message,通过Handler发送出去,并在Handler中进行处理,调用我们的onHandleIntent。进而调用我们实现onHandleIntent的代码。

    @Override
    public void onStart(@Nullable Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }

总结

IntentService并没有什么的新的技术含量,在了解HandlerTread和Handler的消息机制下,对Handler+Thread+Service作一个封装,更适合我们后台进行异步耗时操作的场景。有效避免通过new多个Thread

猜你喜欢

转载自blog.csdn.net/weixin_34355715/article/details/90824897
今日推荐