Quantcast
Channel: CSDN博客移动开发推荐文章
Viewing all articles
Browse latest Browse all 5930

Handler的常用场景总结

$
0
0

1、安卓为什么只能通过消息机制更新UI呢?

最根本的目的就是解决多线程并发问题。(多个线程同时执行一个任务)

假如在一个Activity中,有多个线程去更新UI,并且都没有加锁机制,那就会造成更新UI错乱。如果对更新UI的操作都进行加锁处理,就会造成性能下降。使用消息机制,根本不用关系多线程的问题,因为更新UI的操作,都是在主线程的消息队列当中去轮询处理的

2、Handler是什么?

Handlerandroid提供的一套更新UI的机制,也是消息处理机制,我们可以用它发送消息,也可以通过它处理消息。

更新UI,传递消息,处理消息。

3、默认情况下Handler会与其被定义时所在线程的Looper绑定,比如,Handler在主线程中定义,那么它是与主线程的Looper绑定。

注意Handler的构造函数,New Handler()什么参数都不需要

/**
 * Created on 2016/9/23.
 * Author:crs
 * Description:测试消息机制:主要用于线程间通讯,注意Handler类的构造函数
 * 1)一个完整的消息要包括消息标识和消息内容.(消息对象里面包含消息消息标识和消息内容;如果是空消息,只有消息标识没有消息体)
 *
 * 2)只有在原生线程(主线程)才能更新UI,在子线程更新UI会报错。
 *
 * 3)使用消息机制更新UI的模板性代码:创建Handler实例,在子线程中调用post方法,就两步操作。
 * handler.post(r): r是要执行的任务代码,意思就是说r的代码实际是在UI线程执行的,可以写更新UI的代码。
 *
 * 4)使用消息机制更新UI的模板性代码:创建Handler实例,重写handleMessage()方法,创建消息对象并进行信息传递即可。
 * obtainMessage() Message类 arg1 arg2 sendMessage(message实例) sendToTarget(); sendEmptyMessage()
 *
 * 5)使用消息机制实现图片轮播:创建Handler实例,创建Runnable接口实例,调用postDelayed(runnable实例,毫秒值);
 * removeCallbacks(Runnable),就这几步常规的操作
 *
 * 6)创建Handler的时候,指定callBack;可以通过CallBack截获Handler传递的消息.
 */

案例一:安卓中更新UI的四种方式

package com.crs.demo.ui.handler;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.crs.demo.R;
import com.crs.demo.base.BaseActivity;

/**
 * Created on 2016/10/9.
 * Author:crs
 * Description:安卓中四种更新UI的方式
 * 1)handler.post()
 * 2)handler.sendMessage()
 * 3)runOnUIThread()
 * 4)View.post
 */
public class TestUpdateUIActivity extends BaseActivity {

    private static final int SUCCESS_GET_DATA = 1;
    private Handler mHandler = new Handler();
    private Handler myHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case SUCCESS_GET_DATA: {
                    tv_activity_test_update_ui.setText("使用handler.sendMessage()更新");
                }
                break;
            }
        }
    };
    private TextView tv_activity_test_update_ui;

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

        initViews();
    }

    private void initViews() {
        tv_activity_test_update_ui = findView(R.id.tv_activity_test_update_ui);
        Button btn_test_handler1 = findView(R.id.btn_test_handler1);
        Button btn_test_handler2 = findView(R.id.btn_test_handler2);
        Button btn_test_handler3 = findView(R.id.btn_test_handler3);
        Button btn_test_handler4 = findView(R.id.btn_test_handler4);

        //第一种方式:在子线程中调用runOnUIThread()更细UI
        btn_test_handler1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                tv_activity_test_update_ui.setText("调用runOnUIThread方法更新");
                            }
                        });
                    }
                }).start();

            }
        });

        //第二种方式:使用View的post()更新UI
        btn_test_handler2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                tv_activity_test_update_ui.post(new Runnable() {
                    @Override
                    public void run() {
                        tv_activity_test_update_ui.setText("使用View的post()更新UI");
                    }
                });

            }
        });

        //第三种方式:使用Handler的post()更新UI
        btn_test_handler3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        mHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                tv_activity_test_update_ui.setText("Handler的post()更新UI");
                            }
                        });
                    }
                }).start();
            }
        });

        //第四种方式:使用Handler的sendMessage()更新UI
        btn_test_handler4.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        //Message message = new Message();
                        //Message message = myHandler.obtainMessage();
                        myHandler.sendEmptyMessage(SUCCESS_GET_DATA);
                    }
                }).start();
            }
        });
    }
}
案例二:拦截Handler传递的消息

package com.crs.demo.ui.handler;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;

