Handler小例子逐步深入理解一

对Android稍有了解的都知道Handle机制,然而我学了一段时间后,发现如果不看书,就是自己敲,连一个简单的demo都搞不定。不爽。这个暑假决定Android中几大机制和四大组件可以随意就写出来一些简单或复杂的demo来。
书归正传。
(1)现在想实现一个简单的demo,就是在子线程中更改UI线程,只是单次修改。示例代码如下:

public class MainActivity extends Activity {
    private TextView info;
    private static int sum = 0;
    ChildThread childThread = null;
    private Handler mMainHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
                            info.setText(mMainHandler.getLooper().getThread().getName()
                    + "的Handler收到了消息,消息内容是:"
                    + msg.obj);
        }
    };


    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(R.layout.activity_main);
        info = (TextView) findViewById(R.id.info);
        childThread = new ChildThread();
        childThread.setName("childThread");
        childThread.start();
    }


    private class ChildThread extends Thread {
        public void run() {
            try {
                sum++;
                sleep(2000);//模拟一个耗时操作,sum是计算结果
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //这里产生message调用obtainMessage直接从接收消息对象的Hanler的消息池中获得而不是new Message,效率高
            Message message = mMainHandler.obtainMessage(0x11, 0, 0, Thread.currentThread().getName() + "发送了" + sum + "给主线程");
            message.sendToTarget();//将消息发送给主线程
        }

    }
}

这一段代码实现的功能非常简单,就是创建了一个子线程来完成耗时计算,然后将结果显示在主界面的TextView里,最后输出结果如图所示:
这里写图片描述
本程序实现的功能就是在子线程中动态修改UI线程,但是只能更新一次。(2)接下来我们实现一个可以循环动态更新UI线程的demo,使用的不仅仅是Message.sendToTarget(),还有Handler.post(Runnable)方法。
示例代码如下:

public class MainActivity extends Activity {
    private TextView info;
    private static int sum = 0;
    private Handler mMainHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            info.setText(mMainHandler.getLooper().getThread().getName()
                    + "的Handler收到了消息,消息内容是:"
                    + msg.obj);
            System.out.println("Handler属于-----" + mMainHandler.getLooper().getThread().getName()
                    + "传递的sum值是:" + msg.obj);
            mMainHandler.postDelayed(runnable, 1000);//处理消息1秒后再次执行run()方法,从而实现循环更新TextView
        }
    };
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            Message message = mMainHandler.obtainMessage(0x11, 0, 0, sum++);
            message.sendToTarget();
            System.out.println("执行run()方法的线程是---" + Thread.currentThread().getName());
        }
    };
    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(R.layout.activity_main);
        info = (TextView) findViewById(R.id.info);
        mMainHandler.postDelayed(runnable, 2000);//第一次启动run()方法延时较长
    }
}

这样主线程的handler就会每隔一秒处理run()方法中的发送的消息,根据发送的消息来更新TextView,输出如下:
这里写图片描述
我们会发现虽然相比第一个demo,实现了动态循环更新,但是执行run()方法的却变成了main线程,这样虽然迁就了Handle机制,但是却阻塞主线程,不是我们要的结果。
(3)所以我们再改改程序功能,就是实现动态循环子线程执行耗时操作,将结果交给main线程Handler,从而实现UI更新。
示例代码如下:

public class MainActivity extends Activity {
    private TextView info;
    private static int sum = 0;
    ChildThread childThread;
    private Handler mMainHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            info.setText(mMainHandler.getLooper().getThread().getName()
                    + "的Handler收到了消息,消息内容是:"
                    + msg.obj);
            System.out.println("Handler属于-----" + mMainHandler.getLooper().getThread().getName()
                    + "传递的sum值是:" + msg.obj);

        }
    };
    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(R.layout.activity_main);
        info = (TextView) findViewById(R.id.info);
        childThread = new ChildThread("childThread");
        childThread.start();
    }

    private class ChildThread extends Thread {//将耗时的操作放在子线程中完成
        public ChildThread(String name) {//参数是Runnable和线程名字的构造函数
            super(name);
        }
        public void run() {
            for (int i = 0; i < 10; i++) {
                Message message = mMainHandler.obtainMessage(0x11, 0, 0, sum++);
                message.sendToTarget();
                System.out.println("执行run()方法的线程是---" + Thread.currentThread().getName());
                try {
                    sleep(1000);//每次更新停顿一下
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }
    }
}

输出如下:
这里写图片描述
我们可以看到Handler属于main线程,而执行run()方法的是childThread,并且实现了动态更新。那么,可能有同学会问,为什么不能使用new Thread(Runnable)使得执行run()方法的是子线程??其实这也是可以的,我们可以这样实现:

public class MainActivity extends Activity {
    private TextView info;
    private static int sum = 0;
    ChildThread childThread;
    private Handler mMainHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            info.setText(mMainHandler.getLooper().getThread().getName()
                    + "的Handler收到了消息,消息内容是:"
                    + msg.obj);
            System.out.println("Handler属于-----" + mMainHandler.getLooper().getThread().getName()
                    + "传递的sum值是:" + msg.obj);

        }
    };
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                Message message = mMainHandler.obtainMessage(0x11, 0, 0, sum++);
                message.sendToTarget();
                System.out.println("执行run()方法的线程是---" + Thread.currentThread().getName());
                try {
                    Thread.sleep(1000);//每次更新停顿一下
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };
    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        setContentView(R.layout.activity_main);
        info = (TextView) findViewById(R.id.info);
        childThread = new ChildThread(runnable, "childThread");//将定义好操作的Runnable作为参数传给子线程构造函数
        childThread.start();
    }
    private class ChildThread extends Thread {//将耗时的操作放在子线程中完成

        public ChildThread(Runnable target, String name) {//参数是Runnable和线程名字的构造函数
            super(target, name);
        }

    }
}

输出如下:
这里写图片描述
ok~~我们发现输出和上面的demo是没差的~.
总结一下:
1.如果使用Handler来定时修改界面,就可以使用post的方法,但是执行该post方法的只能是Main线程,因为只有Main线程才可以动态修改UI
2.如果想要传数据给UI线程,可以使用sendMessage的方法。将数据传给Main线程的handler。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值