首页 > 代码库 > Android-线程更新UI的几个方式

Android-线程更新UI的几个方式

如图,Android上新开的线程如想更新UI,需要重新跳到主线程中才能操作,以下是老外给出的几种方案,大家多多学习下.


1通过UI控件post一个runnable子类:

private void loadIcon() {
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					Thread.sleep(mDelay);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}

				mBitmap = BitmapFactory.decodeResource(getResources(),
						R.drawable.painter);
				mImageView.post(new Runnable() {
					@Override
					public void run() {

						mImageView.setImageBitmap(mBitmap);
					}
				});
			}
		}).start();
	}

2.通过调用主线程runOnUiThread执行修改

new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					Thread.sleep(mDelay);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}

				mBitmap = BitmapFactory.decodeResource(getResources(),
						R.drawable.painter);
				SimpleThreadingExample.this.runOnUiThread(new Runnable() {
					@Override
					public void run() {
						mImageView.setImageBitmap(mBitmap);
					}
				});
			}
		}).start();

3.通过Handler不断的在另一条线程上post一个runnable来执行修改:

private class LoadIconTask implements Runnable {
		int resId;

		LoadIconTask(int resId) {
			this.resId = resId;
		}

		public void run() {

			handler.post(new Runnable() {
				@Override
				public void run() {
					mProgressBar.setVisibility(ProgressBar.VISIBLE);
				}
			});

			mBitmap = BitmapFactory.decodeResource(getResources(), resId);
			
			// Simulating long-running operation
			
			for (int i = 1; i < 11; i++) {
				sleep();
				final int step = i;
				handler.post(new Runnable() {
					@Override
					public void run() {
						mProgressBar.setProgress(step * 10);
					}
				});
			}

			handler.post(new Runnable() {
				@Override
				public void run() {
					mImageView.setImageBitmap(mBitmap);
				}
			});
			
			handler.post(new Runnable() {
				@Override
				public void run() {
					mProgressBar.setVisibility(ProgressBar.INVISIBLE);
				}
			});
		}
	}

4.以下的例子通过Handlemessage来做操作,比较有意思的是采用了软引用.(参考IOS中的weak关键字),同时handler发送message的时候obtainMessage采用了池的回收机制.

	static class UIHandler extends Handler {
		WeakReference<HandlerMessagesActivity> mParent;

		public UIHandler(WeakReference<HandlerMessagesActivity> parent) {
			mParent = parent;
		}

		@Override
		public void handleMessage(Message msg) {
			HandlerMessagesActivity parent = mParent.get();
			if (null != parent) {
				switch (msg.what) {
				case SET_PROGRESS_BAR_VISIBILITY: {
					parent.getProgressBar().setVisibility((Integer) msg.obj);
					break;
				}
				case PROGRESS_UPDATE: {
					parent.getProgressBar().setProgress((Integer) msg.obj);
					break;
				}
				case SET_BITMAP: {
					parent.getImageView().setImageBitmap((Bitmap) msg.obj);
					break;
				}
				}
			}
		}

	}

	Handler handler = new UIHandler(new WeakReference<HandlerMessagesActivity>(
			this));


private class LoadIconTask implements Runnable {
		private final int resId;
		private final Handler handler;

		LoadIconTask(int resId, Handler handler) {
			this.resId = resId;
			this.handler = handler;
		}

		public void run() {

			Message msg = handler.obtainMessage(SET_PROGRESS_BAR_VISIBILITY,
					ProgressBar.VISIBLE);
			handler.sendMessage(msg);

			final Bitmap tmp = BitmapFactory.decodeResource(getResources(),
					resId);

			for (int i = 1; i < 11; i++) {
				sleep();
				msg = handler.obtainMessage(PROGRESS_UPDATE, i * 10);
				handler.sendMessage(msg);
			}

			msg = handler.obtainMessage(SET_BITMAP, tmp);
			handler.sendMessage(msg);

			msg = handler.obtainMessage(SET_PROGRESS_BAR_VISIBILITY,
					ProgressBar.INVISIBLE);
			handler.sendMessage(msg);
		}

		private void sleep() {
			try {
				Thread.sleep(mDelay);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

5.采用AyncTask方式,也是我们比较常用的方式

	class LoadIconTask extends AsyncTask<Integer, Integer, Bitmap> {


		@Override
		protected void onPreExecute() {
			mProgressBar.setVisibility(ProgressBar.VISIBLE);
		}

		@Override
		protected Bitmap doInBackground(Integer... resId) {
			Bitmap tmp = BitmapFactory.decodeResource(getResources(), resId[0]);
			// simulating long-running operation 
			for (int i = 1; i < 11; i++) {
				sleep();
				publishProgress(i * 10);
			}
			return tmp;
		}

		@Override
		protected void onProgressUpdate(Integer... values) {
			mProgressBar.setProgress(values[0]);
		}

		@Override
		protected void onPostExecute(Bitmap result) {
			mProgressBar.setVisibility(ProgressBar.INVISIBLE);
			mImageView.setImageBitmap(result);
		}

		private void sleep() {
			try {
				Thread.sleep(mDelay);
			} catch (InterruptedException e) {
				Log.e(TAG, e.toString());
			}
		}
	}

不管如何.发这东西,只是想表达下 ,老外的东西有时候还是蛮有意思的.


Android-线程更新UI的几个方式