[Android开发常见问题-7] 多线程开发的几种方式和子线程操作UI线程控件的问题

移动开发里面经常会有很多耗时的操作需要放在后台运行,比如联网、大量数据处理等,否则的话就会导致主线程,也就是UI线程卡住,给用户一种程序死掉的感觉,体验极差,所以在这里我就大概的说一下如何进行多线程的开发,以及在多线程开发的过程中有哪些需要注意的问题。

方式1:继承Thread类,创建一个新的线程类。

private class thread extends Thread{
		private Context act;
		public thread(Context con){
			act = con;
		}
		@Override
		public void run() {
			super.run();
			//想要放到后台线程做的事情都写在这里。
		}
		
}


上面代码就是最基本的代码框架,要使用的时候可以通过下面代码来启动新线程。

//方式1
new thread(this).start();
//方式2
thread tt = new thread(this);
tt.start();

其中run()函数里面就是在新线程里面需要做的事情,但是这里有一点需要注意,那就是子线程不能直接操作主线程(UI线程)里面的UI控件。

比如说主线程里面有一个TextView tv,你想在子线程里面直接tv.setText('aa");这是不可以的,会报错。

又如,你想在子线程里面来一个Toast.show();这也是不可以的。

那么我们怎么在子线程里面更新主线程的UI呢?答案就是Handler。

那么Handler怎么用呢?请往下看

package com.alex.chat.activity;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.TextView;

import com.alex.chat.R;
import com.alex.chat.util.NetWork;

public class OnCreate extends Activity {
	private boolean netState = false;
	private TextView tv;
	private MyHandler mh;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.oncreate);
		tv = (TextView)findViewById(R.id.tv);
		mh = new MyHandler();
		new thread(this).start();
		
	}
	
	//继承Handler自定义要处理的事件
	private class MyHandler extends Handler{

		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			switch(msg.what){
			case 0:
				tv.setText("NetWork is not OK!");
				break;
			case 1:
				tv.setText("NetWork is OK!");
				break;
			}
		}
		
	} 

	//自己定义的新线程
	private class thread extends Thread{
		private Context act;
		public thread(Context con){
			act = con;
		}
		@Override
		public void run() {
			super.run();
			//IsNetworkAvailable()是我自定义的获得当前网络状况的函数,不必细究
			//如果想了解具体实现,请参看上一篇文章
			netState = NetWork.IsNetworkAvailable(act);
			//通过handler发送消息
			mh.sendEmptyMessage(netState?1:0);
		}
		
	}
}

这样就可以完美解决子线程更新UI线程的问题啦。

方式2:实现runnable接口,其实通过方式1我们也可以看出来,创建一个新的线程类实际上就是利用了父类的runnable接口,所以java提供runnable这个接口来供开发者使用。代码如下:

	//实现runable接口
	private class thread_run implements Runnable{
		private Context act;
		public thread_run(Context con){
			act = con;
		}
		@Override
		public void run() {
			//要在新线程里面进行的任务写在这里
		}
		
	}

这种方法实现的新线程也存在方式1一样的问题,就是要操作UI线程必须通过Handler。

这个类的使用方法如下:

//方式1
new thread_run(this).run();
//方式2
thread_run tr = new thread_run(this);
tr.run();

方式3:AsyncTask

为了方便开发者进行简单安全的多线程开发,android推出了一个安全的多线程类,叫做AsyncTask,这个类的用法如下:

	private class Thread_Task extends AsyncTask<URL, Integer, Long> {
		 protected void onPreExecute(){
			 //在后台线程开始运行之前要做的事情放到这里
		 }
	     protected Long doInBackground(URL... urls) {
	    	 //在新线程里面需要做的事情放到这里
	         return totalSize;
	     }

	     protected void onProgressUpdate(Integer... progress) {
	         setProgressPercent(progress[0]);
	     }

	     protected void onPostExecute(Long result) {
	    	 //后台线程执行完需要做的事情放到这里,注意,这里不属于后台线程,可以操作UI。
	        
	     }
	 }

调用方法如下:

new Thread_Task().execute(url1, 1, 2);
注意看代码中注释,这样的类就给我们进行多线程开发带来了很大的方便。


关于多线程开发的方式,暂时先介绍以上三种,如果以后遇到新的方式会及时更新,同时也欢迎各位朋友多提建议。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值