Android asynchronous message processing mechanism

Android asynchronous messaging commonly used summary

android commonly divided into asynchronous frame handler, AsyncTask, handlerThread, IntentService.

What is the handler

Android upper interface mechanism message, sent and processed by the associated Message Object, and corresponds to Runnable thread MessageQueue.

1. 可以让对应的Message和Runnable在未来的某个时间点进行相应的处理。
    1. 让自己想要处理的耗时操作放在子线程,让更新ui放在主线程。
复制代码

handler to use

  • post(runnable)
  • the sendMessage (msg) msg ​​Note obtaining the best use Message.obtain () Gets. Using object underlying pool to reduce memory consumption.

Principle handler mechanism

Looper thread each is unique, read through the following MessageQueue loop () method, after reading the message to the message sent to process .MessageQueue Handler is a message queue, a FIFO. Create a Loop when he created MessageQueue, 2 who has been hooked together. Message is the message object. Handler is to process messages and sending messages. But it can only be sent MessageQueue associated with it, but MessageQueue associated with any connection looper, so the handler sends a message must have maintained its Looper.

Source analysis:

  1. First, we look handler, MessageQueue, Looper is how linked together?
 public Handler(Callback callback, boolean async) {
        if (FIND_POTENTIAL_LEAKS) {
            final Class<? extends Handler> klass = getClass();
            if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
                    (klass.getModifiers() & Modifier.STATIC) == 0) {
                Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
                    klass.getCanonicalName());
            }
        }

        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }
复制代码

Created in the constructor handler's looper, then this handler will create MessageQueue MessageQueue and associated together according to member variables looper, and MessageQueue is managed by Looper, so that three linked together; we look into the points Looper .myLooper method was found to be obtained from the sThreadLocal, ThreadLocal is unique to each thread of a data, so each handler acquired corresponds Looper own thread.

 public static @Nullable Looper myLooper() {
        return sThreadLocal.get();
    }
复制代码

Read on discovery sThreadLocal really prepare () the assignment, thus ensuring the uniqueness of each thread.

   private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }
复制代码
  1. Then we look looper is how to obtain MessageQueue message.
 public static void loop() {
        ...省略部分不重要代码
        for (;;) {
            Message msg = queue.next(); // might block
                     try {
                msg.target.dispatchMessage(msg);
              
            }             msg.recycleUnchecked();
        }
    }
    
复制代码

In fact, it created a for loop, one by one out msg, by Handler (msg.target) dispatchMessage (msg)

  public void dispatchMessage(Message msg) {
        if (msg.callback != null) {
            handleCallback(msg);
        } else {
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);
        }
    }
复制代码

dispatchMessage, in fact, repeater, depending on the condition of different approaches.

3. Summary Looper opened a loop, constantly getting a message from MessageQueue, the head of the MessageQueue acquired msg, has been handed over to handler.handleMessage msg.target form processing. After the final processing is complete, or it will return to the loop, and continue processing.

handler memory leaks and solutions

Non-static inner class to hold a reference to the outer class, handler there may be a delay or there are time-consuming operation, when the activity destroyed due to the handler holds activity, resulting in activity can not be released, resulting in a memory leak. Solution: handler is set to a static inner classes, call handler.removeCallBack in the activity of onDestroy in (). Note that if the static inner classes, if you want to use activity, some with weak references, rather than directly using activity.

AsyncTask

AsyncTask can be used to deal with some of the more time-consuming background tasks, view the source code found inside the package is a thread pool Handler and, at the same time can help us deal with time-consuming task to update the UI.

AsyncTask use
  • AsyncTask abstract class parameter 3
public abstract class AsyncTask<Params, Progress, Result> {
......
}
 Params 启动任务执行的输入参数,比如下载URL
 Progress 后台任务执行的百分比,比如下载进度
 Result 后台执行任务最终返回的结果,比如下载结果
复制代码
  • Subclasses function can be achieved
 onPreExecute():(运行在UI线程中) (非必须方法)

在任务执行前调用,通常用来做一些准备操作,比如下载文件前,在显示一个进度条等。

doInBackground(Params... params):(运行在子线程中)(必须实现)

可以在此方法中处理比较耗时的操作,比如下载文件等等。

onProgressUpdate(Progress... values) (运行在UI线程中) (非必须方法)

此函数异步任务执行时,回调给UI主线程的进度,比如上传或者下载进度。

onPostExecute(Result result)(运行在UI线程中) (非必须方法)

此函数代表任务执行结束了,回调给UI主线程的结果。比如下载结果。

onCancelled(Result result)onCancelled()任务关闭的函数
复制代码
  • Common Functions
cancel (boolean mayInterruptIfRunning)取消执行任务

execute (Params... params)用指定的参数来执行此任务

executeOnExecutor(Executor exec,Params... params)在指定的Executor中执行任务。

getStatus ()获得任务的当)前状态  PENDING(等待执行)、RUNNING(正在运行)、FINISHED(运行完成)

isCancelled ()在任务正常结束之前能成功取消任务则返回true,否则返回false

复制代码

AsyncTask internal principle Introduction

1. Internal mark also instantiates Handler with Looper, in order to prepare for UI updates flag 2 asynchronous execution place, WorkRunnable can be understood as a worker thread, while itself implements the Callable Interface, Call method contains AyncTask final to be performed tasks and return the results. Result postResult is to carry information sent to the designated target Handler. What we said earlier thread pool + handler implementation.

