一、 介绍

当一个Android app启动同时,也会启动一个UI主线程,所有的UI操作都必须在这个UI主线程上执行,如果在子线程执行UI操作则会出现奔溃。一些android上耗时的操作,如图片加载、数据库访问、复杂的业务逻辑处理都应该放在子线程中来完成,否则会出现ANR的问题。现在介绍两种最常用的异步加载方案。分别是AsyncTask和Thread、Handler实现。

二、 AsyncTask实现异步加载

AsyncTask比较适合那种短时的操作,例如就几秒钟。如果想要线程长时间运行,最好用Executor、ThreadPoolExecutor或者FutureTask。继承AsyncTask的子类至少要实现doInBackground方法。

1、AsyncTask基本参数

AsyncTask< Params, Progress, Result >
(1)Params:传递给子线程的参数类型,可以是String、Integer等基本数据类型,也可以是类对象。
(2)Progress:进度参数的数据类型
(3)Result:线程返回结果的数据类型

2、AsyncTask基本方法

(1) onPreExecute: 在线程被执行前执行的一些操作,如初始化工作等。
(2) doInBackground:在onPreExecute执行后被调用的函数,上面说的Params参数就是被传递到这个函数方法里。运行结果也是在这里返回。在这个函数里,可以调用publishProgress公布进度情况。
(3) publishProgress:公布线程执行的进度。
(4) onProgressUpdate:在publishProgress执行后被调用的函数,用于更新进度信息。
(5) onPostExecute:线程执行完后调用该函数,线程执行的结果作为该函数的参数。
(6) cancle:终止线程的运行。

3、代码实例

public class MainActivity extends Activity {
	
	private TextView textView = null;
	private SeekBar seekBar = null;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		textView = (TextView)findViewById(R.id.progress_text);
		seekBar = (SeekBar)findViewById(R.id.progress_bar);

		Worker workder = new Worker("wgc", 90);
		
		new DemoAsyncTask().execute(workder);
	}
	
	class Worker {
		private String name;
		private int progress;
		
		public Worker(String name, int progress) {
			this.name = name;
			this.progress = progress;
		}

		public String getName() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}

		public int getProgress() {
			return progress;
		}

		public void setProgress(int progress) {
			this.progress = progress;
		}
		
	}

	class DemoAsyncTask extends AsyncTask<Worker, Integer, String>{
		
		@Override
		protected void onPreExecute() {
			Log.v("test", "onPreExecute() is called!");  
			textView.setText("Loading......");
		}

		@Override
		protected String doInBackground(Worker... params) {
			Log.v("test", "doInBackground() is called!");  
			
			Worker worker = params[0];
			
			for(int i = 1; i<= worker.getProgress(); i++) {
				publishProgress(i);//每次使用该函数会调用onProgressUpdate来更新UI的进度
				
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			
			return "loading finished!";//这个结果将作为onPostExecute的参数
		}
		
		
		@Override
		protected void onProgressUpdate(Integer... values) {
			Log.v("test", "onProgressUpdate() is called!");
			//更新UI的进度
			textView.setText(values[0] + "");
			seekBar.setProgress(values[0]);
			if(values[0] == 60) this.cancel(true);//终止线程的运行
		}
		
		@Override
		protected void onPostExecute(String result) {
			Log.v("test", "onPostExecute() is called!");
			textView.setText(result);
		}
		
	}
}

下面是日志的输出结果:可以看到onPreExecute是最先被执行的,然后是doInBackground,在doInBackground里,每一次调用publishProgress都会onProgressUpdate来更新UI。最后就是调用onPostExecute函数。

三、 Thread+handler实现异步加载

public class MainActivity extends Activity {
	
	private TextView textView = null;
	private SeekBar seekBar = null;
	
	private Handler handler;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		textView = (TextView)findViewById(R.id.progress_text);
		seekBar = (SeekBar)findViewById(R.id.progress_bar);
		
		//2.Thread+handler实现异步加载
		handler = new Handler() {
			@Override
			public void handleMessage(Message msg) {
				Bundle data = msg.getData();
				
				textView.setText(data.getInt("progress") + "");
				seekBar.setProgress(data.getInt("progress"));
			}
		};
		
		new Thread(){
			
			public void run() {
				for(int i = 1; i<= 100; i++) {
					Message msg = handler.obtainMessage();
					Bundle bundle = new Bundle();
					bundle.putInt("progress", i);
					msg.setData(bundle);
					handler.sendMessage(msg);
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}}.start();
		}
}

四、 HandlerThread实现异步加载

public class MainActivity extends Activity {
	
	private Handler handler1;
	
	private TextView text;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		text = (TextView)findViewById(R.id.text);
		
		Log.v("thread_id","UI thread: " + Thread.currentThread().getId());
		
		HandlerThread handlerThread = new HandlerThread("handler_thread");
		handlerThread.start();
		
		handler1 = new Handler(handlerThread.getLooper()) {
			@Override
			public void handleMessage(Message msg) {
				Log.v("thread_id","Looper thread1: " + getLooper().getThread().getId());
				text.setText(msg.arg1 + "");
			}
		};
		
		new Thread(){
			public void run() {
				Message msg = new Message();
					
				msg.arg1 = 1;
				handler1.sendMessage(msg);

			};
		}.start();
		
	}
}
 
打赏

发表评论

电子邮件地址不会被公开。