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

  • 相关阅读:
    统计一行字符串中每个字母个数
    不定宽高的文字在div中垂直居中
    转:Python 与 Excel 不得不说的事
    Centos 6安装python3.5
    day04
    day03
    Day02
    python ciscolib模块
    三级菜单
    模拟登陆系统
  • 原文地址:https://www.cnblogs.com/zhouyang209117/p/5323170.html
Copyright © 2011-2022 走看看