AsyncTask Notes

  1. Memory leak non-static inner classes held outside of class references; if the Activity has been destroyed, AsyncTask background thread is still running, it will continue to keep this reference in memory, resulting Activity can not be recovered, causing a memory leak. Solution: Set the AsyncTask static inner classes, which holds a weak reference activity. And task onDestroy the cancel ().

  2. AsyncTask not bound lifecycle solutions to any component: call cancel (true) in onDestory Activity / Fragment of ();

  3. Serial or parallel execution of asynchronous serial execution task when you want to directly execute execute () method, if need be performed in parallel, will have to perform executeOnExecutor (Executor). Serial recommendations, to ensure the stability of the thread pool, AsyncTask generally can not do high concurrency, too time-consuming operation.

  4. The results screen rotation or missing Activity in the background are systematically killed and so will lead to re-create the Activity, AsyncTask before running will be held before the Activity of a reference, this reference is no longer valid, then call onPostExecute () interface will be updated again no longer effective.

handlerThread

Open sub-thread time-consuming operation, repeatedly creating and destroying threads is consuming system resources, google for our encapsulates handlerThread. It is handler + thread + looper formed. It is transmitted through the object to obtain handlerThread the looper handler, and then perform asynchronous tasks in handleMessage. The advantage is not going to block the UI thread, the disadvantage is serial execution, low processing efficiency.

handlerThread use

  1. Initialization HandlerThread then call its start method
mHandlerThread = new HandlerThread("mHandlerThread");//这里的mHandlerThread其实就是线程的名字
 mHandlerThread.start();
复制代码

Initialization Handler carried out, the incoming mHandlerThread in Looper, thus ensuring Handler runs a sub-thread, loop rotation, different handleMessage to process the message.

 workHandler = new Handler(mHandlerThread.getLooper()) {
 
             @Override
             public void handleMessage(Message msg) {
                 ...//消息处理
                }             }
         };
复制代码

3. The use of work threads Handler sends a message to the thread's message queue work

 Message msg = Message.obtain();
  msg.what = 2; //消息的标识
  msg.obj = "B"; // 消息的存放
  // b. 通过Handler发送消息到其绑定的消息队列
  workHandler.sendMessage(msg);
复制代码

4. The end of the thread, the thread stops message loop mHandlerThread.quit ();

handlerThread source code analysis

//1.Thread的子类
public class HandlerThread extends Thread {
    int mPriority;
    int mTid = -1;
    Looper mLooper;
    private @Nullable Handler mHandler;

//还记得上面的HandlerThread使用的初始化吗?
    public HandlerThread(String name) {
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }
    
    public HandlerThread(String name, int priority) {
        super(name);
        mPriority = priority;
    }
    
    //thread在开启start后会执行run方法,在这里会准备Looper并开启轮训。
    @Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }
    
    //还记得上面的Handler的创建吗?
      public Looper getLooper() {
        if (!isAlive()) {
            return null;
        }
        synchronized (this) {
            while (isAlive() && mLooper == null) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
        }
        return mLooper;
    }

  //可以发送消息的异步Handler
    @NonNull
    public Handler getThreadHandler() {
        if (mHandler == null) {
            mHandler = new Handler(getLooper());
        }
        return mHandler;
    }

        public boolean quit() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quit();
            return true;
        }
        return false;
    }

       public boolean quitSafely() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quitSafely();
            return true;
        }
        return false;
    }

  
    public int getThreadId() {
        return mTid;
    }
}

复制代码

Note Point 1 : java thread here with the knowledge, wait (); and notifyAll (), why do you use it first, Handler's creation is generally done in the main thread created when acquiring HandlerThread.getLooper (), and Looper's creation is created in the child thread, where there is a thread synchronization issues, such as we call getLooper () when HandlerThread the run () method has not completed execution, mLooper variable has not been assigned at this time on the implementation of the wait () waiting logic, wait until the run () method mLooper is assigned immediately after the execution notifyAll (), then getLooper () can return mLooper correct. Note point 2 : quitSafely () and quit () What is the difference?

The difference is that this method removes the message queue if care is currently being processed messages when exiting the loop, whether or not being executed at this time quit () will immediately exit the loop. If being processed quitSafely, then wait for the message processing is complete before exiting the loop.

IntentService

A package and a special Service HandlerThread Handler can start several times, each consuming operations to work queue are in a serial manner onHandleIntent callback method is performed in IntentService. Task execution stops automatically after.

IntentService use

1. Custom LocalIntentService inherited from IntentService

public class MyIntentService extends IntentService{
 public LocalIntentService(String name) {
        super(name);
    }
}
复制代码

2. To achieve onHandleIntent (), it is a time-consuming operation.

@Override
    protected void onHandleIntent(@Nullable Intent intent) {
        String action = intent.getStringExtra("task_action");
      //dosomething
    }
复制代码

IntentService source code analysis

  1. IntentService inheritance Service, first of all we look onCreate (), you can see which created HandlerThread, so you can time-consuming operation.
 //IntentService第一次启动调用
        public void onCreate() {
            super.onCreate();
                       HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
            thread.start();
            mServiceLooper = thread.getLooper();
            mServiceHandler = new ServiceHandler(mServiceLooper);
        }
复制代码

2. Start times will go startService () -> onStartCommand () -> onStart () to send messages through HandlerThread the handler.

@Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

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

3.IntentService的SerivceHandler

Remove HandlerThread order to perform the task, calls ServiceHandler of handleMessage () -> onHandleIntent (). After the task is finished stopSelf (startId) Stop Service. After the mission, in onDestory () will exit Looper HandlerThread in circulation.

//ServiceHandler接收并处理onStart()方法中发送的Msg
        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); //会判断启动服务次数是否与startId相等
            }
        }

        public void onDestroy() {
            mServiceLooper.quit();
        }
复制代码

Guess you like

Origin blog.csdn.net/weixin_34249678/article/details/91364068