Android developers - to achieve the child thread to update the UI

Android threads by function, it can be divided into two, a main thread (UI thread), all other sub-thread

The main thread can not take too long to implement those code or task (taking too long to execute code of the application is not responding prompt will appear), it is taking too long to execute code using child threads, such as downloading files, etc. task

Generally, the child thread executing the code is too long, all need to be updated UI operations.

But Android in order to prevent security, is not allowed to update the UI thread in the child , but we can use the API to achieve given the official Android operating sub-thread to update the UI (in essence, the API also switch back to the main thread updated UI)

Example: Click a button to complete the download task After a 1s, returned data, this data will be displayed on the screen

Specific explanation:

Click the button to open after a child thread to simulate the download process (thread sleep 1s), after the task is completed will return data (a String), update the UI with the returned data

Create a new method to simulate the download tasks

/**
 * 模拟下载
 */
fun download(): String {
    Thread.sleep(1000)
    return "this is data"
}

Simulation methods The following tasks and using the above six ways to achieve the effect of the above example

1.Activity.runOnUiThread()

runOnUiThreadActivity in the method, the object is only the current Activity, it can be used directly, if the current object is not Activity, Activity need to find objects to perform this method

runOnUiThreadParameter method is a Runnable interface, kotlin I use, so there are a lot of things are omitted

Set the button's click event, click the button to open a thread

btn_start.setOnClickListener {
    thread {
        val data = download()
        runOnUiThread({
            //这里进行更新UI操作
            tv_show.text = data
        })
    }
}

Java version

btn_start.setOnClickListener(new OnClickListener(){
    new Thread(new Runnable(){
        String data = download();
        runOnUiThread(new Runnable(){
            @Override
            public void run() {
                tv_show.setText(data);
            }
        })
    }).start();
});

2.View.post()

View post method is a method of an object, the parameter is an interface receiving a runnable

Here I use the view objects that need to be updated textview itself, of course, can choose other View object, as long as the current Activity objects can

btn_start.setOnClickListener {
    thread {
        val data = download()
        //选择当前Activity的View对象都可以
        tv_show.post { 
            tv_show.text = data 
        }
    }
}

3.View.PostDelayed()

This method and the above method analogous post, just one more parameter to achieve the effect of delayed update UI

btn_start.setOnClickListener {
    thread {
        val data = download()
        tv_show.postDelayed({
            tv_show.text = data
        },2000)
    }
}

The code above effect is achieved after clicking the button, after 3s after will see the interface changes

4.Handler.post()

a new Handler object (a global variable)

private val handler = Handler()

Use the post method to update UI, this method and post the same way as the previous post, the parameters are for the Runnable interface

btn_start.setOnClickListener {
    thread {
        val data = download()
        handler.post {
            tv_show.text = data
        }
    }
}

5.AsyncTask (recommended)

Explanation

AsyncTask is an abstract class, you must create a subclass of the class to inherit it

Introduce three generic parameter here and on several methods of AsyncTask

Generic parameters can be used to empty, then any typeVoid

parameter Explanation
params Parameters generic, doInBackground method
progress Progress generic parameters, onProgressUpdate method
result Results generic parameters, onPostExecute Method

Abstract methods Description:

Method name Explanation
onPreExectute() In this method, the initialization operation is often performed, such as the progress bar display
doInBackground(Params...) This method must be implemented,
onProgressUpdate(Progress...) UI update operations
publishProgress(Progress...) In doInBackground method calls this method after calling callback method execution onProgressUpdate updated UI
onPostExcute(Result) After the task is updated UI

Briefly, if the subclass inherits the AsyncTask, its abstract methods will become generic parameters corresponding to the type of

example

The following code is taken from my APP, briefly explainAsyncTask<String, DownloadingItem, DownloadedItem>

I passed a three generic parameter are String, , DownloadingItem, DownloadedItemrespectively corresponding params, progressand resultgenerics

I am here according to their own needs two classes DownloadingItemand DownloadedItemcan be seen from the following code, the parameters of the abstract method becomes our generic type

internal inner class DownloadingTask : AsyncTask<String, DownloadingItem, DownloadedItem>() {

    override fun onPreExecute() {
        //一些初始化操作
    }

    override fun doInBackground(vararg params: String?): DownloadedItem {
        //params是一个参数数组,如果创建DownloadingTask对象只传入了一个参数,直接取下标为0的那个即可(需要转型)
        //耗时操作(如下载操作),获得进度数据
        
        //将新的进度数据传递到onProgressUpdate方法,更新UI
        publishProgress(messageItem)
        
        //任务执行完毕,返回结果(回调onPostExecute方法)
    }

    override fun onProgressUpdate(vararg values: DownloadingItem?) {
        //这里使用最新的进度来进行相关UI的更新
        //values是一个DownloadingItem数组,取末尾那个即为最新的进度数据
    }

    override fun onPostExecute(result: DownloadedItem?) {
        //下载成功提示或者是其他更新UI的操作
    }
}

carried out:

Task execution time of need (UI thread calls) in the main thread

DownloadingTask().execute("参数")

Batch download:

//允许在同一时刻有5个任务正在执行,并且最多能够存储50个任务
private val exec = ThreadPoolExecutor(5, 50, 10, TimeUnit.SECONDS, LinkedBlockingQueue<Runnable>())
DownloadingTask().executeOnExecutor(exec, url)

6.Handler mechanism to achieve (core)

In fact, Handler mechanism is the core of the child process to update the UI

We realize the above five child process to update the UI the way, it is based on the mechanism to achieve Handler

Specific mechanisms article is not to say, there are many online mechanism described here to talk about what steps to achieve the

Message has several attributes, what, , arg1, arg2these three are receiving a Int, so data transfer is not very friendly, not prepared here an example of the effect of realized before

represents what sources, arg1 and arg2 for data transfer Int

1. Method override Handler class handleMessage

General provisions are a constant Int's good to representwhat

private val handler =object : Handler(){
    override fun handleMessage(msg: Message?) {
        if (msg.what == 1) {
            //来源为1,则
        }
    }
}

2. Send Message

val msg = handler.obtainMessage()
//一般都是规定好一个Int的常量,来表示what
msg.what = 1
//传递Int数据
msg.arg1 = 20
handler.sendMessage(msg)

Guess you like

Origin www.cnblogs.com/kexing/p/11666803.html