Android~Handler机制DEMO示例

来源:互联网 发布:服务器防火墙开放端口 编辑:程序博客网 时间:2024/06/05 16:19

大家好,在上一篇中我给大家介绍了Android~Handler机制的自我理解,那么在这一篇中我将会用代码DEMO示例演示Handler机制使用方法。

好了,我们废话不多说直接写起来!

1)我们首先新建一个工程handlerDemo,工程目录如下:


2)在activity_main.xml中,我们设置一个TextView控件,显示文本控件,代码如下:


好了,到现在框架搭建起来了,接下来开始在MainActivity类开始编写Handler机制用法。

第一:主线程自我更新界面

private Handler mHandler;
private TextView textview;
</pre><p>在onCreate方法中添加代码:</p><pre>
</pre><pre name="code" class="java">
textview = (TextView) findViewById(R.id.textview);mHandler = new Handler();mHandler.post(new Runnable() {<span style="white-space:pre"></span>@Overridepublic void run() {<span style="white-space:pre"></span>textview.setText("post");}});

我们分析TextView初始化文本内容是“文本控件”,我们mHandler.post请求修改界面内容,如果TextView内容显示post,表示请求成功,否则表示请求失败。我们运行程序如下:


从运行显示中我们可以观察到mHandler.post请求界面成功。

第二:子线程发送数据给主线程

我们在onCreate方法中添加如下代码:

new Thread(new Runnable() {@Overridepublic void run() {try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}textview.setText("child Thread");}}).start();
运行程序,程序报出经典错误!

原因就是我们在子线程中更新UI了!

那么我们应该怎么去写代码更新界面UI呢?这个时候我们就应该需要使用Handler机制

我们需要修改onCreate方法中的代码,首先我们需要添加另外一个Handler,该Handler专门负责和新建线程Thread相关联。

private Handler threadHandler;
new Thread(new Runnable() {@Overridepublic void run() {try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}threadHandler = new Handler();Message msg = threadHandler.obtainMessage();msg.what = 1;msg.obj = "treadhandler";mHandler.sendMessage(msg);}}).start();
我们看到了threadHandler从新建线程Thread中取出一条消息封装,mHandler发送给UI主线程,则我们需要mHandler构造重写代码如下:

mHandler = new Handler(){@Overridepublic void handleMessage(Message msg) {int what = msg.what;switch (what) {case 1:textview.setText((String)msg.obj);break;default:break;}}};
现在如果我们运行程序,系统会崩溃吗?崩溃、还是不崩溃?那好我们运行一下程序试一下就知道了!

系统崩溃,所报的一异常就是:

系统崩溃我们分析为什么会报错呢!?threadHandler = new Handler();错误就出现在这里,我们都知道new Handler的时候,Handler会将和Handler相关的Looper、MessageQueue相关联的,在和Looper相关联的时候,当前的子线程的Looper对象,系统不会帮我们调用,也就是说此时相对应的Looper对象为null,所以就会报这个异常!。如何解决呢! 我们只需要添加一句话:

Looper.prepare();
这个时候运行程序我保证就不会崩溃,并且textview控件显示treadhandler,运行程序如下:


第三:主线程发送数据给子线程

主线程发送数据给子线程,我们需要修改onCreate方法代码如下:

HandlerThread t = new HandlerThread("child");t.start();threadHandler = new Handler(t.getLooper()){@Overridepublic void handleMessage(Message msg) {Log.i(TAG, msg.obj.toString());}};Message msg = mHandler.obtainMessage();msg.what = 1;msg.obj = "mainHandler";threadHandler.sendMessage(msg);
在这里我们用到了HandlerThread这个类,底层它也是一个Thread类,只不过在run方法中Looper、messageQueue消息队列已经创建,然后threadHandler接收数据,我们从UI线程中的MessageQueue消息队列中取出一条消息封装,用threadHandler发送消息给子线程。我们运行程序,系统日志将会显示如下:


Handler机制无非就是上面这么几种消息传递,只要弄清楚Handler、Looper、MessageQueue、Message之间的关系,另外他们和Thread线程的联系,我们就可以很好的运用他们了。

UI界面更新常用的几种方法有:

post、sendMessage、runOnUiThread、view.post

这几个方法底层其实都是Handler消息传递机制,来下面我们看看他们的实现方式底层代码:

post方式:

public final boolean post(Runnable r)    {       return  sendMessageDelayed(getPostMessage(r), 0);    }
runOnUiThread方式:

public final void runOnUiThread(Runnable action) {        if (Thread.currentThread() != mUiThread) {            mHandler.post(action);        } else {            action.run();        }    }
view.post方式:

public boolean post(Runnable action) {        final AttachInfo attachInfo = mAttachInfo;        if (attachInfo != null) {            return attachInfo.mHandler.post(action);        }        // Assume that post will succeed later        ViewRootImpl.getRunQueue().post(action);        return true;    }
看到上面的底层代码我们就会明白底层都是使用Handler消息机制传递的。

好了,就写这么多了。如果有错误,欢迎留言!。。

0 0
原创粉丝点击