IntentService源码解析与HandlerThread在Android框架上的使用

很好用的两个东西,知其然知其所以然

首先注意:服务并不是一个新的进程,启动的应用程序在哪个进程,服务就在哪个进程

-IntentService作为Service的升级版,增加了在服务中使用线程的能力,而Service其实的在主线程中运行的,耗时操作的话还是会引起ANR,IntentService的好处就不言而喻了,不仅能处理耗时操作,而且优先级还比线程高,同时服务执行完成后还会自动停止。接下来我们从源码角度去探究下这些功能如何实现。

首先打开IntentService
源码不多我就全贴出来:

  • 首先可以看到是继承自Service
  • 然后内部包裹了一层HandlerThread
  • 创建服务的同时把handler与HandlerThread 绑定
    任务就会在HandlerThread 中执行

注意:任务是在MessageQueue中被Looper不断的取出来由Handler去执行的
所以一次只能执行一个任务,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);
        }
// onHandleIntent在这里处理任务信息,处理完了后调用stopSelf服务就自动停止了
        @Override
        public void handleMessage(Message msg) {
            onHandleIntent((Intent)msg.obj);
//这里要注意,不是说一个请求结束后,服务就停止了,因为可能service会接收到新的启动请求,stopSelf有个参数startId,跟最后启动该service时生成的ID相等时才会执行停止服务。
            stopSelf(msg.arg1);
        }
    }
    public IntentService(String name) {
        super();
        mName = name;
    }

    public void setIntentRedelivery(boolean enabled) {
        mRedelivery = enabled;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        // 可以看到在服务创建的时候,这里创建了HandlerThread,并且把一个Handler和这个HandlerThread绑定了起来(通过传入线程的Looper)

        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) {
    //每次调用startService都会调用这个方法,于是消息就会被发送到ServiceHandler那里去处理,就是个HandlerThread 线程了
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

    // 销毁服务的时候退出循环,其实就是结束了这个线程
    @Override
    public void onDestroy() {
        mServiceLooper.quit();
    }

    @Override
    @Nullable
     // 这个是用来和Activity通信的
    public IBinder onBind(Intent intent) {
        return null;
    }
    @WorkerThread
    protected abstract void onHandleIntent(@Nullable Intent intent);
}

顺便写一下HandlerThread的使用方式

  HandlerThread handlerThread = new HandlerThread("name");
  // 开启start就是把HandlerThread 内部的Looper启动起来,详见下方源码
  handlerThread.start();
  // 接下来只要把循环器对象给Handler 就可以完成绑定了
  // 不然默认Handler是用主线程的Looper,当然如果是更新UI,我们可以在线程中用这个handler发送消息,然后handler的回调方法会在主线程中运行,就能实现异步请求更新UI了
  Handler handler = new Handler(handlerThread.getLooper());
  // 这里发消息就会把任务发送处理队列,Looper会不断取出Runnable交由Handler处理
  handler.post(new Runnable() {
            @Override
            public void run() {

            }
        });

HandlerThread 继承Thread,内部有一个Looper,调用start()会启动这个循环器

    @Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }

Service和Activity的通信

还记得Service中的那个onBind()方法吗,我们需要让它返回一个IBinder对象,并在Activity中拿到这个对象

// Service中创建一个内部类
  public class DownLoadBinder extends Binder{
        public void startDownLoad(){
            System.out.println("=====startDownLoad()=====");
        }
        public void getProgress(){
            System.out.println("=====getProgress()=====");
        }
    }

// 这个方法返回
  public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        System.out.println("=====onBind=====");
        return downLoadBinder;
    }

在Activity中这样调用

 private ServiceConnection connection=new ServiceConnection() {
        /**
         * 服务解除绑定时候调用
         */
        @Override
        public void onServiceDisconnected(ComponentName name) {
            // TODO Auto-generated method stub

        }
        /**
         * 绑定服务的时候调用
         */
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            // TODO Auto-generated method stub
            //myService=((DownLoadBinder) service).
            downLoadBinder=(DownLoadBinder) service;
            /*
             * 调用DownLoadBinder的方法实现参数的传递
             */
            downLoadBinder.startDownLoad();
            downLoadBinder.getProgress();
        }
    };

接下来就简单了,调用绑定服务方法

Intent bindIntent = new Intent(this, MyService.class);
// 第三个参数是一个标记,表明一旦建立绑定就创建服务,会执行onCreate,但不会执行OnStartCommand
bindService(bindIntent, connection, BIND_AUTO_CREATE);

// 记得要关闭
  unbindService(connection);

关于服务关闭的问题:
只调用bindService和unbindService可以启动/关闭服务(没有调用startService)
但是如果调用了startService和bindService那么关闭服务就必须同时调用stopService和unbindService

猜你喜欢

转载自blog.csdn.net/superman4933/article/details/79676853