Android异步机制更新UI线程(详解)
来源:互联网 发布:红包软件代理招募 编辑:程序博客网 时间:2024/05/17 04:42
引入
所有的Android应用程序都运行在一个独立的dalvik虚拟机中,dalvik虚拟机就是一个开辟在Linux内核中的一个进程,而每一个dalvik虚拟机启动的时候,都会启动一个主线程(MainThread),主线程主要负责处理UI相关的事件,所以MainThread又叫UI线程,这也是我题目的缘由。
在Android中,我们不能直接在子线程中更新UI,因为UI是单线程模式,我们只能在UI线程中对UI元素进行更改,要是直接对UI操作,就会报错。
同时,把一些耗时的代码放到非UI线程中执行,也能提高用户体验,还能避免UI更新5秒超时的ANR;
下面用实例来介绍一下Android中异步机制更新UI线程,用各种方法来更新一个TextView中的内容。
Android中异步更新UI的几种方法
- 使用 Activity.runOnUiThread(Runnable)方法
- 使用View.post(Runnable)或View.postDelayed(Runnable, long)方法
- 使用Handler的post(Runnable)或者postDelayed(Runnable, long)方法
- 使用Handler的消息传递机制
- 使用AsyncTask异步机制
0、多线程实现方法
- 继承Thread类
class MyThread extends Thread{ public Handler mHandler; @Override public void run() { try { Thread.sleep(5000); }catch (InterruptedException e) { e.printStackTrace(); } mHandler.sendEmptyMessage(0); }}
调用的时候:
new MyThread().start();
2.实现Runnable接口
class MyRunnable implements Runnable{ public Handler mHandler; @Override public void run() { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } mHandler.sendEmptyMessage(0); }}
调用的时候:
new Thread(new MyRunnable()).start();
1、使用 Activity.runOnUiThread(Runnable)方法
核心代码模块:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); //使用使用runOnUiThread(Runnable)方法更新UI线程 new MRunOnUiThread().start(); } //内部类实现第一种更新UI的方法 class MRunOnUiThread extends Thread{ @Override public void run() { runOnUiThread(new Runnable() { @Override public void run() { try { //延迟一秒 Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } mTextView.setText("使用runOnUiThread(Runnable)方法"); } }); } }
2、使用View.post(Runnable)或View.postDelayed(Runnable, long)方法
核心代码模块:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); //使用View.post(Runnable)或View.postDelayed(Runnable, long)方法 new MViewPost().start(); } //内部类实现第二种更新UI的方法 class MViewPost extends Thread{ @Override public void run() { mTextView.postDelayed(new Runnable() { @Override public void run() { mTextView.setText("使用View.post(Runnable)或View.postDelayed(Runnable, long)方法"); } },1000); /**下面post方法和上面的postDelayed方法效果是一样的,后者提供了一个延时参数而已**/// mTextView.post(new Runnable() {// @Override// public void run() {// try {// Thread.sleep(1000);// } catch (InterruptedException e) {// e.printStackTrace();// }// mTextView.setText("使用View.post(Runnable)或View.postDelayed(Runnable, long)方法");// }// }); } }
3、使用Handler的post(Runnable)或者postDelayed(Runnable,long)方法
核心代码模块:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); //使用Handler的post(Runnable)方法 Handler handler = new Handler(); handler.postDelayed(new Runnable() { @Override public void run() { mTextView.setText("使用Handler的post(Runnable)" + "或postDelayed(Runnable, long)方法"); } },1000); }
4、使用Handler的消息传递机制
核心代码模块:
Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { if(msg.what == 0x123){ mTextView.setText("使用Handler的消息传递机制"); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); //使用Handler的消息传递机制 new MHandler().start(); } //内部类实现第四种更新UI的方法 class MHandler extends Thread{ @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } handler.sendEmptyMessage(0x123); } }
5、使用AsyncTask异步机制
核心代码模块:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); //使用Handler的消息传递机制 //new MHandler().start(); //使用AsyncTask异步机制 new MAsyncTask().execute(); } //内部类实现第五种更新UI的方法 class MAsyncTask extends AsyncTask<String,String,String>{ @Override protected String doInBackground(String... params) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(String s) { mTextView.setText("使用AsyncTask异步机制"); } }
6、总结一下
事实上,更新UI线程,还有很多的已经被封装开源框架,如Okhttp,Volley等,在项目中使用,能更有效率也能一定程度上提高性能。
UI线程更新是我们在开发过程中经常遇到的,熟练掌握各种更新方法,根据项目需求选用合适的方法。个人比较推荐Handler消息传递机制和AsyncTask异步机制更新UI线程,毕竟Handler的消息传递机制就是为了解决异步更新问题,AsyncTask类更是Google专门为了更新UI线程而提供的。
7、附录:源代码
效果展示:请忽略标题栏,顺手在旧的工程中撸的
源代码:
import android.os.AsyncTask;import android.os.Handler;import android.os.Message;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.TextView;public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private TextView mTextView; private Button btn_one; private Button btn_two; private Button btn_three; private Button btn_four; private Button btn_five; Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { if(msg.what == 0x123){ mTextView.setText("使用Handler的消息传递机制"); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); } private void init() { mTextView = (TextView)findViewById(R.id.textView); btn_one = (Button)findViewById(R.id.btn_one); btn_two = (Button)findViewById(R.id.btn_two); btn_three = (Button)findViewById(R.id.btn_three); btn_four = (Button)findViewById(R.id.btn_four); btn_five = (Button)findViewById(R.id.btn_five); btn_one.setOnClickListener(this); btn_two.setOnClickListener(this); btn_three.setOnClickListener(this); btn_four.setOnClickListener(this); btn_five.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()){ case R.id.btn_one: //使用使用runOnUiThread(Runnable)方法更新UI线程 new MRunOnUiThread().start(); break; case R.id.btn_two: //使用View.post(Runnable)或View.postDelayed(Runnable, long)方法 new MViewPost().start(); break; case R.id.btn_three: //使用Handler的post(Runnable)方法 Handler handlerPost = new Handler(); handlerPost.postDelayed(new Runnable() { @Override public void run() { mTextView.setText("使用Handler的post(Runnable)" + "或postDelayed(Runnable, long)方法"); } },1000); break; case R.id.btn_four: //使用Handler的消息传递机制 new MHandler().start(); break; case R.id.btn_five: //使用AsyncTask异步机制 new MAsyncTask().execute(); break; } } //内部类实现第五种更新UI的方法 class MAsyncTask extends AsyncTask<String,String,String>{ @Override protected String doInBackground(String... params) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(String s) { mTextView.setText("使用AsyncTask异步机制"); } } //内部类实现第四种更新UI的方法 class MHandler extends Thread{ @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } handler.sendEmptyMessage(0x123); } } //内部类实现第二种更新UI的方法 class MViewPost extends Thread{ @Override public void run() { mTextView.postDelayed(new Runnable() { @Override public void run() { mTextView.setText("使用View.post(Runnable)" + "或View.postDelayed(Runnable, long)方法"); } },1000); /**下面post方法和上面的postDelayed方法效果是一样的,后者提供了一个延时参数而已**/ mTextView.post(new Runnable() { @Override public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } mTextView.setText("使用View.post(Runnable)" + "或View.postDelayed(Runnable, long)方法"); } }); } } //内部类实现第一种更新UI的方法 class MRunOnUiThread extends Thread{ @Override public void run() { runOnUiThread(new Runnable() { @Override public void run() { try { //延迟一秒 Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } mTextView.setText("使用runOnUiThread(Runnable)方法"); } }); } }}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.jiaohanhan.intentdemo.MainActivity"> <TextView android:id="@+id/textView" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:textSize="20sp" android:hint="未更新UI线程之前" /> <Button android:layout_marginTop="40dp" android:layout_marginBottom="3dp" android:id="@+id/btn_one" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="第一种方式更新UI线程"/> <Button android:layout_margin="3dp" android:id="@+id/btn_two" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="第二种方式更新UI线程"/> <Button android:layout_margin="3dp" android:id="@+id/btn_three" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="第三种方式更新UI线程"/> <Button android:layout_margin="3dp" android:id="@+id/btn_four" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="第四种方式更新UI线程"/> <Button android:layout_margin="3dp" android:id="@+id/btn_five" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="第五种方式更新UI线程"/></LinearLayout>
参考文档
1、http://blog.csdn.net/mylzc/article/details/6736988
2、郭霖《第一行代码》(第二版)
3、https://segmentfault.com/a/1190000003702775
4、https://developer.android.com/reference/android/os/AsyncTask.html
- Android异步机制更新UI线程(详解)
- Android异步机制一:使用Thread+Handler实现非UI线程更新UI界面
- Android异步机制一:使用Thread+Handler实现非UI线程更新UI界面
- Xamarin.Android如何异步更新UI线程
- xamarin android异步更新UI线程
- xamarin android异步更新UI线程
- 在子线程中更新UI+延时更新(异步消息处理机制)
- Android:在子线程中更新UI,解析异步消息处理机制(Handler)
- 使用异步消息机制在子线程中更新UI
- android异步更新UI
- 开启线程异步更新UI
- Android-初识Handler-子线程异步更新UI
- Android异步更新UI-线程池-Future-Handler实例分析
- Android AsyncTask(异步耗时 更新UI)
- android 运用Message机制更新UI线程界面
- android消息机制之子线程更新UI其它方式
- Android 异步更新UI----AsyncTask
- Android 异步更新UI----AsyncTask
- Spring Boot整合Mybatis
- jQuery常用的ajax-api-$.ajax()方法
- P1060 开心的金明 水水的01背包模板
- ResNeXt算法详解
- C++作业5
- Android异步机制更新UI线程(详解)
- 深度学习时代的计算机视觉
- TensorFlow深度学习框架
- VS2017我们无法刷新此账户的凭据发送请求时出错
- 堆以及php实现堆排序
- properties
- unity使用屏幕后处理实现闪烁特效,创建新的shader文件过程
- selenium 之Xpath定位泛指元素&&下载图片
- 跨服务器Session共享的四种方法