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

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

时间: 2024-11-08 18:24:53

Android-线程更新UI的几个方式的相关文章

Android 线程更新UI报错 : Can&#39;t create handler inside thread that has not called Looper.prepare()

MainActivity中有一个按钮,绑定了save方法 public void save(View view) { String title = titleText.getText().toString(); String timelength = lengthText.getText().toString(); ExecutorService exec = Executors.newCachedThreadPool(); exec.execute(new NewsService(getApp

Android攻城狮 Android中更新UI的几种方式

Android中更新UI的几种方式: 1. Activity 的 runOnUiThread() 2. Handler 的 post() 3. Handler 的 sendMessage() 4. View 的 post() 1 public class FiveActivity extends Activity { 2 3 private TextView textView; 4 5 private Handler handler = new Handler() { 6 public void

android中子线程更新UI的方式浅析

一.为何写作此文 ??你是不是经常看到很多书籍中说:不能在子线程中操作ui,不然会报错.你是不是也遇到了如下的疑惑(见下面的代码): @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = (TextView) findViewById(R.id.tv); Threa

Android异步处理一:使用Thread+Handler实现非UI线程更新UI界面

Android应用的开发过程中需要把繁重的任务(IO,网络连接等)放到其他线程中异步执行,达到不阻塞UI的效果. 下面将由浅入深介绍Android进行异步处理的实现方法和系统底层的实现原理. 本文介绍Android异步处理一:使用Thread+Handler实现非UI线程更新UI界面: 即如何使用Thread+Handler的方式从非UI线程发送界面更新消息到UI线程. 概述:每个Android应用程序都运行在一个dalvik虚拟机进程中,进程开始的时候会启动一个主线程(MainThread),

Android多线程更新UI的方式

Android下,对于耗时的操作要放到子线程中,要不然会残生ANR,本次我们就来学习一下Android多线程更新UI的方式. 首先我们来认识一下anr: anr:application not reponse:应用程序无响应 主线程:UI线程 anr产生的原因:主线程需要做很多重要的事情,响应点击事件,更新ui,如果在主线程里面阻塞时间过久,应用程序就会无响应,为了避免应用程序出现anr,所有的耗时的操作,都应该放在子线程中执行. 认识了anr后,我们就来学习一下怎样在Android下开启多线程

Android异步处理系列文章四篇之一使用Thread+Handler实现非UI线程更新UI界面

目录: Android异步处理一:使用Thread+Handler实现非UI线程更新UI界面Android异步处理二:使用AsyncTask异步更新UI界面Android异步处理三:Handler+Looper+MessageQueue深入详解Android异步处理四:AsyncTask的实现原理 Android异步处理一:使用Thread+Handler实现非UI线程更新UI界面 概述:每个Android应用程序都运行在一个dalvik虚拟机进程中,进程开始的时候会启动一个主线程(MainTh

Android开发——实现子线程更新UI

Android中线程按功能分的话,可以分为两个,一个是主线程(UI线程),其他的都是子线程 主线程不能执行那些耗时过长的代码或任务(执行耗时过长的代码会出现应用未响应的提示),所以都是使用子线程来执行耗时过长的代码,比如说下载文件等任务 一般情况,子线程中执行过长的代码,都是需要进行更新UI操作. 但是Android中,为了防止安全,是不允许在子线程更新UI的,但是我们可以使用到Android官方给予的API来实现子线程更新UI的操作(本质上,这些API也是切换回了主线程来进行更新UI) 例子:

Android子线程更新UI主线程方法之Handler

背景: 我们开发应用程序的时候,处于线程安全的原因子线程通常是不能直接更新主线程(UI线程)中的UI元素的,那么在Android开发中有几种方法解决这个问题,其中方法之一就是利用Handler处理的. 下面说下有关Handler相关的知识. 多线程一些基础知识回顾:在介绍Handler类相关知识之前,我们先看看在Java中是如何创建多线程的方法有两种:通过继承Thread类,重写Run方法来实现通过继承接口Runnable实现多线程 具体两者的区别与实现,看看这篇文章中的介绍:http://de

Android关于线程更新UI的方法

Android关于线程更新UI的方法 在一个Android 程序开始运行的时候,会单独启动一个Process.默认的情况下,所有这个程序中的Activity或者Service(Service和 Activity只是Android提供的Components中的两种,除此之外还有Content Provider和Broadcast Receiver)都会跑在这个Process.   一个Android 程序默认情况下也只有一个Process,但一个Process下却可以有许多个Thread.   在

子线程更新UI界面的2种方法

一.一般我们都会在子线程完成一些耗时的操作. 1.Android中消息机制: 2.知识点: Message:消息,其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理.                      Handler:处理者,负责Message的发送及处理.使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理,例如更新UI等.