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()
runOnUiThread
Activity 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
runOnUiThread
Parameter 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
, DownloadedItem
respectively corresponding params
, progress
and result
generics
I am here according to their own needs two classes DownloadingItem
and DownloadedItem
can 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
, arg2
these 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)