Android学习笔记:关于Handler的详解(二)

4.Handler移除消息
handler不只能发送一个消息,而且还能移除消息。当我们调用handler.post()方法时,调用handler.removeCallbacks(myRunnable)方法,可以移除正在调用的对象。当调用handler.sendMessage()方法时,可以通过调用
handler.removeMessages(int )方法移除正在调用的对象;

实例五:拦截消息
布局代码:

"http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="100dp"
        android:text="hello" />
    

java逻辑代码:

public class MainActivity extends Activity implements OnClickListener{
    private Button intercept,send;
    private TextView tv;
    Handler handler = new Handler(){
        public void handleMessage(Message msg) {
            if (msg.what ==1) {
                tv.setText(msg.obj+"");
            }
        }
    };
    @Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        intercept = (Button)findViewById(R.id.intercept);
        send = (Button)findViewById(R.id.send);
        send.setOnClickListener(this);
        intercept.setOnClickListener(this);
        tv = (TextView)findViewById(R.id.textView1);
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.send:
            new Thread(){
              public void run() {
                Message msg = handler.obtainMessage();
                msg.what = 1;
                msg.obj = "你拦截不到,哈哈哈";
                handler.sendMessageDelayed(msg, 5000);
                }
            }.start();
            break;
        case R.id.intercept:
            //移除一条信息
            handler.removeMessages(1);
            break;
        default:
            break;
        }
    }
}

5.Handler移除消息内容
上述的例子展示的是handler如何移除一条消息的对象,除此之外我们也可以拦截消息内容。

实例六:拦截消息内容
布局代码:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
        android:id="@+id/send"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:onClick="send"
        android:text="发送消息" />
RelativeLayout>

java逻辑代码:

public class MainActivity extends Activity {
//传递消息内容的拦截,返回值为false不拦截,为true就拦截   
    Handler handler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            Log.i("tag", "handle--1:"+msg.arg1);
            if (msg.what>100) {
                return false;
            }
            return true;
        }
    }){
        public void handleMessage(Message msg) {
            Log.i("tag", "handle--2:"+msg.arg1);
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    public void send(View view){
        new Thread(){
            public void run() {
                Message message = Message.obtain();
                message.arg1 = 98;
                handler.sendMessage(message);
            }
        }.start();
    }
}

初始化handler的对象时,传入callback参数,重写callback中的handlemessage的方法,如果返回值设置为false不拦截消息,如果返回值设置为true,则拦截。

6.Handler的原理是什么?

Handler封装了消息的发送,主要包括消息发送给谁
Looper类主要用于一个线程循环获取消息队列中的消息。
Looper的作用主要是负责管理消息队列,负责消息的出列和入列操作。
MessageQueue:就是一个消息队列,可以添加消息,并处理消息。
Message是线程之间传递信息的载体,包含了对消息的描述和任意的数据对象。
总结:
Handler 负责发送消息,looper负责接收handler发送的消息,并直接把消息传递给handler自己,MessageQueue就是一个存储消息的容器。
Looper的知识:
1.每个线程有且最多只能有一个Looper对象,它是一个ThreadLocal
2.Looper内部有一个消息队列,loop()方法调用后线程开始不断从队列中取出消息执行
3.Looper使一个线程变成Looper线程。

7. 如何实现一个与线程相关的handler
所谓的消息机制其实很简单,实现这种机制需要只需要五步:
1、调用Looper.prepare(),线程变成循环线程;
2、实例化Handler,这里需要覆盖handleMessage方法,处理收到的消息;
3、 调用Looper.loop();使线程进入循环;
4、 实例化Message对象,调用已经实例化好的handler对象的obtainMessage方法,把数据传给obtainMessage方法,obtainMessage方法就会实例化一个Message对象。(这里也可以发送实现Runnable接口的对象);
5、调用Handler的sendMessage方法把实例化好的Message对象发送出去。

实例七:如何实现一个handler与自定义线程相关联
逻辑代码:

public class MainActivity extends Activity {
    MyThread thread;
    Handler handler = new Handler(){
        public void handleMessage(Message msg) {
            Log.i("tag", "Thread:"+Thread.currentThread().getName());
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        thread = new MyThread();
        thread.start();
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        thread.handler.sendEmptyMessage(1);
        handler.sendEmptyMessage(1);
    }
    class MyThread extends Thread{
        public Handler handler;
        @Override
        public void run() {
            super.run();
            Looper.prepare();   //把普通线程变成looper线程
            handler = new Handler(){
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    Log.i("tag", "Thread:"+Thread.currentThread().getName());
                }
            };
            Looper.loop();  //使looper线程循环
        }
    }
}

初学者在学习handler消息机制时,往往会产生一个误区,认为只有主线程才有handler,才能够实现通信,通过上面的例子,我们可以看出在子线程中同样也有handler,但是需要实现线程添加looper,才能够得到该线程中的handler。

8. Android中更新ui的几种方式。

handler post( );
handler sendMessage( );
view post( );
runOnUiThread( );
包含以上四种方式,前两种与handler相关。第三种一般在主线程中调用,避免因为线程嵌套出现线程错乱的现象,第四种会回到主线程中执行。

实例八:Android中更新ui的方式
逻辑代码:

public class MainActivity extends Activity {
    private TextView tv;
     Handler handler = new Handler(){
        public void handleMessage(Message msg) {
            tv.setText("handler sendmessage update ui");
         }
     };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv = (TextView)findViewById(R.id.tv);
//      new Thread(){
//          public void run() {
//              handlerSendMessage();    //第一种
//              handlerPost();           //第二种
//              runOnUiThreadUpdateUi(); //第三种
//          }
//      }.start();
        viewPost();                 //第四种
    }
    /***
     * 通过handler的sendMessage发送数据,更新ui
     * */
    public void handlerSendMessage(){
        handler.sendEmptyMessage(1);
    }
    /***
     * 通过handler的post方法,更新ui
     * */
    public void handlerPost(){
        handler.post(new Runnable() {
            @Override
            public void run() {
                tv.setText("handler post update ui");
            }
        });
    }
    /**
     * runOnUiThreadUpdateUi回到主线程,更新ui
     * */
    public void runOnUiThreadUpdateUi(){
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                tv.setText("runOnUiThread update ui");
            }
        });
    }
    /**
     * view的post方法,更新ui
     * */
    public void viewPost(){
        tv.post(new Runnable() {
            @Override
            public void run() {
                tv.setText("view post update ui");
            }
        });
    }
}

以上为handler的使用方法和消息处理机制的原理,更多相关代码资源请下载:
http://download.csdn.net/detail/u012156341/9447357

你可能感兴趣的:(Android学习笔记)