Android 开发中的消息机制 Handler 机制

子线程中更新主线程界面(UI)

一、前言

        最近在多线程的使用过程中遇到一些问题,记录下来以加深印象。当在主线程中要进行某一操作比较耗时时,就需要开启新线程来处理,主线程通常等待时间在 5 秒左右,大于 5 秒的操作会报错,所以需要子线程。


         其一是在子线程中更新主线程界面(UI)  时抛出异常如下:

:Android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created view hierarchy can touch its views.


   谷歌翻译:只有创建视图层次才可以触摸其焦点原来的线程。


二、子线程更新主线程界面 (UI)的异常原因及处理

     示例代码:(以下代码是本人的相关文件的部分代码,其中部分类是个人需要写的)

(1)报异常代码

[java]  view plain  copy
  1. <span style="font-size:14px;">new Thread(new Runnable() {  
  2.             @Override  
  3.             public void run() {  
  4.                 GetAllMessageFromWeb getAll = new GetAllMessageFromWeb();  
  5.                 allList = getAll.getAllMessage();//(1)数据源加载来自数据库(2)创建适配器(3)视图加载适配器  
  6.                 dataList = new ArrayList<Map<String,Object>>();  
  7.                 for(int i=0;i<allList.size();i++){  
  8.                     MyMessage message = new MyMessage();  
  9.                     message = allList.get(i);  
  10.                     Map<String,Object> map = new HashMap<String,Object>();  
  11.                     map.put("id",message.getId());  
  12.                     map.put("content",message.getContent());  
  13.                     dataList.add(map);  
  14.                 }  
  15.                     adapter = new MyStyle(MenuActivity.this,dataList,R.layout.listview_layout,new String[] {"id","content"},new int[] {R.id.msg_id,R.id.msg_content});  
  16.                     listView.setAdapter(adapter);//出错,报异常,原因在子线程中修改主线程UI会引起错乱,应用Handler机制来处理。  
  17.             }  
  18.         }).start();</span>  

    异常原因是直接在主线程中开一个新线程,该子线程有修改主线程 UI的操作,报异常

Only the original thread that created view hierarchy can touch its views.


(2)Handler 消息机制处理后的代码,不报异常,成功更新主线程界面 (UI)

[java]  view plain  copy
  1. <span style="font-size:14px;">final Handler handler = new Handler(){  
  2.             @Override  
  3.             public void handleMessage(Message msg) {  
  4.                 super.handleMessage(msg);  
  5.                 if(msg.what==RIGHT){  
  6.                     //(2)创建适配器  
  7.                     adapter = new MyStyle(MenuActivity.this,dataList,R.layout.listview_layout,new String[] {"id","content"},new int[] {R.id.msg_id,R.id.msg_content});  
  8.                     //(3)视图加载适配器  
  9.                     listView.setAdapter(adapter);  
  10.                 }  
  11.             }  
  12.         };  
  13. new Thread(new Runnable() {  
  14.             @Override  
  15.             public void run() {  
  16.                 GetAllMessageFromWeb getAll = new GetAllMessageFromWeb();  
  17.                 allList = getAll.getAllMessage();  
  18.                 dataList = new ArrayList<Map<String,Object>>();  
  19.                 //(1)数据源加载来自数据库  
  20.                 for(int i=0;i<allList.size();i++){  
  21.                     MyMessage message = new MyMessage();  
  22.                     message = allList.get(i);  
  23.                     Map<String,Object> map = new HashMap<String,Object>();  
  24.                     map.put("id",message.getId());  
  25.                     map.put("content",message.getContent());  
  26.                     dataList.add(map);  
  27.                 }  
  28.   
  29.                 if(dataList!=null){  
  30.                     Message m = new Message();  
  31.                     m.what = RIGHT;  
  32.                     handler.sendMessage(m);  
  33.                 }else{  
  34.                     Message m = new Message();  
  35.                     m.what = ERROR;  
  36.                     handler.sendMessage(m);  
  37.                 }  
  38.             }  
  39.         }).start();</span>  


分析:


    
1、对子线程中更新主线程 UI的异常处理,就是使用 Handler消息处理机制。新建 Haldler对象,通过 message 的发送与接收,来处理更新 UI操作。使用 Handler 机制进行子线程更新界面后返回给用户不会报异常。


   2、注意:在子线程中是无法更新主线程的界面(UI)的.Android引入Handler解决这个问题。


   3、原因是如果同时多个子线程更新主线程界面,会导致界面不断变化,并且不易找到原因,Handler机制就是的当子线程中有更新主线程 UI 的操作时,将通过 message 消息的发送接收来告诉主线程,handler 在主线程中运行,对发送接收的message处理,从而实现主线程页面的更新。该机制主要是规范子线程与主线程的操作,从而避免子线程的相关操作引起混乱。


三、 Handler 处理机制的简单使用


      在子线程中修改主线程界面 (UI)中控件 EditText 的内容,代码如下:

其中 _handler1,_handler2 是两个按钮,对其监听,进行修改 UI操作;前者直接在新线程中更新 UI,后者使用Handler message处理。

[java]  view plain  copy
  1. <span style="font-size:14px;">/** 
  2.          * 监听 handler 机制 (1) 会报异常,因为没用 handler 机制,在子线程修改界面 (UI)会报异常。修改 editText内容失败。 
  3.          */  
  4.         _handler1.setOnClickListener(new OnClickListener() {  
  5.               
  6.             @Override  
  7.             public void onClick(View v) {  
  8.                 //对文本框内容修改  
  9.                 editText.setText("调用 handler 之前的内容。");  
  10.                 new Thread(new Runnable() {  
  11.                       
  12.                     @Override  
  13.                     public void run() {  
  14.                         try {  
  15.                             Thread.sleep(3000);//休息3秒  
  16.                         } catch (InterruptedException e) {e.printStackTrace();}  
  17.                           
  18.                         editText.setText("调用 handler 机制进行修改内容1。");  
  19.                     }  
  20.                 }).start();  
  21.             }  
  22.         });  
  23.           
  24.         /** 
  25.          * 监听 handler 机制,(2)子线程调用handler 处理主线程界面 (UI)成功,将 exitText对应的文本框内容修改 
  26.          */  
  27.         _handler2.setOnClickListener(new OnClickListener() {  
  28.               
  29.             @Override  
  30.             public void onClick(View v) {  
  31.                 editText.setText("handler 机制,子线程修改 UI之前");  
  32.                 final Handler handler = new Handler(){  
  33.                     public void handleMessage(Message m) {  
  34.                         super.handleMessage(m);  
  35.                         if(m.what==1){  
  36.                             editText.setText("调用 handler 机制进行修改内容2。");  
  37.                         }  
  38.                     }  
  39.                 };  
  40.                   
  41.                 new Thread(new Runnable() {  
  42.                       
  43.                     @Override  
  44.                     public void run() {  
  45.                         try {  
  46.                             Thread.sleep(3000);  
  47.                         } catch (InterruptedException e) {e.printStackTrace();}  
  48.                         Message message = new Message();//新建消息  
  49.                         message.what = 1;               //赋给内容  
  50.                         handler.sendMessage(message);       //发送消息  
  51.                     }  
  52.                 }).start();  
  53.             }  
  54.         });</span>  


      在运行的程序中,点击两按钮的结果如下图:

_handler1

     


所报异常:



_handler2


      


正常运行,不报异常。


四、handler + message + looper 对于线程 Thread 详细图示

   
  
本文转自http://blog.csdn.net/niaonao
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值