Android 平台不允许Activity启动的新线程访问该Activity中的界面组件,这样新启动的线程就无法改变界面组件的属性值。在这种情况下需要借助Handler消息传递机制来实现。

Handler类的作用:

  • 在新启动的线程中发送消息
  • 在主线程中获取消息,处理消息

为了让主线程能够在合适的时间获取的新线程发来的消息,只能通过回调的机制来实现,我们需要重写Handler类中处理消息的方法,当新启动的线程发送消息时,Handler类中处理消息的方法被自动回调。

Handler类中包含的的常用方法主要有以下几个
void handleMessage(Message msg):处理消息的方法,通常被重写
final boolean hasMessages(int what):检查消息队列中,是否包含what属性指定的消息
final boolean hasMessages(int what, Object object):检查消息队列中,是否包含what属性和object属性指定值的消息
Message obtainMessage():该函数具有多个重载,用于获取消息
sendEmptyMessage(int what):立即发送空消息
final boolean sendEmptyMessageDelayed(int what, long delayMills):指定delayMills毫秒后发送空消息
final boolean sendMessage(Message msg):立即发送消息
final boolean sendMessageDelayed(Message msg, long delayMills):指定多少毫秒后发送消息

package me.lightless.handletest;

import android.app.Activity;
import android.os.Bundle;
import android.os.Message;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ImageView;

import java.util.Timer;
import java.util.TimerTask;
//import java.util.logging.Handler;
import java.util.logging.LogRecord;


public class MyActivity extends Activity {

    int[] imageIds = new int[] {
            R.drawable.ajax,
            R.drawable.classic,
            R.drawable.ee,
            R.drawable.ic_launcher,
            R.drawable.java,
            R.drawable.xml
    };
    int currentImageId = 0;

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

        // Get ImageView
        final ImageView show = (ImageView)findViewById(R.id.show);

        final Handler myHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                if (msg.what == 0x1233) {
                    show.setImageResource(imageIds[currentImageId++]);
                    if (currentImageId >= 5) {
                        currentImageId = 0;
                    }
                }
            }
        };

        // Set a timer to execute sth
        new Timer().schedule(new TimerTask() {
            @Override
            public void run() {
                Message msg = new Message();
                msg.what = 0x1233;
                myHandler.sendMessage(msg);
            }
        }, 0, 800)
;
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.my, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}