Handler(四)-使用

Android知识总结

一、HandlerThread

HandlerThread是Thread的子类,严格意义上来说就是一个线程,只是它在自己的线程里面帮我们创建了Looper,使Handler的Message消息在子线程处理。

  • 1) 方便使用:a. 方便初始化,b,方便获取线程looper
  • 2)保证了线程安全

而我们要使用子线程中的Looper的方式是怎样的呢?看下面的代码

Thread thread = new Thread(new Runnable() {
  Looper looper;
  @Override
  public void run() {
    Log.d(TAG, "click2: " + Thread.currentThread().getName());
    Looper.prepare();
    looper =Looper.myLooper();
    Looper.loop();
 }
  public Looper getLooper() {
    return looper;
 }
});
thread.start();
Handler handler = new Handler(thread.getLooper());

上面这段代码有没有问题呢?

  • 1)在初始化子线程的handler的时候,我们无法将子线程的looper传值给Handler,解决办法有如下办法:
    a. 可以将Handler的初始化放到 Thread里面进行
    b. 可以创建一个独立的类继承Thread,然后,通过类的对象获取。
  • 2)依据多线程的工作原理,我们在上面的代码中,调用 thread.getLooper() 的时候,此时的looper可能还没有初始化,此时是不是可能会挂掉呢?

这两种办法都可以,但是,这个工作 HandlerThread帮我们完成了。

    //创建Looper
    @Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            //notifyAll(); 放到这里也是可以的,都是唤醒 wait() 是其拿到锁后在执行
            mLooper = Looper.myLooper();
            notifyAll(); //此时唤醒其他等待的锁,使其处于就绪态
            //在这里会使 其他引用 wait() 的线程处于就绪状态,
            //等 notifyAll() 这边释放锁后,wait() 获取锁在执行
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }

    //获取Looper
    public Looper getLooper() {
        if (!isAlive()) {
            return null;
        }
        
        synchronized (this) {
            //这边用 while 循环,主要是因为此处的 wait() 可能被其他地方的 notifyAll() 唤醒,
            //此时这个线程的 mLooper == null,再次进行等待被唤醒。
            while (isAlive() && mLooper == null) { //主要解决线程并发时 wait() 被唤醒和 wait() 异常唤醒的问题。
                try {
                    wait();//当mLooper==null时,进入阻塞状态,并释放线程锁
                } catch (InterruptedException e) {
                }
            }
        }
        return mLooper;
    }
 
    public boolean quit() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quit();    //退出hander发送消息
            return true;
        }
        return false;
    }

wait()/ notifyAll()的原理见Java基础-线程和进程(二)

二、IntentService

在Android开发中,我们或许会碰到这么一种业务需求,一项任务分成几个子任务,子任务按顺序先后执行,子任务全部执行完后,这项任务才算成功。那么,利用几个子线程顺序执行是可以达到这个目的的,但是每个线程必须去手动控制,而且得在一个子线程执行完后,再开启另一个子线程。或者,全部放到一个线程中让其顺序执行。这样都可以做到,但是,如果这是一个后台任务,就得放到Service里面,由于Service和Activity是同级的,所以,要执行耗时任务,就得在Service里面开子线程来执行。那么,有没有一种简单的方法来处理这个过程呢,答案就是IntentService。

IntentService是继承于Service并处理异步请求的一个类,在IntentService内有一个工作线程来处理耗时操作,启动IntentService的方式和启动传统Service一样,同时,当任务执行完后,IntentService会自动停止,而不需要我们去手动控制。另外,可以启动IntentService多次,而每一个耗时操作会以工作队列的方式在IntentService的onHandleIntent回调方法中执行,并且,每次只会执行一个工作线程,执行完第一个再执行第二个,以此类推。

  • 1)、原理
    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);
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        //创建HandlerThread
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

        mServiceLooper = thread.getLooper();
        //创建Handler
        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);
    }

    //处理消息
    @WorkerThread
    protected abstract void onHandleIntent(@Nullable Intent intent);

    //停止服务
    public final void stopSelf(int startId) {
        if (mActivityManager == null) {
            return;
        }
        try {
            mActivityManager.stopServiceToken(
                    new ComponentName(this, mClassName), mToken, startId);
        } catch (RemoteException ex) {
        }
    }

