Handler 应用

512 阅读4分钟

前言

这篇文章文章讲下Handler的一些其他方面的应用(HandlerThreadIntentServiceGlide 如何做到生命周期的控制),所以需要对Handler原理有一定的理解 。如果对原理不是很理解,可以补下Handler 源码解析这篇文章

HandlerThread

HandlerThreadThread的子类,就是一个线程,只是它在自己的线程里面帮我们创建了Looper

@Override
//线程start的时候会创建Looper
public void run() {
    mTid = Process.myTid();
    Looper.prepare();
    synchronized (this) {
        mLooper = Looper.myLooper();
        notifyAll();
    }
    Process.setThreadPriority(mPriority);
    onLooperPrepared();
    Looper.loop();
    mTid = -1;
}

//调用的线程可能会挂起线程,保证线程安全
public Looper getLooper() {
    if (!isAlive()) {
        return null;
    }
    
    // If the thread has been started, wait until the looper has been created.
    synchronized (this) {
        while (isAlive() && mLooper == null) {
            try {
              	//等待Looper创建
                wait();
            } catch (InterruptedException e) {
            }
        }
    }
    return mLooper;
}

我们可以看到上面两个方法中添加了同步锁机制,防止多线程操作中getLooper返回为null,确保了线程安全。

使用

HandlerThread thread = new HandlerThread();
thread.start();
//代码会阻塞等待Looper 返回
Handler handler = new Handler(thread.getLooper());
//发送消息
handler.send.......;

//退出循环
handler.getLooper().quit();
handler.getLooper().quitSafely();

HandlerThread 存在的意义

  1. 方便使用
    1. 方便初始化
    2. 方便其他线程获取线程Looper
  2. 保证了线程安全

IntentService

大家可能非常熟悉了,但是这里我还是要拿过来再讲讲,重点还是Handler。因为IntentServiceHandler的应用方面是个不错的例子。看代码

private final class ServiceHandler extends Handler {
    public ServiceHandler(Looper looper) {
        super(looper);
    }

    @Override
    public void handleMessage(Message msg) {
      	//5.处理任务
        onHandleIntent((Intent)msg.obj);
      	//6.根据 startId 结束service
        stopSelf(msg.arg1);
    }
}

@Override
public void onCreate() {
    super.onCreate();
  	//1.创建HanderThread 处理任务
    HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
    thread.start();
		//2.创建handler
    mServiceLooper = thread.getLooper();
    mServiceHandler = new ServiceHandler(mServiceLooper);
}

@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
  	//3.每次启动IntentService调用
    onStart(intent, startId);
    return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}

@Override
public void onStart(@Nullable Intent intent, int startId) {
  	//4.发送消息,并将当前启动的 startId 传过去
    Message msg = mServiceHandler.obtainMessage();
    msg.arg1 = startId;
    msg.obj = intent;
    mServiceHandler.sendMessage(msg);
}

@Override
public void onDestroy() {
  	//7.当所有所有startId 相关的任务都结束之后的 线程回收
    mServiceLooper.quit();
}

上面代码注释从第1步到第7步,我们看到IntentService帮我们维护了所有后台的任务。这些任务通过Handler机制按照先后顺序执行,并且自动维护IntentService生命周期

IntentService 存在的意义

  • 用于处理后台耗时的任务
  • 可以用于任务的拆分,一项任务拆分若干个子任务,子任务按照顺序先后执行。子任务执行完之后,这项任务才算完成
  • 管理好后台线程,保证只有一个线程处理工作,而且一个一个的完成任务,有条不紊的进行,直到所有任务完成,回收线程

Glide中的应用

Glide 相信大应该非常熟悉了,我们都知道Glide生命周期的控制(如果不了解,可以看下Glide相关文章的分析,跟LiveData 是同一个原理)是通过添加一个空的FragmentActivity 或者Fragment中,然后通过FragmentMannager管理Fragment的生命周期,从而达到生命周期的控制。下面是节选了Glide一段添加Fragment的代码:

private RequestManagerFragment getRequestManagerFragment(
    @NonNull final android.app.FragmentManager fm,
    @Nullable android.app.Fragment parentHint,
    boolean isParentVisible) {
  //1.通过FragmentManager获取 RequestManagerFragment,如果已添加到FragmentManager则返回实例,否则为空
  RequestManagerFragment current = (RequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
  if (current == null) {
    //2.如果fm里面没有则从map缓存里取
    current = pendingRequestManagerFragments.get(fm);
    if (current == null) {
      //3.第1和2步都没有,说明确实没创建,则走创建的流程
      current = new RequestManagerFragment();
      current.setParentFragmentHint(parentHint);
      if (isParentVisible) {
        current.getGlideLifecycle().onStart();
      }
      //4.将新创建的fragment 保存到map容器
      pendingRequestManagerFragments.put(fm, current);
      //5.发送添加fragment事务事件
      fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
      //6.发送remove 本地缓存事件
      handler.obtainMessage(ID_REMOVE_FRAGMENT_MANAGER, fm).sendToTarget();
    }
  }
  return current;
}

//跟上面那个方法唯一的区别是 这个是Fragment 的FragmentManager,上面的是Acitivity 的FragmentManager
private SupportRequestManagerFragment getSupportRequestManagerFragment(
    @NonNull final FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
  SupportRequestManagerFragment current =
      (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
  if (current == null) {
    current = pendingSupportRequestManagerFragments.get(fm);
    if (current == null) {
      current = new SupportRequestManagerFragment();
      current.setParentFragmentHint(parentHint);
      if (isParentVisible) {
        current.getGlideLifecycle().onStart();
      }
      pendingSupportRequestManagerFragments.put(fm, current);
      fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
      handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
    }
  }
  return current;
}

@Override
public boolean handleMessage(Message message) {
  boolean handled = true;
  Object removed = null;
  Object key = null;
  switch (message.what) {
    case ID_REMOVE_FRAGMENT_MANAGER:
      //7.移除缓存
      android.app.FragmentManager fm = (android.app.FragmentManager) message.obj;
      key = fm;
      removed = pendingRequestManagerFragments.remove(fm);
      break;
  		//省略代码...
  }
  //省略代码...
  return handled;
}


看了上面的代码,大家可能会有疑惑。

  • Fragment添加到FragmentManager为什么还要保存到map容器里(第4步)?
  • 判断Fragment是否已添加为啥还要从map容器判断(第2步),FragmentManager 去find 不就可以做到了吗?

其实答案很简单,学了Handler原理之后我们知道:就是在第5步执行完之后并没有将Fragment添加到FragmentManager(事件排队中),而是发送添加Fragment的事件。接下来我们看代码

//FragmentManagerImpl.java
void scheduleCommit() {
    synchronized (this) {
        boolean postponeReady =
                mPostponedTransactions != null && !mPostponedTransactions.isEmpty();
        boolean pendingReady = mPendingActions != null && mPendingActions.size() == 1;
        if (postponeReady || pendingReady) {
            mHost.getHandler().removeCallbacks(mExecCommit);
            mHost.getHandler().post(mExecCommit);
            updateOnBackPressedCallbackEnabled();
        }
    }
}

添加Fragment 最终会走到FragmentManagerImplscheduleCommit方法,我们可以看到他是通过Handler 发送事件。

这也就解释了为什么第5步执行完之后Fragment为什么没有立即添加到FragmentManager,所以需要Map缓存Fragment来标记是否有Fragment添加。再接着有了第6步发送移除Map缓存的消息,因为Handler处理消息是有序的。

总结

上面的几个列子可以充分说明了Handler应用的广泛,以及重要性。如果不理解Handler原理,也就无法理解代码的意图。