更新UI

本文详细介绍了在Android应用中使用子线程更新UI的方法,包括Handler+sendMessage+Thread,Runnable+post+Thread,runOnUiThread及AsyncTask等。重点讨论了避免在访问网络的子线程中直接更新UI的问题,提供了实际应用示例。

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);
	    }
}


转载于:https://my.oschina.net/carbenson/blog/497917

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值