IntentService运用了HandlerThread来获取Looper,然后通过Handler来发送消息。

  • 2)、实现

实现IntentService

public class IntentServiceDemo extends IntentService {  
  
    public IntentServiceDemo() {  
        //必须实现父类的构造方法  
        super("IntentServiceDemo");  
    }  
      
    @Override  
    public IBinder onBind(Intent intent) {  
        System.out.println("onBind");  
        return super.onBind(intent);  
    }  
  
  
    @Override  
    public void onCreate() {  
        System.out.println("onCreate");  
        super.onCreate();  
    }  
  
    @Override  
    public void onStart(Intent intent, int startId) {  
        System.out.println("onStart");  
        super.onStart(intent, startId);  
    }  
  
  
    @Override  
    public int onStartCommand(Intent intent, int flags, int startId) {  
        System.out.println("onStartCommand");  
        return super.onStartCommand(intent, flags, startId);  
    }  
  
  
    @Override  
    public void setIntentRedelivery(boolean enabled) {  
        super.setIntentRedelivery(enabled);  
        System.out.println("setIntentRedelivery");  
    }  
  
    @Override  
    protected void onHandleIntent(Intent intent) {  
        //Intent是从Activity发过来的,携带识别参数,根据参数不同执行不同的任务  
        String action = intent.getExtras().getString("param");  
        if (action.equals("oper1")) {  
            System.out.println("Operation1");  
        }else if (action.equals("oper2")) {  
            System.out.println("Operation2");  
        }  
          
        try {  
            Thread.sleep(2000);  
        } catch (InterruptedException e) {  
            e.printStackTrace();  
        }  
    }  
  
    @Override  
    public void onDestroy() {  
        System.out.println("onDestroy");  
        super.onDestroy();  
    }  
  
}  

在Activity里面使用

public class TestActivity extends Activity {  
    /** Called when the activity is first created. */  
    @Override  
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
          
        //可以启动多次,每启动一次,就会新建一个work thread,但IntentService的实例始终只有一个  
        //Operation 1  
        Intent startServiceIntent = new Intent("com.test.intentservice");  
        Bundle bundle = new Bundle();  
        bundle.putString("param", "oper1");  
        startServiceIntent.putExtras(bundle);  
        startService(startServiceIntent);  
          
        //Operation 2  
        Intent startServiceIntent2 = new Intent("com.test.intentservice");  
        Bundle bundle2 = new Bundle();  
        bundle2.putString("param", "oper2");  
        startServiceIntent2.putExtras(bundle2);  
        startService(startServiceIntent2);  
    }  
} 

在AndroidManifest.xml里面进行注册:

          
              
                  
              
          
  • 3)、总结
  • 1、可用于执行后台耗时的任务,任务执行后会自动停止。
  • 2、具有高优先级,适合高优先级的后台任务,且不容易被系统杀死。
  • 3、可以多次启动,每个耗时操作都会以工作队列的方式在IntentService的onHandleIntent回调方法中执行