import com.crs.demo.R;
import com.crs.demo.base.BaseActivity;
import com.crs.demo.utils.ToastUtils;

/**
 * Created on 2016/10/8.
 * Author:crs
 * Description:测试创建Handler指定CallBack
 */
public class TestCallBackActivity extends BaseActivity {

    private Handler mHandler = new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            //可以通过CallBack截获Handler传递的消息,返回值表示是否截获消息,false表示不截获。
            ToastUtils.showShort(TestCallBackActivity.this, "1");
            //如果设置为true,就表示截获消息,后面的handleMessage()就不在继续执行了,即2不会被打印了。
            return false;
        }
    }) {
        @Override
        public void handleMessage(Message msg) {
            ToastUtils.showShort(TestCallBackActivity.this, "2");
        }
    };

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

        initViews();
    }

    private void initViews() {
        Button btn_activity_test_call_back = findView(R.id.btn_activity_test_call_back);
        btn_activity_test_call_back.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mHandler.sendEmptyMessage(1);
            }
        });
    }
}
案例三:使用Handler实现图片轮播效果

package com.crs.demo.ui.handler;

import android.os.Bundle;
import android.os.Handler;
import android.widget.ImageView;

import com.crs.demo.R;
import com.crs.demo.base.BaseActivity;

/**
 * Created on 2016/10/8.
 * Author:crs
 * Description:使用消息机制实现图片轮播效果
 * 关键是练习消息机制的使用
 */
public class TestPostDelayedActivity extends BaseActivity {

    int[] image = {R.drawable.iv_1, R.drawable.iv_2, R.drawable.iv_3};
    int index;
    private ImageView iv_test_post_delayed;

    //1)创建Handler实例
    private Handler mHandler = new Handler();
    //2)创建Runnable实例
    private MyRunnable myRunnable = new MyRunnable();


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test_post_delayed);
        iv_test_post_delayed = findView(R.id.iv_test_post_delayed);

        //3)调用此方法实现定时器效果
        mHandler.postDelayed(myRunnable, 1000);
    }

    //实现接口
    class MyRunnable implements Runnable {
        @Override
        public void run() {
            index++;
            //余数只有三种类型0、1、2
            index = index % 3;
            //每隔多少秒要做的事(业务逻辑)
            iv_test_post_delayed.setImageResource(image[index]);
            mHandler.postDelayed(this, 1000);
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        //清除此定时器效果
        mHandler.removeCallbacks(myRunnable);
    }
}
案例四:自定义与线程相关的handler

package com.crs.demo.ui.handler;

import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;

import com.crs.demo.R;
import com.crs.demo.base.BaseActivity;
import com.crs.demo.utils.LogUtils;

/**
 * Created on 2016/10/9.
 * Author:crs
 * Description:自定义与线程相关的Handler
 */
public class TestCustomHandlerActivity extends BaseActivity {

    private static final String TAG = "TestCustomHandler";
    private MyThread myThread;
    //创建主线程Handler
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            LogUtils.i(TAG, Thread.currentThread() + "主线程");
        }
    };


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



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

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

        //主线程中的Handler
        mHandler.sendEmptyMessage(1);

        //子线程中的Handler
        myThread.myHandler.sendEmptyMessage(2);
    }


    class MyThread extends Thread {
        private Handler myHandler;

        @Override
        public void run() {
            super.run();
            Looper.prepare();
            myHandler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    LogUtils.i(TAG, Thread.currentThread() +"子线程");
                }
            };
            Looper.loop();
        }
    }
}

Handler的原理是什么?

1)Handler封装了消息的发送,主要包括消息发送给谁。

2)Looper:内部包含一个消息队列,也就是MessageQueue,所有Handler发送的消息都会走向这个消息队列。

Looper类中有一个loop()方法,它不断的从MessageQueue中取消息,如果有消息就处理消息,如果没有消息就阻塞。

3)MessageQueue就是一个消息队列,可以添加消息、移除消息。

4)Handler内部会和Looper进行关联,在Handler内部可以找到Looper。使用Handler发送消息,其实就是向MessageQueue队列中发送消息。

总结:handler负责发送消息,Looper负责接收Handler发送的消息,并直接发消息传回给handler自己、MessageQueue就是一个存储消息的容器、looper是循环器。


消息标识与消息内容(int类型和对象类型)

如何获取一个Message对象?

Handler的两种作用:发送消息、传递消息.

MessageHandler之间的关系  sendToTarget()

Handler移除一个事件,停止事件的执行removeCallBack(runnable实例)

发送一个空消息的目的是什么原理是什么

截获Handler发送的消息  new CallBack()

作者:chenrushui 发表于2016/10/9 10:37:58 原文链接
阅读:41 评论:0 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>