Android学习(17)-子线程修改UI

(1)所谓后台服务是指当我们程序在运行的时候,总有那么一些默默无闻的服务在后面跑着,提供着服务。程序是进程,进程中除了主线程之外可能有其他一些线程,那么这些线程在后台可能就提供者某类服务。本篇文章要研究的其实就是Android环境下多线程的用法。


(2)Java中多线程主要有三种方式:extends Thread类,implements Runable接口,通过匿名类的方式直接开始线程new Thread(new Runable(){}).start()

(3)在Android中只有主线程可以修改UI元素。比如界面上有个按钮,有一个文本,点击按钮来修改文本内容,如果点击事件中通过子线程去做这件事情,那么就会出问题。那么如何在一个子线程中修改用户界面呢?还是一个按钮改变文本的例子:

其界面和布局如下:


<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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <Button
        android:id="@+id/changeText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="47dp"
        android:text="子线程修改文本内容" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/changeText"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="155dp"
        android:text="@string/hello_world" />

</RelativeLayout>
其活动代码如下:

public class MainActivity extends Activity implements OnClickListener{

	//布局控件
	private Button changeText;
	private TextView textView;
	
	//标识码
	public static final int UPDATE_TEXT = 1;
	
	//处理器对象
	private Handler handler = new Handler(){
		//重写该方法
		public void handleMessage(Message msg){
			switch (msg.what) {
			case UPDATE_TEXT:
				//在此修改UI内容
				textView.setText("内容已修改");
				break;
			default:
				break;
			}
		}
	};
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		changeText = (Button)findViewById(R.id.changeText);
		textView = (TextView)findViewById(R.id.textView);
		changeText.setOnClickListener(this);
	}

	//处理点击事件
	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.changeText:
			//启动一个线程
			new Thread(){
				//重写该方法
				public void run(){
					Message msg = new Message();
					msg.what = UPDATE_TEXT;
					handler.sendMessage(msg);
				}
			}.start();
			break;

		default:
			break;
		}		
	}

}

(4)其实上述实现是通过异步消息处理机制来做到的。在异步消息处理中,主要有四部分的内容:

Message: 线程之间传递的消息

Handler: 主要用于发送和处理消息

MessageQueue: 消息队列的意思,存放所有Handler发送的消息,每个线程中只会有一个MessageQueue

Looper: Looper是每个线程中MessageQueue的管家,用于不断循环,如果queue中有了消息,马上交给Handler处理。每个线程也只有一个。

上述方法的思路就是:

主线程创建一个Handler对象,重写handleMessage方法。子线程想改变UI的时候,创建一个Message对象,通过handler发送,消息进去了MessageQueue队列,Looper等到了队列,分发给Handler处理。因为Handler是主线程创建的,所以能够改变UI。


(5)为了更加方便的通过子线程操作UI,Android中提供了另外一个好用的工具,AsyncTask就是其中之一。其示例代码如下:

public class DownloadTask extends AsyncTask<Void, Integer, Boolean> {
	//编写子类继承AsyncTask,并实现里面的抽象方法
	//包含三个参数:传入的参数 ; 如果前台显示后台的进度,第二个参数是进度单位;返回值类型

	//这个方法会在后台任务开始执行前调用
	protected void onPreExecute(){
		progressDialog.show(...);//显示进度条
	}
	
	
	//这个方法中的所有代码都会在子线程中运行, 这里面的例子就是模仿下载速度
	protected Boolean doInBackground(Void... arg0) {
		try{
			while(true){
				int downloadPercent = doDownload(); //下载方法,虚构的方法
				publishProgress(downloadPercent); //反馈当前的进度
				if(downloadPercent >= 100){
					break;
				}
			}
		}catch(Exception e){
			return false;
		}
		return true;
	}

	//当后台调用publishProgress方法时,这个方法很快被调用,方法中的参数是后台传递过来的   在这个方法中可以对UI进行操作
	protected void onProgressUpdate(Integer... values){
		//在这里更新下载速度
		progressDialog.setMessage("下载 "+values+"%");
	}
	
	//当后台任务执行完毕,将要返回时调用这个方法
	protected void onPostExecute(Boolean result){
		progressDialog.dismiss(); //关闭进度对话框
		//提示下载结果
		if(result){
			Toast.makeText(context, text, duration).show();
		}else{
			Toast.makeText(context, text, duration).show();
		}
	}

}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值