三、Glide 生命周期管理

  //用于缓存fragment
  final Map pendingSupportRequestManagerFragments = new HashMap<>();

  @NonNull
  private SupportRequestManagerFragment getSupportRequestManagerFragment(
      @NonNull final FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
    //尝试通过tag,从FragmentManager中获取绑定的fragment
    SupportRequestManagerFragment current =
        (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
    if (current == null) {
      //尝试冲Map缓存中获取fragment
      current = pendingSupportRequestManagerFragments.get(fm);
      if (current == null) {
        current = new SupportRequestManagerFragment(); 
        current.setParentFragmentHint(parentHint);
        if (isParentVisible) {
          current.getGlideLifecycle().onStart();
        }
         //添加fragment到缓存map中
        pendingSupportRequestManagerFragments.put(fm, current);
        fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
//把fragment从map中移出,原理是Handler里面的消息是一个队列,obtainMessage放在commitAllowingStateLoss 添加的事务之后,
//可以是Handler先处理绑定Fragment的事务在处理移出Fragment的事务。从而保证不多次创建Fragment。
       handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
      }
    }
    return current;
  }

从上面代码可见看出避免Glide#with()多次调用,多次创建fragment。使用pendingSupportRequestManagerFragmentsMap缓存的作用是:

Glide.with(context).load(url).into(mImageView);
Glide.with(context).load(url).into(mImageView);
Glide.with(context).load(url).into(mImageView);

当出现上面情况的时候,我们可以知道当执行commitAllowingStateLossFragmentFragmentManager绑定的时候,实际上是通过Handler#post()发送事务进行绑定,过程如下:

BackStackRecord继承FragmentTransaction,然后在BackStackRecord处理事务。BackStackRecord#commitAllowingStateLoss 然后调用BackStackRecord#commitInternal 方法

    @Override
    public int commitAllowingStateLoss() {
        return commitInternal(true);
    }

    int commitInternal(boolean allowStateLoss) {
        if (mCommitted) throw new IllegalStateException("commit already called");
        if (FragmentManager.isLoggingEnabled(Log.VERBOSE)) {
            Log.v(TAG, "Commit: " + this);
            LogWriter logw = new LogWriter(TAG);
            PrintWriter pw = new PrintWriter(logw);
            dump("  ", pw);
            pw.close();
        }
        mCommitted = true;
        if (mAddToBackStack) {
            mIndex = mManager.allocBackStackIndex();
        } else {
            mIndex = -1;
        }
       //调用FragmentManager,添加事务到队列中
        mManager.enqueueAction(this, allowStateLoss);
        return mIndex;
    }

然后调用FragmentManager#enqueueAction,最后调用FragmentManager#scheduleCommit方法,让后通过Hander的发送和处理事务。

    void enqueueAction(@NonNull OpGenerator action, boolean allowStateLoss) {
        if (!allowStateLoss) {
            if (mHost == null) {
                if (mDestroyed) {
                    throw new IllegalStateException("FragmentManager has been destroyed");
                } else {
                    throw new IllegalStateException("FragmentManager has not been attached to a "
                            + "host.");
                }
            }
            checkStateLoss();
        }
        synchronized (mPendingActions) {
            if (mHost == null) {
                if (allowStateLoss) {
                    // This FragmentManager isn't attached, so drop the entire transaction.
                    return;
                }
                throw new IllegalStateException("Activity has been destroyed");
            }
            mPendingActions.add(action);
            //提交事务
            scheduleCommit();
        }
    }

    void scheduleCommit() {
        synchronized (mPendingActions) {
            boolean postponeReady =
                    mPostponedTransactions != null && !mPostponedTransactions.isEmpty();
            boolean pendingReady = mPendingActions.size() == 1;
            if (postponeReady || pendingReady) {
                mHost.getHandler().removeCallbacks(mExecCommit);
                //通过Hander发送消息处理事务
                mHost.getHandler().post(mExecCommit);
                updateOnBackPressedCallbackEnabled();
            }
        }
    }

当Hanler处理好Fragment和FragmentManager绑定。就通过收到Handler的消息(Handler#ID_REMOVE_SUPPORT_FRAGMENT_MANAGER)来释放Map的内存,避免内存泄露。

  @Override
  public boolean handleMessage(Message message) {
    boolean handled = true;
    Object removed = null;
    Object key = null;
    switch (message.what) {
      case ID_REMOVE_FRAGMENT_MANAGER:
       //移出fragment
        android.app.FragmentManager fm = (android.app.FragmentManager) message.obj;
        key = fm;
        removed = pendingRequestManagerFragments.remove(fm);
        break;
      case ID_REMOVE_SUPPORT_FRAGMENT_MANAGER:
        FragmentManager supportFm = (FragmentManager) message.obj;
        key = supportFm;
        //释放内存
        removed = pendingSupportRequestManagerFragments.remove(supportFm);
        break;
      default:
        handled = false;
        break;
    }
    if (handled && removed == null && Log.isLoggable(TAG, Log.WARN)) {
      Log.w(TAG, "Failed to remove expected request manager fragment, manager: " + key);
    }
    return handled;
  }

你可能感兴趣的:(Handler(四)-使用)