android之handler

android中handler的基本使用方法以及运行原理。

最近看mars的android重置版第二季的视频关于handler的讲解,让我对于这个以前知道怎么用,却不是很明白原理的组件的理解瞬间加深了无数倍。mars真的讲的很好,视频真的都蛮不错的。下面我写写自己学习到的知识,以及自己的了解。

  1. handler的基本运行原理
  2. handler怎样从worker thread传输数据到main thread
  3. handler怎样从main thread传输数据到worker thread
  4. handler的post()方法

handler的基本运行原理

为什么我们需要一个handler?我想这是一个最重要的问题,也就是说handler的作用到底是什么?handler主要是用于线程间的通信,那么问题又来了,为什么一个app中需要多个线程,而不是只有一个UI主线程就可以了呢?

假如app中只有一个UI主线程,那么,当需要进行网络连接,网络下载这些等待耗时较长的任务时,android系统就会检测到UI主线程长时间没有响应,就会发出一个 application not response的异常警告,简称ANR问题。所以,在UI主线程中,是要与用户实时交互的,不能出现长时间的等待问题。于是,这些任务必须在worker thread中进行。

然而根据android的设定,UI主线程之外的线程,(除了特别的控件,例如progressbar)不能修改UI里的控件的,这样又出现了新的问题,我们在子线程获得的数据,该如何反应的UI上与用户进行交互?这样,就出现了这个巧妙的组件,handler!

那么,handler到底是如何运行的呢?handler对象首先取出一个消息对象,存入到一个消息队列messagequeue中,然后在另外一端,有一个looper对象,循环的从消息队列中取出消息对象再交给handler去处理。

handler怎样从worker thread传输数据到main thread

public class MainActivity extends ActionBarActivity {

    private Handler handler;
    private Button button;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        button = (Button) findViewById(R.id.cancleButton);
//    点击button启动新线程
        button.setOnClickListener(new OnClickListener() {
            public void onClick(View arg0) {
                Thread thread = new Mythread();
                thread.start();

            }
        });
        handler = new Myhandler();
    }

//  复写hanlder中的handlerMessage方法,处理从消息队列中得到的消息
    class Myhandler extends Handler{
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            String s = msg.obj.toString();
            System.out.println("在当前线程中"+Thread.currentThread().getName()+"获得来自这个线程的消息"+s);
        }
    }

//  在worker thread中使用handler.obtainMessage()方法得到一个Message对象,再把消息存入message中,发入消息队列
    class Mythread extends Thread{
        @Override
        public void run() {
            Message msg = handler.obtainMessage();
            msg.obj = currentThread().getName();
            handler.sendMessage(msg);
        }
    }
}

通过这个例子,我们可以看到,handlerMessage()方法是运行在主线程中的,而他可以得到来自worker thread的消息,这样,就可以将消息在UI界面更新了。

为什么只是初始化了一个handler对象,就会自动调用他的handleMessage方法?是因为在android.os.Handler类中有一个looper对象,会循环的从消息队列中取出消息,调用handleM而是撒个方法。

handler怎样从main thread传输数据到worker thread

public class MainActivity extends ActionBarActivity {

    private Handler handler;
    private Button button;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        button = (Button) findViewById(R.id.cancleButton);

//      每点击一次button,给worker thread 发送一个消息
        button.setOnClickListener(new OnClickListener() {
            public void onClick(View arg0) {
//              在main中使用handler.obtainMessage()方法得到一个Message对象,再把消息存入message中,发入消息队列
                Message msg = handler.obtainMessage();
                msg.obj = Thread.currentThread().getName();
                handler.sendMessage(msg);
            }
        });
        Thread thread = new Mythread();
        thread.start();


    }

//  复写hanlder中的handlerMessage方法,处理得到的消息
    class Myhandler extends Handler{
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            String s = msg.obj.toString();
            System.out.println("在当前线程中"+Thread.currentThread().getName()+"获得来自这个线程的消息"+s);
        }
    }

//  work thread 接受这个消息,并调用handleMeesage()方法处理消息
    class Mythread extends Thread{
        @Override
        public void run() {
//      looper对象的loop方法从消息队列中取出消息,调用handleMeesage()方法处理消息
            Looper.prepare();
            handler = new Myhandler();
            Looper.loop();
        }
    }
}


通过运行结果可以知道,handleMessage()方法运行在worker thread中,这样就可以在worker thread中处理来自主线程的消息,实现了进程间的通信。

handler的post()方法

post方法通过生成一个message,然后把Runnable对象放在message中,再把message放在消息队列中,然后在主线程中取出这个Runnable对象,在主线程中执行。

public class MainActivity extends ActionBarActivity {

    private Handler handler;
    private Button button;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        button = (Button) findViewById(R.id.cancleButton);
//      初始化handler,处理得到的Runnable对象
        handler = new Handler();

//      点击按钮执行worker thread
        button.setOnClickListener(new OnClickListener() {
            public void onClick(View arg0) {
                Thread thread = new Mythread();
                thread.start();
            }
        });

    }
    class Mythread extends Thread{
        @Override
        public void run() {
//          在worker thread 中初始化一个Runnable对象
            Runnable runnable = new Runnable() {
                public void run() {
//          打印出该Runnable方法执行的线程    
                    System.out.println("当前线程名"+Thread.currentThread().getName());
                }
            };
//          post该Runnable对象
            handler.post(runnable);
        }
    }
}

最后的结果,是这个Runnable对象执行在main线程中。有了post()方法,我们可以直接在worker thread中先生成一个Runnable对象,然后在其中写上更新UI的代码,直接用post方法即可更新UI。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。