您的位置:首页 > 移动开发 > Android开发

Android(java)学习笔记202:Handler消息机制的原理和实现

2015-08-30 10:40 831 查看
联合学习 Android(java)学习笔记149:AsyncTask(异步任务)和Handler(消息机制)

1. 首先我们通过一个实例案例来引出一个异常:

(1)布局文件activity_main.xml:

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >

<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="@string/hello_world" />

</RelativeLayout>


(2)MainActivity.java:

package com.itheima.testthread;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
System.out.println(Thread.currentThread().getName());
final TextView tv = (TextView) findViewById(R.id.tv);
new Thread() {
public void run() {
for (int i = 0; i < 100; i++) {
tv.setText("哈哈哈"+i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
}.start();
}

}


(3)布署程序到模拟器上,出现如下效果,程序直接stop;并且直接报出异常错误:




报错:





android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

意思:从错误线程调用的异常。谁创建的view,谁才能修改编辑view,只有主线程才可以修改view(所有的View都是主线程创建的)。

总结:上面报这个CalledFromWrongThreadException错误,是因为只有主线程才能修改View更新UI,但是我们这里却自己新建一个线程new Thread()其中run()的内容涉及到更新UI,这是不允许的,所有才会出现这样的错误警告。

但是往往我们编写程序的时候设计多个线程需要控制UI显示,但是我们上面已经说过了UI更新只能交给主线程,为了解决这个矛盾,解放程序员,google开发出来消息机制,用来子线程和主线程通信,子线程要更新UI,就会发送消息数据给主线程,这样主线程就会更新相应的UI界面,从而解决这个矛盾。

2. 消息机制的原理和实现

消息机制实现逻辑图:

这里handler负责把外面的子线程的消息发到message queue消息队列之中,然后looper不停监听[b]message queue里面是不是有消息,如果有的话,looper就把消息发送到handler,交给handler的handlemessage根据信息,更新UI。[/b]





使用消息机制目的:

Android系统的主线程安全的系统,别的线程不可以修改ui线程的界面,如果子线程里面想要更新UI,就必须采用消息机制处理。

使用handler消息处理器编写代码步骤:

(1)在主线程里面声明消息处理器handler;

private Handler  handler = new  Handler()  { };


(2)子线程想要更新UI,利用消息机制

Message  msg  =  new Message();
msg.what  消息类型
msg.obj     具体消息携带的数据
handler.sendMessage(msg);


(3)系统内部有消息队列message queue和消息looper,轮询到消息,交给handler去处理:

(4)重写handler的方法处理消息:

public  void  handleMessage (Message msg)  {
//运行在主线程,更新UI

};


接下来我们就修改上面的案例,就更好理解这个消息机制:

MainActivity.java:

 package com.itheima.testthread;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends Activity {
private TextView tv;
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
// 运行在主线程,更新ui
String str = (String) msg.obj;
tv.setText(str);
EditText et;

};
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
System.out.println(Thread.currentThread().getName());
tv = (TextView) findViewById(R.id.tv);
new Thread() {
public void run() {
for (int i = 0; i < 100; i++) {
// tv.setText("哈哈哈"+i);
Message msg = new Message();
msg.obj = "哈哈哈" + i;
handler.sendMessage(msg);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
}.start();
}

}


acitivity_main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="@string/hello_world" />

</RelativeLayout>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: