android里面,如果是在从网络中获取数据并进行界面更新的话,直接在访问网络的子线程里面更新是不可行的,因为只有在UI线程才可以访问界面的控件,一下提供几个常用的方法更新UI
1、Handler+sendMessage+Thread方法
public class UpdateUIActivity extends Activity
{
private TextView mTextView;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_update_ui);
mTextView = (TextView) findViewById(R.id.textView1);
}
//使用handler的线程类
public class MyHandler implements Runnable
{
private Handler mHandler;
//handler对象会通过构造方法的参数将传入线程类
public MyHandler(Handler handler)
{
mHandler = handler;
}
@Override
public void run()
{
Message message = new Message();
//通过Message对象想handler传递更新的内容
message.obj = "Handler";
//通过handler更新TextView控件的内容
mHandler.sendMessage(message);//这句话负责把message方法中的代码引用压入主线程的执行堆栈中
}
}
//实例化用于更新TextView控件的handler对象
Handler mHandler = new Handler()
{
@Override
public void handleMessage(Message msg)
{
//从Message对象获取要更新的文本
String str = String.valueOf(msg.obj);
//更新TextView控件的显示内容(成功更新)
mTextView.setText(str);
}
};
//“使用handler”按钮的单击事件方法
public void onClick_Handler(View view)
{
//创建线程
Thread thread = new Thread(new MyHandler(mHandler));
//开启线程,并成功更新TextView控件的显示内容
thread.start();
}
}
步骤:
1、创建自己的mHandler类,并实现Runnable接口
2、在run方法里面创建Message对象,并设置相关的字段,此处是message.obj,用于传递更新UI的参数,如果更新UI的参数是一组数据,可以使用Bundle,eg:
Message msg = new Message();
Bundle bundle = new Bundle();
bundle.putString("xxx", "string");
bundle.putInt("yyy","int");
msg.setData(bundle);
mHandler.sendMessage(message);//这句话负责把message方法中的代码引用压入主线程的执行堆栈中
3、实例化mHandler对象,
Handler mHandler = new Handler()
然后在handleMessage方法里面相应的跟新UI操作
4、开启线程
Thread thread= new Thread(new MyHandler(mHandler));//关键,把thread,MyHandler联系在一起,
thread.start() ;
小结:以上是比较完整的使用子线程sendMessage方式的代码,实际应用过程里面,会使用分别继承Handler和Thread的方式,例如:
public class MainActivity extends Activity {
private EditText UITxt;
private Button updateUIBtn;
private UIHandler UIhandler;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
UITxt = (EditText)findViewById(R.id.ui_txt);
updateUIBtn = (Button)findViewById(R.id.update_ui_btn);
updateUIBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// TODO Auto-generated method stub
UIhandler = new UIHandler();
UIThread thread = new UIThread();
thread.start();
}
});
}
private class UIHandler extends Handler{
@Override
public void handleMessage(Message msg) {
// 更新UI的代码
// TODO Auto-generated method stub
super.handleMessage(msg);
Bundle bundle = msg.getData();
String color = bundle.getString("color");
UITxt.setText(color);
}
}
private class UIThread extends Thread{
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Message msg = new Message();
Bundle bundle = new Bundle();
bundle.putString("color", "黄色");
msg.setData(bundle);
MainActivity.this.UIhandler.sendMessage(msg);
}
}
}
小结: 继承Handler,在sendMessage方法里面获取msg传递过来的数据,进行UI更新的操作
继承Thread,在run方法里面创建Message对象msg,并传入参数,发送msg
如何使用该子线程和之前提到的方法是一样的。
2、Runnable+post+Thread方法
public void onClick(View view)
{
//创建子线程
new Thread(new Runnable()
{
public void run()
{
final Bitmap bitmap=loadImageFromNetwork("http://example.com/image.png");
//mImageView 是UI线程创建的ImageView对象,在另一个线程中使用post方法
mImageView.post(new Runnable()
{
public void run()
{
mImageView.setImageBitmap(bitmap);
}
})
}
}
).start();
}
小结:使用post方式,需要在对应的控件调用post方法,好处是使用简便,
3、runOnUiThread方法
((Activity) context).runOnUiThread(new Runnable() {
@Override
public void run() {
try {
// 更新UI
text.setText("xxx");
} catch (Exception e) {
e.printStackTrace();
}
}
});
在runOnUiThread里面的run函数里面写更新UI的代码。Runnable对像在UI程序中被调用。如果当前线程是UI线程,那么行动是立即执行。如果当前线程不是UI线程,操作是发布到事件队列的UI线程。其实和handler差不多,都是将这个更新UI的请求消息,加入到事件队列,等待主线程空闲的时候执行。
4、AsyncTask,异步处理利器(建议使用这方法,确实好用)
以下获取网络图片并跟新的例子
mImageView = (ImageView)this.findViewById(R.id.imageThreadConcept) ;
new DownloadImageTask().execute(IMAGE_URL) ;
private class DownloadImageTask extends AsyncTask<String, Void, Drawable>
{
protected Drawable doInBackground(String... urls) {
return loadImageFromNetwork(urls[0]);
}
protected void onPostExecute(Drawable result) {
mImageView.setImageDrawable(result);
}
}