Android应用程序通常运行在一个dalvik虚拟机进程中,进程开始的时候会启动一个主线程(MainThread),主线程负责处理和UI相关的事件,如:用户的按键事件,因此主线程通常又叫UI线程。而由于Android采用UI单线程模型,所以只能在主线程中对UI元素进行操作。如果在非UI线程直接对UI进行了操作,则会报错:CalledFromWrongThreadException:only the original thread that created a view hierarchy can touch its views。

Android提供了消息循环的机制,利用这个机制可以实现线程间的通信,从而达到更新UI的操作。

为了保证UI线程能够及时响应用户的操作,应尽量避免在UI线程中进行费时操作。如果UI线程被阻塞5秒,则系统会弹出ANR对话框,等待用户进一步操作。

Message Queue是一个消息队列,用来存放通过Handler发送的消息。Android在第一启动程序时会默认会为UI thread创建一个关联的消息队列,可以通过Looper.myQueue()得到当前线程的消息队列,用来管理程序的一些上层组件,activities,broadcast receivers 等,你可以在自己的子线程中创建Handler与UI thread通讯。

Handler会向message queue通过两种方法发送消息:send或post。这两种消息都会插在message queue队尾并按先进先出执行,但通过这两种方法发送的消息执行的方式略有不同:1)通过send发送的是一个message对象, 会被handler的 handleMessage()函数处理;2)而通过post方法发送的是一个runnable对象,则会自己执行。

UI线程图形界面中的view可通过post方法向GUI线程的message queue投递一个runnable。对于除UI线程以外的其他线程,创建时缺省并没有message queue,而对于UI线程,则可以直接(比如在onCreate)创建一个handler并重载handleMessage,省去创建message queue的过程。

如果在UI线程中,把费时操作放到新开启的线程中,当操作完成时,通过Handler来统一对相关UI进行更新,这是一个可行且易于理解的处理方法。

代码结构如下:

public class RefreshUIActivity extends Activity implements OnClickListener {    private static final int ACTION_BUTTON_1 = 1;private static final int ACTION_BUTTON_2 = 2;private static final int ACTION_BUTTON_3 = 3;private Button button1;private Button button2;private Button button3;private Handler mHandler = new Handler(new Callback() {@Overridepublic boolean handleMessage(Message msg) {switch (msg.what) {case ACTION_BUTTON_1:button1.setText("Button1 " + msg.what);break;case ACTION_BUTTON_2:button2.setText("Button2 " + msg.what);break;case ACTION_BUTTON_3:button3.setText("Button3 " + msg.what);break;default:break;}return false;}});    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);                button1 = (Button) findViewById(R.id.button1);        button2 = (Button) findViewById(R.id.button2);        button3 = (Button) findViewById(R.id.button3);                button1.setOnClickListener(this);        button2.setOnClickListener(this);        button3.setOnClickListener(this);            }@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.button1:        handleButton1();break;case R.id.button2:handleButton2();break;case R.id.button3:handleButton3();break;default:break;}}private void handleButton3() {new Thread(new Runnable() {@Overridepublic void run() {try {Thread.sleep(3 * 1000);} catch (InterruptedException e) {e.printStackTrace();}mHandler.sendEmptyMessage(ACTION_BUTTON_3);}}).start();}private void handleButton2() {new Thread(new Runnable() {@Overridepublic void run() {try {Thread.sleep(3 * 1000);} catch (InterruptedException e) {e.printStackTrace();}mHandler.sendEmptyMessage(ACTION_BUTTON_2);}}).start();}private void handleButton1() {new Thread(new Runnable() {@Overridepublic void run() {try {Thread.sleep(3 * 1000);} catch (InterruptedException e) {e.printStackTrace();}mHandler.sendEmptyMessage(ACTION_BUTTON_1);}}).start();}}

说明:上面仅仅是个人喜欢的代码结构罢了,呵呵!

多说一句:当然还有其它的机制可以完成更新UI的操作,在此不再赘述!=^_^=

更多相关文章

  1. [原]Android应用程序消息处理机制(Looper、Handler)分析
  2. :Handler方法小结(在线程中更新UI和了解HandlerThread类的用法)
  3. 第3.3.1节 处理手势操作
  4. android线程池原理和实现
  5. Android消息推送完美解决方案全析

随机推荐

  1. Android对数据库表的一个约定:每张表都应
  2. Android(安卓)弹无虚发之第三弹:ActionBar
  3. 非开发人员如何使用命令行安装和卸载Andr
  4. Android----xml文件中的控件的id设置
  5. Android(安卓)开发中重力感应的实例
  6. android库工程jar打包和混淆
  7. 【小王的安卓之路】Android原生网络请求
  8. Android(安卓)仿当乐游戏详情页面(二)
  9. 包括后台的Android美食APP项目开源代码,an
  10. android权限申请库解析