Android asynchronously updates UI-thread pool-Future-Handler instance analysis, ui-future-handler
Android asynchronously updates UI-thread pool-Future-Handler instance analysis
During Android development, time-consuming tasks are processed and refreshed in sub-threads. the following two questions are raised by most developers:
1. Data often needs to be read and updated, which is time-consuming. You need to refresh the UI step by step.
2. How to stop the data being read in the Child thread and not refresh the old data to the new UI after the UI switch.
Currently, most tutorials on the Internet are simple Handler. postDelayed (), Thread + Handler, and Async are only applicable to simple one-time refresh. some people may say that I can use the new Thread method to create a subthread to refresh, and then pass the message back to update the UI, however, such constant new features will cause high performance consumption and data synchronization problems.
To solve these two problems, I would like to introduce the use of thread pool + Future + handler.
To better understand the principles of asynchronous UI update, we will first introduce the Thread + Handler + logoff + Message model, as shown in 1:
Figure 1 Thread + Handler + logoff + Message model
Figure 1 clearly shows the Message Queue Processing Method in logoff. There are two important points: (1) subthreads can also manage messages through logoff, however, logoff is required. prepare () and logoff. loop () can realize the message loop; (2) the main UI thread does not need to implement prepare () and loop () because it has been implemented by default in the main thread.
Now we will introduce some basic concepts of thread pool + Future + handler and use demo instances.
Thread Pool
It is an object pool idea. It opens up a memory space and stores a large number of threads (not dead). The thread execution scheduling in the pool is handled by the pool manager. When there is a thread task, take one from the pool. After the execution is complete, the thread object is returned to the pool. This avoids the performance overhead caused by repeated creation of thread objects and saves system resources. if threads are repeatedly created and destroyed in the program, the response speed of the program will be seriously affected, and sometimes even Crash the program. here we use the simple ExecutorService class.
Future <?>
The Future mode can be described as follows: I have a task submitted to Future, and Future completes this task for me. During this period, I can do anything I want. After a while, I can retrieve the results from Future. It is equivalent to a order form. After a period of time, you can take the order to pick up the goods. During this period, you can do anything else. The Future interface is the order form, and the Executor class is used to process the order. It produces the product according to the requirements of the Future interface.
Handler
A bridge connecting the sub-thread and the main thread. It can communicate with the main thread through sendmessage or post.
If there are still children's shoes that are not familiar with the basic concepts, you can move them to the final reference article and read it again. Here, we will go directly to the Code for dry goods.
Method 1: Use sendMessage
Public class MyActivity extends Activity {private final String TAG = "DemoExecutorService"; @ Override public void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. main); initFindView (); setListener ();} private TextView mTitle; private Button mBtn; private void initFindView () {mTitle = (TextView) findViewById (R. id. title); mBtn = (Button) findViewBy Id (R. id. btn);} private void setListener () {mBtn. setOnClickListener (new View. onClickListener () {@ Override public void onClick (View view) {TestCallBack testCallBack = new TestCallBack (); testCallBack. loadToHandler () ;}});} private class TestCallBack {public TestCallBack () {Log. d (TAG, "##### TestCallBack = Constructor");} public void loadToHandler () {Handler myHandler = new Handler (getMainLo Receive () {@ Override public void handleMessage (Message msg) {Log. d (TAG, "###### receive the msg ?? What = "+ msg. what); int num = msg. what; switch (num) {case 1: mTitle. setText ("###### Yeah, we receive the first msg 1"); break; case 2: mTitle. setText ("###### Yeah, we receive the second msg 2"); break; default: break ;}}; testExecutorHandler (myHandler );}} private final ExecutorService mExecutor = Executors. newSingleThreadExecutor (); Future <?> MTask; boolean mSendMsg; public void testExecutorHandler (final Handler handler) {Log. d (TAG, "######## testExecutorHandler, mTask =" + mTask); if (mTask! = Null) {// cancel mTask to enable tasks that have been queued but not run in the queue. Use a flag to prevent msg from being updated to the UI main thread. mTask. cancel (false); Log. d (TAG, "####### mTask. isCannel? = "+ MTask. isCancelled (); mSendMsg = false;} Runnable r = new Runnable () {@ Override public void run () {mSendMsg = true; try {Log. d (TAG, "### step 1 #### start to sleep 6 s. "); Thread. sleep (6000);} catch (InterruptedException e) {e. printStackTrace ();} Message msg; Log. d (TAG, "####### 1111 mSendMsg =" + mSendMsg); if (mSendMsg) {msg = handler. obtainMessage (); msg. what = 1; handler. sendMessage (msg);} else {return;} Log. d (TAG, "#### step 2 #### start to sleep 4 s. "); try {Thread. sleep (4000);} catch (InterruptedException e) {e. printStackTrace ();} // if no obtainMessage is returned, the following error is returned because it has been recycled. you need to re-obtainMessage (). /// E/AndroidRuntime (1606): java. lang. illegalStateException: The specified message queue synchronization barrier token has not been posted or has already been removed. log. d (TAG, "####### 22222 mSendMsg =" + mSendMsg); if (mSendMsg) {msg = handler. obtainMessage (); msg. what = 2; handler. sendMessage (msg) ;}else {return ;}}; // mExecutor. submit (r); // if this is the case, it will not enter the Future task, so that each submit submitted will be executed in sequence. mTask = mExecutor. submit (r );}}
The results and prints are shown in 2 and 3:
Figure 2 Figure 3
Figure 4 uses multiple clicks to simulate UI refreshing without stopping calls. The execution tasks in the background only retain the current task and the last submitted task, and the middle tasks are all dropped by Futurecancel. in addition, the old task is also controlled by the flag, and the updated content is not sendMessage, which does not affect the last UI refresh.
Figure 4
Method 2: Update using runnable:
Because some methods are the same as above, you can download the complete code below. The following is only the core code.
public void loadToRunnable() { Runnable runable = new Runnable(){ @Override public void run() { Log.d(TAG, "#########Ok..1111 let update callback1..."); mTitle.setText("####Yeah, Refresh in runnable, callback1"); } }; Runnable runable2 = new Runnable() { @Override public void run() { Log.d(TAG, "######Ok, let update callback2, ..."); mTitle.setText("####Callback2 update success!!!"); } }; testExecutorRunnable(runable, runable2, getMainLooper()); } }
Public void testExecutorRunnable (final Runnable callback, final Runnable callback2, final Looper loback) {Log. d (TAG, "##### testExecutor # mTask .. ####= "+ mTask); if (mTask! = Null) {mTask. cancel (false); // true indicates that the task is forcibly canceled and an exception occurs. false indicates that the task is canceled after the task ends. mSendMsg = false;} Runnable r = new Runnable () {@ Override public void run () {mSendMsg = true; try {Log. d (TAG, "##### Step 1 #### Async run after submit... ### sleep 6 s "); Thread. sleep (6000);} catch (InterruptedException e) {e. printStackTrace ();} if (callback! = Null & mSendMsg) {// Handler handler = new Handler (); // Not use it, shocould use the logoff. handler handler = new Handler (lofter); handler. post (callback);} try {Log. d (TAG, "##### Step 2 #### Async run after submit... ### sleep 4 s "); Thread. sleep (4000);} catch (InterruptedException e) {e. printStackTrace ();} if (callback2! = Null & mSendMsg) {Handler handler = new Handler (loader); handler. post (callback2) ;}}; mTask = mExecutor. submit (r );}
Code download path: http://download.csdn.net/detail/jjzhoujun2010/8524159
For Original Articles, please refer to blog.csdn.net/jjzhoujun2010 for reprinting.
Author: Dream Fly
Reference: http://yangjingblog.iteye.com/blog/1860590
Http://www.eoeandroid.com/thread-274533-1-1.html
Http://www.cnblogs.com/qingblog/archive/2012/06/27/2566021.html
Http://my.oschina.net/bairrfhoinn/blog/177639
Http://blog.csdn.net/lyf_007217/article/details/8542238