TII--Android技术篇Handler

零、前言

Handler也是个磨人的小妖精,一次又一次的败给她,现在总结一下用法
Handler最主要的作用就是子线程更新UI的问题。
Handler使用并不难,背后的一套机制理解起来怪麻烦,而且很重要。


一、还是以最经典的:子线程更新UI来引入吧

场景:点击按钮新建线程,在新线程里更改TextView的值,如下图

9414344-73d33337ec8f9ef6.png
handler1.png
1、准备工作:
public class HandlerActivity extends AppCompatActivity {
    private static final String TAG = "HandlerActivity";
    @BindView(R.id.id_tv_handler)
    TextView mIdTvHandler;
    @BindView(R.id.id_btn_change)
    Button mIdBtnChange;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler);
        ButterKnife.bind(this);
        Log.e(TAG, "onCreate: " + Thread.currentThread().getName());//main
    }

    @OnClick(R.id.id_btn_change)
    public void onViewClicked() {
        //新建线程
        new Thread() {
            @Override
            public void run() {
                Log.e(TAG, "onViewClicked: " + Thread.currentThread().getName());//Thread-24375
                 mIdTvHandler.setText("你身上有米粒!");//更改视图
            }
        }.start();
    }
}

2.结果:
9414344-f1ebb954395ef061.png
结果.png

看起来不太好,直接崩了,报了个CalledFromWrongThreadException:只有创建视图层的那个原始线程(main)才给摸他的视图。
是啊,我穿(main线程)的衣服(View)凭什么给你(其他线程)乱摸(修改...),你又不是我女朋友。

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

二、Handler的使用

人家(其他线程)就是看你衣服上有个米粒,想把他拿掉,你(main线程)还不乐意了。好吧,我找你女友(Handler)去,让她把你拿掉


public class HandlerActivity extends AppCompatActivity {
    private static final String TAG = "HandlerActivity";
    @BindView(R.id.id_tv_handler)
    TextView mIdTvHandler;
    @BindView(R.id.id_btn_change)
    Button mIdBtnChange;
    //新建Handler
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            String info = (String) (msg.obj);
            //更新UI
            mIdTvHandler.setText(info);
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler);
        ButterKnife.bind(this);
    }

    @OnClick(R.id.id_btn_change)
    public void onViewClicked() {
        new Thread() {
            @Override
            public void run() {
                //拿到一个Message对象--或直接new,但不建议new。Message.obtain()使用享元模式
                Message msg = Message.obtain();
                //将数据放到信息里
                msg.obj = "你身上有米粒!";
                //发送消息
                mHandler.sendMessage(msg);
                
                //或者
                //msg.obj = "你身上有米粒";
                使用handler.obtainMessage获得的msg 可以直接msg.sendToTarget()
                //msg.sendToTarget();
            }
        }.start();
    }
}
9414344-a55e4b586ae059b6.png
handler2.png

二、发送空消息
9414344-93051226c67cf3e1.png
empty.png
1.空消息
1-1:空消息要有一个标识
private int SEND_ID = 0;
1-2:发送空消息:
new Thread() {
     @Override
     public void run() {
         mHandler.sendEmptyMessage(SEND_ID);
     }
 }.start();
1-3:Handler根据接收的标识执行动作
 private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == SEND_ID) {
                mIdTvHandler.setText("你身上有米粒!");
            }
        }
    };
2.延迟空消息
 mHandler.sendEmptyMessageDelayed(SEND_ID,1000);
 //或:mHandler.sendEmptyMessageAtTime(SEND_ID, SystemClock.uptimeMillis()+1000);
9414344-ccc782149571fb85.gif
延迟.gif
3.同样sendMessage延迟类似:
mHandler.sendMessageDelayed(msg, 1000L);
mHandler.sendMessageAtTime(msg, SystemClock.uptimeMillis()+1000);

三、post发送消息:传入Runnable
9414344-8b058ffa8608dcae.png
post.png

通过mHandler反复发信息可做到循环

mRunnable = new Runnable() {
    @Override
    public void run() {
        index++;
        mIdTvHandler.setText("你身上有"+index+"個米粒");
        if (index < 10) {
            mHandler.postDelayed(this, 2000);
        }
    }
};

new Thread(){
    @Override
    public void run() {
        mHandler.postDelayed(mRunnable, 2000);
    }
}.start();
移除callback
if (mRunnable != null) {
    mHandler.removeCallbacks(mRunnable);
}

四、Activity方法:runOnUiThread

可见底层也是基于Handler机制的

9414344-3a73f868156d9bbb.png
runout.png
new Thread(){
    @Override
    public void run() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mIdTvHandler.setText("你身上有米粒!");
            }
        });
    }
}.start();

五、Handler和Timer结合
public class HandlerTimerActivity extends AppCompatActivity {
    private static final String TAG = "HandlerActivity";
    @BindView(R.id.id_tv_handler)
    TextView mIdTvHandler;
    @BindView(R.id.id_btn_change)
    Button mIdBtnChange;

    private final Timer timer = new Timer();
    private TimerTask task;
    int count = 0;

    Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            mIdTvHandler.setText("你身上有" + count + "個米粒!");
            super.handleMessage(msg);
        }
    };
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler);
        ButterKnife.bind(this);

    }

    @OnClick({R.id.id_tv_handler, R.id.id_btn_change})
    public void onViewClicked(View view) {
        switch (view.getId()) {
            case R.id.id_tv_handler:
                timer.cancel();
                
                break;
            case R.id.id_btn_change:

                task = new TimerTask() {
                    @Override
                    public void run() {
                        mHandler.sendEmptyMessage(0);
                        count++;
                    }
                };
                timer.schedule(task, 2000, 3000);
                break;
        }
    }
}


后记、
1.声明:

[1]本文由张风捷特烈原创,转载请注明
[2]欢迎广大编程爱好者共同交流
[3]个人能力有限,如有不正之处欢迎大家批评指证,必定虚心改正
[4]你的喜欢与支持将是我最大的动力

2.连接传送门:

更多安卓技术欢迎访问:安卓技术栈
我的github地址:欢迎star
简书首发,腾讯云+社区同步更新
张风捷特烈个人网站,编程笔记请访问:http://www.toly1994.com

3.联系我

QQ:1981462002
邮箱:1981462002@qq.com
微信:zdl1994328

4.欢迎关注我的微信公众号,最新精彩文章,及时送达:
9414344-c474349cd3bd4b82.jpg
公众号.jpg
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值