Android中的Handler使用方式

一、什么是Handler



Handler是Android中引入的一种让开发者参与处理线程中消息循环的机制。每个Hanlder都关联了一个线程,每个线程内部都维护

一个消息队列MessageQueue,这样Handler实际上也就关联了一个消息队列。可以通过Handler将Message和Runnable对象发

送到该Handler所关联线程的MessageQueue(消息队列)中,然后该消息队列一直在循环拿出一个Message,对其进行处理,处

理完之后拿出下一个Message,继续进行处理,周而复始。当创建一个Handler的时候,该Handler就绑定了当前创建Hanlder的线

程。从这时起,该Hanlder就可以发送Message和Runnable对象到该Handler对应的消息队列中,当从MessageQueue取出某个

Message时,会让Handler对其进行处理。



二、Handler作用



Handler可以用来在多线程间进行通信,在另一个线程中去更新UI线程中的UI控件只是Handler使用中的一种典型案例,除此之外,

Handler可以做很多其他的事情。每个Handler都绑定了一个线程,假设存在两个线程ThreadA和ThreadB,并且HandlerA绑定了

 ThreadA,在ThreadB中的代码执行到某处时,出于某些原因,我们需要让ThreadA执行某些代码,此时我们就可以使用

Handler,我们可以在ThreadB中向HandlerA中加入某些信息以告知ThreadA中该做某些处理了。由此可以看出,Handler是

Thread的代言人,是多线程之间通信的桥梁,通过Handler,我们可以在一个线程中控制另一个线程去做某事。



三、主线程中的Handler



下面的Handler是主线程中的Handler,因为其是在主线程中创建的,所以默认就是和主线程进行绑定的,通过一个延时的POST方法来进行UI的循环更新。

public class MainActivity extends AppCompatActivity {

    private Handler handler = new Handler();

    private  int images[] = new int[]{R.drawable.im1, R.drawable.im2, R.drawable.im3};
    private int index = 0;

    private MyRunnable myRunnable = new MyRunnable();
    private ImageView im_debug;

    class MyRunnable implements Runnable{

        @Override
        public void run() {
            index++;
            index = index % 3;

            im_debug.setImageResource(images[index]);
            handler.postDelayed(myRunnable, 1000);
        }
    }
    

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        im_debug = (ImageView) findViewById(R.id.im_debug);
        handler.postDelayed(myRunnable, 1000);
    }
    
}



四、两种Handler发消息



如下是Handler的两种绑定方式,一个和主线程进行绑定,一个和子线程进行绑定,这两个分别向主线程的Handler和子线程的

Handler发消息就可以得到得到其线程的ID,并且子线程中建立Looper

public class SecondActivity extends Activity {

    private MyThread thread;

    //默认是在主线程中执行
    public Handler uiHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            System.out.print("UI-----"+Thread.currentThread());
        }
    };

    //在子线程中执行
    class MyThread extends Thread{
        public Handler hander;

        public void run(){
            Looper.prepare();
            hander = new Handler(){
                @Override
                public void handleMessage(Message msg) {
                    System.out.print("CurrentID = "+Thread.currentThread());
                }
            };
            Looper.loop();
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        TextView tv = new TextView(this);
        tv.setText("hello Handler");
        setContentView(tv);

        thread = new MyThread();
        thread.start();

        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        //向子线程发消息
        thread.hander.sendEmptyMessage(1);

        //向主线程发消息
        uiHandler.sendEmptyMessage(1);
    }
    
}



五、HandlerThread使用



HandlerThread建立的线程是在子线程中的,建立子线程的Handler的时候要绑定一个Looper

public class ThreeActivity extends Activity {

    private HandlerThread thread;
    private Handler handler;
    private static final String TAG = "ThreeActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        TextView tv = new TextView(this);
        tv.setText("Handler Thread Handler");
        setContentView(tv);

        //HandlerThread中使用了同步机制了
        thread = new HandlerThread("handlerThread");
        thread.start();

        //如果looper为空,就处于等待的状态,直到Handler可以拿到looper对象
        //这个是子线程的Handler
        handler = new Handler(thread.getLooper()){
            @Override
            public void handleMessage(Message msg) {
                System.out.print("当前线程:"+Thread.currentThread());
                Log.i(TAG, "当前线程"+Thread.currentThread());
            }
        };

        handler.sendEmptyMessage(1);
    }
}



六、Handler更新UI



Handler提供了两种方式解决我们在本文一开始遇到的问题(在一个新线程中更新主线程中的UI控件),一种是通过post方法,一

种是调用sendMessage方法。

public class FiveActivity extends Activity {

    private TextView tv_five;

    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            tv_five.setText("OK了方法2");
        }
    };

    public void handler1(){
        //这个是第一种方式来更新UI
        //本质上也是发送message
        handler.post(new Runnable() {
            @Override
            public void run() {
                tv_five.setText("OK了方法1");
            }
        });
    }

    public void handler2(){
        handler.sendEmptyMessage(1);
    }

    public void handler3(){
        //内部还是通过UI机制
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                tv_five.setText("OK了方法3");
            }
        });
    }

    public void handler4(){
        //
        tv_five.post(new Runnable() {
            @Override
            public void run() {
                tv_five.setText("OK了方法4");
            }
        });
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_five);

        tv_five = (TextView) findViewById(R.id.tv_five);

        new Thread(){
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                    //分别在此处调用不同的更新UI的方法
                    handler4();

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }
}

其实最常用的还是那两种方式, 虽然Message的构造函数式public的,我们还可以通过Message.obtain()或

Handler.obtainMessage()来获得一个Message对象(Handler.obtainMessage()内部其实调用了Message.obtain())。 







详细的介绍请参考下面两篇文章,写的很好:


http://blog.csdn.net/iispring/article/details/47115879

http://blog.csdn.net/iispring/article/details/47180325



你可能感兴趣的:(【安卓,基础】)