android之Handler的使用,回到主线程更新UI的四种方法

Android为了线程安全,并不允许我们在UI线程外操作UI;很多时候我们做界面刷新都需要通过Handler来通知UI组件更新!除了用Handler完成界面更新外,还可以使用runOnUiThread()来更新,甚至更高级的事务总线。 

当我们的子线程想修改Activity中的UI组件时,我们可以新建一个Handler对象,通过这个对象向主线程发送信息;而我们发送的信息会先到主线程的MessageQueue进行等待,由Looper按先入先出顺序取出,再根据message对象的what属性分发给对应的Handler进行处理。

Handler运行在主线程中(UI线程中), 它与子线程可以通过Message对象来传递数据, 这个时候,Handler就承担着接受子线程传过来的(子线程用sedMessage()方法传弟)Message对象,(里面包含数据) , 把这些消息放入主线程队列中,配合主线程进行更新UI。

  • UI线程:就是我们的主线程,系统在创建UI线程的时候会初始化一个Looper对象,同时也会创建一个与其关联的MessageQueue;
  • Handler:作用就是发送与处理信息,如果希望Handler正常工作,在当前线程中要有一个Looper对象
  • Message:Handler接收与处理的消息对象
  • MessageQueue:消息队列,先进先出管理Message,在初始化Looper对象时会创建一个与之关联的MessageQueue;
  • Looper:每个线程只能够有一个Looper,管理MessageQueue,不断地从中取出Message分发给对应的Handler处理!

Handler在子线程中:

如果是Handler写在了子线程中的话,我们就需要自己创建一个Looper对象了!创建的流程如下:

1 )直接调用Looper.prepare()方法即可为当前线程创建Looper对象,而它的构造器会创建配套的MessageQueue; 

2 )创建Handler对象,重写handleMessage( )方法就可以处理来自于其他线程的信息了! 3 )调用Looper.loop()方法启动Looper

 new Thread(new Runnable() {
        @Override
        public void run() {
            /*
            * handler使用步骤
            *gei threadLocal设置了一个looper对象
            * 在looper的构造方法中,创建了一个messageQueue对象
            * */
            Looper.prepare();

            /*在构造方法中获取looper和looper中的messageQueue
            *
            * */
            Handler handler=new Handler(){
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);

                }
            };

            /*奖message发送到messagequeue中,在messageQueue里面,所有的message都是时间为顺序从小到大排列
            *
            * */
handler.sendEmptyMessage(0);
/*
*顺序取出messageQueue中的message
*并且执行message。target。dispatchMessage();其中的message。target就是发送这个消息的handler
* 每一条消息都有一定的执行时间,handler会判断时间有没有到,如果没到时间会等待,
* */
Looper.loop();
        }
    }).start();

 

----------handler的使用------

通过Message与Handler进行通信的步骤是: 
1. 重写Handler的handleMessage方法,根据Message的what值进行不同的处理操作 
2. 创建Message对象 
虽然Message的构造函数式public的,我们还可以通过Message.obtain()或Handler.obtainMessage()来获得一个Message对象(Handler.obtainMessage()内部其实调用了Message.obtain())。 
3. 设置Message的what值 
Message.what是我们自定义的一个Message的识别码,以便于在Handler的handleMessage方法中根据what识别出不同的Message,以便我们做出不同的处理操作。 
4. 设置Message的所携带的数据,简单数据可以通过两个int类型的field arg1和arg2来赋值,并可以在handleMessage中读取。 
5. 如果Message需要携带复杂的数据,那么可以设置Message的obj字段,obj是Object类型,可以赋予任意类型的数据。或者可以通过调用Message的setData方法赋值Bundle类型的数据,可以通过getData方法获取该Bundle数据。 
6. 我们通过Handler.sendMessage(Message)方法将Message传入Handler中让其在handleMessage中对其进行处理。 

需要说明的是,如果在handleMessage中 不需要判断Message类型,那么就无须设置Message的what值;而且让Message携带数据也不是必须的,只有在需要的时候才需要让其携带数据;如果确实需要让Message携带数据,应该尽量使用arg1或arg2或两者,能用arg1和arg2解决的话就不要用obj,因为用arg1和arg2更高效。

 

Handler handler = new Handler()
{
    public void handleMessage(android.os.Message msg) {
        switch (msg.what){
            case 1:
                String str= (String) msg.obj;
                reponsedattx.setText(str);
                break;


        }
    };
};

 

 

 

//get同步请求---http://ddb.cn/api/VlianbaoCash/deposit
    public void gettongbuDatasync(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                OkHttpClient client = new OkHttpClient();//创建OkHttpClient对象
                Request request = new Request.Builder()
                        .url(String.valueOf(test.getText()))//请求接口。如果需要传参拼接到接口后面。
                        .build();//创建Request 对象
                Response    response=null;
                try {
                     response = client.newCall(request).execute();//得到Response 对象
                    Log.e("kwwl","get同步res=="+response.body().string());
                  String resstr=response.body().string();

                    Message msg=new Message();
                    //虽然Message的构造函数式public的,我们也可以通过以下两种方式通过循环对象获取Message
                    //msg = Message.obtain(uiHandler);
                    //msg = uiHandler.obtainMessage();

                    //what是我们自定义的一个Message的识别码,以便于在Handler的handleMessage方法中根据what识别
                    //出不同的Message,以便我们做出不同的处理操作
                    msg.what = 1;

                    //我们可以通过arg1和arg2给Message传入简单的数据

                    msg.arg2 = 321;
                    msg.obj="jjjj";
                    //我们也可以通过给obj赋值Object类型传递向Message传入任意数据
                    //msg.obj = null;
                    //我们还可以通过setData方法和getData方法向Message中写入和读取Bundle类型的数据
                    //msg.setData(null);
                    //Bundle data = msg.getData();

                    //将该Message发送给对应的Handler*****
                    handler.sendMessage(msg);

                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
    }

 

 

 

-------回到主线程更新UI的四种方法,参考:https://blog.csdn.net/mislaydu/article/details/51776247

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值