Android 四种更新UI方式

Android中非UI线程不能更新Activity中的组件,但是在开发中经常需要更新UI组件中的属性值,于是Android提供了一套Handler消息传递的机制,handler即可以发送消息,也可以处理消息。

实际上Handler只是封装了消息的发送,Handler是通过Looper来实现消息传递的。

private Looper(){

mQueue = new MessageQueue();

mRun  = true;

mThread = Thread.currentThread();

}

从Looper的构造器可以看出,无法通过Looper()构造器创建Looper对象,在Looper()中,可以看见有一个 MessageQueue(), MessageQueue()实际上是一个消息队列,Handler发送消息时,实际上将消息存储在 MessageQueue()中,发送消息时,Looper会不断从 MessageQueue()中取得消息,交给Handler处理,它采用先进先出的方式进行处理。

创建Looper对象是通过prepare()方法实现,创建Looper的同时也就创建了配套的MessageQueue,下面是Android 中的源码:

public static void prepare() {
        prepare(true);
    }


    private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }

有了Looper对象后,调用loop()方法启动Looper.

以上是Handler进行消息传递的机制,利用Handler就可以更新UI了。

下面是更新UI的四种方法:

package com.example.updateui;


import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;
//更新UI

public class MainActivity extends Activity {
private TextView textView;

private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
textView.setText("ok"); //handler2更新UI
}
};
//第一种
private void handler1(){
handler.post(new Runnable() {
@Override
public void run() {
textView.setText("ok");
}
});
}
//第二种
private void handler2(){
handler.sendEmptyMessage(1);
}
//第三种
private void updateUI(){
runOnUiThread(new Runnable() {

@Override
public void run() {
textView.setText("ok");
}
});
}
//第四种,通过视图直接更新
private void viewUI(){
textView.post(new Runnable() {

@Override
public void run() {
textView.setText("ok");
}
});
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

textView = (TextView) findViewById(R.id.textView);

new Thread(){
@Override
public void run() {
try {
Thread.sleep(2000);
//handler1();
//handler2();
//updateUI();
viewUI();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}
}

实际上,它们的机制大同小异:

对于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();
        }
    }

它们本质上还是利用Handler机制。

应为每个线程只有一个Looper()对象,所以主线程中已初始化一个Looper()对象, 因此可以直接通过handler发送消息。

若是程序员自己启动子线程,则必须创建一个Looper()对象,下面是一个实例:

/**
 *利用Looper更新UI
 */
public class TestLooper extends Activity {
    private LooperThread looperThread;
    private TextView textView;
    private ImageView imageView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_handler);
        textView  = (TextView) findViewById(R.id.tv_handler);
        imageView = (ImageView)findViewById(R.id.image_handler);
        imageView.setImageResource(R.drawable.meimei01);
        textView.setText("测试looper");
        looperThread = new LooperThread();
        looperThread.start();
    }
    class LooperThread extends  Thread{
        public Handler handler;
        @Override
        public void run() {
            Looper.prepare();
            handler = new Handler(){
                @Override
                public void handleMessage(Message msg) {
                    if(msg.what == 0x001){
                        Toast.makeText(TestLooper.this,msg.getData().getString("looper"),Toast.LENGTH_LONG).show();
                       // textView.setText(msg.getData().getString("looper"));
                    }
                }
            };
            Looper.loop();
        }
    }
    public void setMsg( View v){
        Message msg = new Message();
        msg.what = 0x001;
        Bundle bundle = new Bundle();
        bundle.putString("looper","hello looper");
        msg.setData(bundle);
        textView.setText(msg.getData().getString("looper"));
        looperThread.handler.sendMessage(msg);
    }
}



版权声明:本文为feiye_wine原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。