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

本文深入探讨了Android环境下多线程的使用方法,重点介绍了如何在子线程中修改用户界面,通过异步消息处理机制实现UI更新,并以AsyncTask为例展示了简化操作界面的方法。

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

}

Applies basic field behavior in circuit design and demonstrates how it relates to grounding and shielding requirements and techniques in circuit designThis book connects the fundamentals of electromagnetic theory to the problems of interference in all types of electronic design. The text covers power distribution in facilities, mixing of analog and digital circuitry, circuit board layout at high clock rates, and meeting radiation and susceptibility standards. The author examines the grounding and shielding requirements and techniques in circuit design and applies basic physics to circuit behavior. The sixth edition of this book has been updated with new material added throughout the chapters where appropriate. The presentation of the book has also been rearranged in order to reflect the current trends in the field.Grounding and Shielding: Circuits and Interference, Sixth Edition: Includes new material on vias and field control, capacitors as transmission lines, first energy sources, and high speed designs using boards with only two layersDemonstrates how circuit geometry controls performance from dc to gigahertzExamines the use of multi-shielded transformers in clean-power installationsProvides effective techniques for handling noise problems in analog and digital circuitsDiscusses how to use conductor geometry to improve performance, limit radiation, and reduce susceptibility to all types of hardware and systemsGrounding and Shielding: Circuits and Interference, Sixth Edition is an updated guide for circuit design engineers and technicians. It will also serve as a reference for engineers in the semiconductor device industry.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值