zoukankan      html  css  js  c++  java
  • android学习11——Handler,Looper,MessageQueue工作原理

    Message是Handler接收和处理的消息对象. 每个线程只能拥有一个Looper.它的loop方法读取MessageQueue中的消息,读到消息之后就把消息交给发送该消息的Handler进行处理.MessageQueue是消息队列,它采用先进先出的方式来管理Message.程序创建Looper对象时会在它的构造器中创建MessageQueue对象.
    下面用一个例子说明.不能在主线程中执行耗时的工作,否则会报ANP错误.常用的方法是在主线程中向子线程中发消息,交给子线程处理.看下面的例子.

    public class SumThread extends Thread {
        private Handler handler;
        private Context context;
        public SumThread(Context context) {
            this.context = context;
        }
        @Override
        public void run() {
            Log.i("Logzy", "Loop prepare");
            Looper.prepare();
            handler = new SumHandler(context);
            Looper.loop();
            Log.i("Logzy", "Loop end");
        }
    
        public Handler getHandler() {
            return handler;
        }
    }
    

    在子线程中创建一个Handler.注意在子线程中创建Handler的时候,要先创建Looper对象,并通过prepaer启动它. Looper.loop()是一个死循环,不断从MessageQueue中取出消息交给Handler处理.所以除非显式退出Looper,Log.i("Logzy", "Loop end")这行代码不会被执行.另外需要注意的一点是在主线程中,系统已经初始化一个Looper对象,因此程序直接创建Handler即可,然后就可通过Handler来发送,处理消息.主线程中创建Handler的方法见这个例子http://www.cnblogs.com/zhouyang209117/p/5108048.html
    例子的源代码:https://github.com/zhouyang209117/AndroidTutorial/tree/master/Crazy/ch3/Loop
    再说HandlerThread的用法.上面已经提到子线程中创建Handler的时候,要先创建Looper对象,并通过prepaer启动.HandlerThread可以将这些操作简化.看下面代码:

    public class MyActivity extends Activity {
        static final String UPPER_NUM = "upper";
        EditText etNum;
        private Handler handler;
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            etNum = (EditText)findViewById(R.id.etNum);
            HandlerThread handlerThread = new HandlerThread("aaa");
            handlerThread.start();
            handler = new SumHandler(this, handlerThread.getLooper());
        }
        
        public void cal(View source) {
            Message msg = new Message();
            msg.what = 0x123;
            Bundle bundle = new Bundle();
            bundle.putInt(UPPER_NUM,
                    Integer.parseInt(etNum.getText().toString()));
            msg.setData(bundle);
            handler.sendMessage(msg);
        }
    }
    

    最重要的是这3行代码:

    HandlerThread handlerThread = new HandlerThread("aaa");
    handlerThread.start();
    handler = new SumHandler(this, handlerThread.getLooper());
    

    HandlerThread也是一个线程.通过start()启动,里面的Looper就已经初始化好了再调用handler = new SumHandler(this, handlerThread.getLooper()),可以启动Looper,不用再显式启动.这样简化了代码.
    源代地址:https://github.com/zhouyang209117/AndroidTutorial/tree/master/Crazy/ch3/HandlerThread

  • 相关阅读:
    js调用oc方法 UIWebView 跳 到另一个UIWebView
    可变cell,自适应cell,理解iOS 8中的Self Sizing Cells和Dynamic Type
    设置textField的placeholder字体的颜色,默认是灰色
    设置按钮(UIButton)为圆角矩形
    UITextView限制输入字数
    如何更好地限制一个UITextField的输入长度
    uitableview style类型为Grouped时,去掉上面空白的方法
    python note 01 计算机基础与变量
    Leetcode61.旋转链表
    Leetcode 430. 扁平化多级双向链表
  • 原文地址:https://www.cnblogs.com/zhouyang209117/p/5323170.html
Copyright © 2011-2022 走看看