Android-不阻塞的UI线程方法

来源:互联网 发布:linux进程崩溃 编辑:程序博客网 时间:2024/05/18 02:28

Android不阻塞的UI线程的方法

分类: Android 759人阅读 评论(0) 收藏 举报
Android编程界面线程并发

Android中的UI线程也是应用的主线程。顾名思义,UI线程主要负责界面的刷新与管理,向onKeyDown()这样的系统回调也都在UI线程中(主线程)中被执行。


这个线程是否在流畅的运行直接关系到当前的App的用户体验。例如:如果一个按钮被点击后会执行某个非常耗时间的操作(比如下载),那么用户单击了这个按钮后,界面会发生卡顿现象,直到这个非常耗时间的操作执行完毕界面才会恢复到能与用户交互的状态。如果用户发现他们单击了某个按钮后界面就会死掉,按哪里都没有反应,他们就会觉得你的App出了BUG,然后就很可能会卸载你的应用。


概括来讲,为了UI线程能随时对用户的操作做出反应,你应该遵循下列两个基本原则:

(1) 绝对不要阻塞UI线程

(2) 不要从UI线程以外的线程中访问UI组件。


如果你会使用线程那么第一条原则你就已经能够实现了。是的,如果想让耗时间的操作不阻塞UI线程,就要让这个操作在一个另外一个线程中运行。

例如下面的代码:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. public class MainActivity extends Activity {  
  2.     private TextView textView;   //UI线程的UI组件  
  3.   
  4.     protected void onCreate(Bundle savedInstanceState) {  
  5.         super.onCreate(savedInstanceState);  
  6.         setContentView(R.layout.activity_main);  
  7.         textView = (TextView) findViewById(R.id.showText);  
  8.     }  
  9.   
  10.     public void onChangeText(View view) { // 界面中的一个按钮onClick()函数  
  11.         new Thread(new Runnable() {  
  12.             public void run() {  
  13.                 for (int i = 0; i < 1000000000; i++) { // 这是个很耗时的操作  
  14.                 }  
  15.                 textView.setText("Finished");  
  16.             }  
  17.   
  18.         }).start();  
  19.   
  20.     }  
  21. }  


像这样通过线程来运行很耗时间的代码就可以不阻塞UI线程了。

但是上面的代码还有问题,因为它不符合第二条原则,那就是它没在UI线程中操作 textView 。


要在非UI线程中操作UI组件,可以通过下面的一些方法:

<1> View.post(Runnable)

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. public class MainActivity extends Activity {  
  2.     private TextView textView;  
  3.   
  4.     protected void onCreate(Bundle savedInstanceState) {  
  5.         super.onCreate(savedInstanceState);  
  6.         setContentView(R.layout.activity_main);  
  7.         textView = (TextView) findViewById(R.id.showText);  
  8.     }  
  9.   
  10.     public void onChangeText(View view) {  //界面中的一个按钮onClick()函数  
  11.         new Thread(new Runnable() {  
  12.             public void run() {  
  13.                 for (int i = 0; i < 1000000000; i++) {   //这是个很耗时的操作  
  14.                 }  
  15.                 textView.post(new Runnable() {  //这样textView.setText()就会在UI线程中执行  
  16.                     public void run() {  
  17.                         textView.setText("123");  
  18.                     }  
  19.                 });  
  20.             }  
  21.         }).start();  
  22.           
  23.     }  
  24. }  

<2> Activity.runOnUiThread(Runnable)

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. public class MainActivity extends Activity {  
  2.     private TextView textView;  
  3.   
  4.     protected void onCreate(Bundle savedInstanceState) {  
  5.         super.onCreate(savedInstanceState);  
  6.         setContentView(R.layout.activity_main);  
  7.         textView = (TextView) findViewById(R.id.showText);  
  8.     }  
  9.   
  10.     public void onChangeText(View view) {     //界面中的一个按钮onClick()函数  
  11.         new Thread(new Runnable() {  
  12.             public void run() {  
  13.                 for (int i = 0; i < 1000000000; i++) {   //这是个很耗时的操作  
  14.                 }  
  15.                 runOnUiThread(new Runnable() {     //这样textView.setText()就会在UI线程中执行  
  16.                     public void run() {  
  17.                         textView.setText("123");  
  18.                     }  
  19.                 });  
  20.             }  
  21.         }).start();  
  22.           
  23.     }  
  24. }  

<3> View.postDelayed(Runnable, long) 

View.post(Runnable)的带延迟版。


<4> 使用Handler类

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. public class MainActivity extends Activity {  
  2.     private TextView textView;  
  3.     private Handler handler;  
  4.   
  5.     protected void onCreate(Bundle savedInstanceState) {  
  6.         super.onCreate(savedInstanceState);  
  7.         setContentView(R.layout.activity_main);  
  8.         textView = (TextView) findViewById(R.id.showText);  
  9.   
  10.         handler = new Handler() {  //初始化handler  
  11.             @Override  
  12.             public void handleMessage(Message msg) { //通过handleMessage()来处理传来的消息  
  13.                 if (msg.what == 1)  
  14.                     textView.setText("Finished");  
  15.             }  
  16.         };  
  17.     }  
  18.   
  19.     public void onChangeText(View view) { // 界面中的一个按钮onClick()函数  
  20.         new Thread(new Runnable() {  
  21.             public void run() {  
  22.                 for (int i = 0; i < 1000000000; i++) {  
  23.                 }  
  24.                 Message msg = new Message();    
  25.                 msg.what = 1;  
  26.                 //通过sendMessage()向handler发送一个消息,这个消息会在  
  27.                 //handleMessage()中被处理  
  28.                 handler.sendMessage(msg);    
  29.             }  
  30.         }).start();  
  31.     }  
  32. }  
<5>使用Handler.post(Runnable)


如果转载请注明出处:http://blog.csdn.net/gophers


0 0