一:问题的提出
- Android用户界面是与用户交互的接口,对于用户的操作,Android迅速响应用户的输入是一个重要目标。如果Activity中的应用程序在5s之内未做出响应,可能会出现“应用程序无响应,是否关闭?"的对话框,还可能会出现崩溃
- 对于这类耗时比较多的工作,一般是使用多线程的方法来解决的。例如用递归求斐波那契数列
- 但是在Android中,只,只有主线程才可以更新主UI界面,而其子线程不能更新UI视图。那我们应该怎么办呢?
二:使用Handler处理多线程问题
Handler:
- 接收子线程发送的数据,并用此数据配合主线程更新UI。
- Handler充当主线程和子线程之间交互的中介
示例:使用Handler+Thread解决求斐波那契数列问题,并更新UI界面
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private EditText editText;
private Button button;
TextView result;
long res;
private Handler mainHandler =new Handler(){
public void handleMessage(Message msg){
switch(msg.what){
case 100:
result.setText(msg.obj+"");
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText=findViewById(R.id.num);
button=findViewById(R.id.btu);
result=findViewById(R.id.result);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new myThread().start();
}
});
}
private class myThread extends Thread{
@Override
public void run() {
res=fib(6);
Message message=new Message();
message.what=100;
message.obj=res;
mainHandler.sendMessage(message);
}
}
long fib(int n){
if(n==1||n==2){
return 1;
}
else{
return fib(n-1)+fib(n-2);
}
}
}
三:使用AsyncTask(异步任务)处理多线程问题
- 异步任务的定义是一个在后台线程上运行,其结果是在UI线程上显示的一种类.
异步任务执行时对应的四个方法:
-
onPreExecute():任务被执行之前调用UI线程.这步通常被用于设置任务,例如在用户界面显示一个进度条.
-
doInBackground() :onPreExcute()执行完后,立刻调用后台任务 .
-
onProgressUpdate():一次呼叫publishProgress()后调用UI线程,执行的时机没有定义.
-
onPostExecute():当后台计算结束时,调用UI线程.
示例:模拟进度条,线程中不断更新进度条显示在UI中
import androidx.appcompat.app.AppCompatActivity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.ProgressBar;
public class MainActivity extends AppCompatActivity {
private ProgressBar progressBar;
private int currentProgress;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressBar = findViewById(R.id.progressbar);
//初始化进度条
progressBar.setMax(100);
//启动异步任务
MyAsyncTask myAsyncTask = new MyAsyncTask();
myAsyncTask.execute("访问的网络地址");//参数的值会传入doInBackgroud方法
}
//定义异步任务类,继承自AsyncTask类
//如果不指定泛型类型,方法中所有的形参和返回值类型都是Object
private class MyAsyncTask extends AsyncTask<String, Integer, String>{
@Override
protected void onPreExecute() {
Log.e("onPreExecute","所在的线程"+Thread.currentThread().getName());
super.onPreExecute();
}
@Override
//必须重写的方法
protected String doInBackground(String[] objects) {
Log.e("doInBackground","所在的线程"+Thread.currentThread().getName());
Log.e("主线程传递的数据",objects[0]);
while (true) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
publishProgress(20);//每隔2s执行一次onProgressUpdate方法,更新进度条
if (currentProgress == 80){
break;
}
}
// publishProgress();//会执行onProgressUpdate方法
return "doInBackground执行的结果";
}
@Override
protected void onProgressUpdate(Integer[] values) {
Log.e("onProgressUpdate","所在的线程"+Thread.currentThread().getName());
Log.e("onProgressUpdate参数的值",values[0] + "");
//获取进度条的当前进度
currentProgress = progressBar.getProgress();
progressBar.setProgress(currentProgress + 20);
super.onProgressUpdate(values);
}
@Override
protected void onPostExecute(String o) {
Log.e("onPostExecute","所在的线程"+Thread.currentThread().getName());
Log.e("onPostExecute参数的值",o);//o是doInBackgroud方法的返回值
super.onPostExecute(o);
}
}
}