关闭

android handler简单学习总结

标签: androidUI更新handler
66人阅读 评论(1) 收藏 举报
分类:

谈到handler,我们首先想到的就是ui更新,这个是当然了,android为我们提供了一种消息机制handler,在子线程中也可以更新到ui会出现

CalledFromWrongThreadException:Only the original thread that created a view hierarchy can touch its views.),

那为什么在子线程中不能更新主线程ui,我们需要看看UI更新的源码:view更新UI需要调用invalidate()方法,而创建view的同时 也创建了viewrootimpl类, invalidateChildInParent(int[] location, Rect dirty)--》 checkThread();而在checkThread()里面判断当前线程id是否与主线程id相同,如果不同就抛异常

void checkThread() {
        if (mThread != Thread.currentThread()) {
            throw new CalledFromWrongThreadException(
                    "Only the original thread that created a view hierarchy can touch its views.");
        }
    } 

那那为什么要这样设计呢 ,就是为了防止多线程更新ui,导致数据紊乱问题,有人说了可以加线程锁synchronized;但是有么有会出现场线程出现死锁问题导致ui无法更新会出现卡顿,那么用户体验该多么不好,所以我们还是认命吧,用下面方法去实现更新ui





下面基于上述原理说一下更新方法: 
方法一:用Handler 

1、主线程中定义Handler: 

Java代码  收藏代码
  1. Handler mHandler = new Handler() {  
  2.   
  3.         @Override  
  4.         public void handleMessage(Message msg) {  
  5.             super.handleMessage(msg);  
  6.             switch (msg.what) {  
  7.             case 0:  
  8.                 //完成主界面更新,拿到数据  
  9.                 String data = (String)msg.obj;  
  10.                   
  11.                 updateWeather();  
  12.                 textView.setText(data);  
  13.                 break;  
  14.             default:  
  15.                 break;  
  16.             }  
  17.         }  
  18.   
  19.     };  


2、子线程发消息,通知Handler完成UI更新: 
Java代码  收藏代码
  1. private void updateWeather() {  
  2.           
  3.           
  4.         new Thread(new Runnable(){  
  5.   
  6.             @Override  
  7.             public void run() {  
  8.                 //耗时操作,完成之后发送消息给Handler,完成UI更新;  
  9.                 mHandler.sendEmptyMessage(0);  
  10.                   
  11.                 //需要数据传递,用下面方法;  
  12.                 Message msg =new Message();  
  13.                 msg.obj = "数据";//可以是基本类型,可以是对象,可以是List、map等;  
  14.                 mHandler.sendMessage(msg);  
  15.             }  
  16.               
  17.         }).start();  
  18.           
  19.     }  

方法一的Handler对象必须定义在主线程中,如果是多个类直接互相调用,就不是很方便,需要传递content对象或通过接口调用; 

方法二:用Activity对象的runOnUiThread方法更新 
在子线程中通过runOnUiThread()方法更新UI: 
Java代码  收藏代码
  1. new Thread() {  
  2.             public void run() {  
  3.                 //这儿是耗时操作,完成之后更新UI;  
  4.                 runOnUiThread(new Runnable(){  
  5.   
  6.                     @Override  
  7.                     public void run() {  
  8.                         //更新UI  
  9.                         imageView.setImageBitmap(bitmap);  
  10.                     }  
  11.                       
  12.                 });  
  13.             }  
  14.         }.start();  

如果在非上下文类中(Activity),可以通过传递上下文实现调用; 
Java代码  收藏代码
  1. Activity activity = (Activity) imageView.getContext();  
  2.                 activity.runOnUiThread(new Runnable() {  
  3.   
  4.                     @Override  
  5.                     public void run() {  
  6.                         imageView.setImageBitmap(bitmap);  
  7.                     }  
  8.                 });  

这种方法使用比较灵活,但如果Thread定义在其他地方,需要传递Activity对象; 

方法三:View.post(Runnable r) 

Java代码  收藏代码
  1. imageView.post(new Runnable(){  
  2.   
  3.                     @Override  
  4.                     public void run() {  
  5.                         imageView.setImageBitmap(bitmap);  
  6.                     }  
  7.                       
  8.                 });  

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:673次
    • 积分:85
    • 等级:
    • 排名:千里之外
    • 原创:8篇
    • 转载:1篇
    • 译文:0篇
    • 评论:2条
    文章存档
    最新评论