`
阿尔萨斯
  • 浏览: 4181107 次
社区版块
存档分类
最新评论

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的几种方法

    我们知道在Android开发中不能在非ui线程中更新ui,但是,有的时候我们需要在代码中执行一些诸如访问网络、查询数据库等耗时操作,为了不阻塞ui线程,我们时常会开启一个新的线程(工作线程)来执行这些耗时操作,...

    浅谈Android中使用异步线程更新UI视图的几种方法

    在Android中子线程是不能更新ui的。 所以我们要通过其他方式来动态改变ui视图, 1、runOnUiThread activity提供的一个轻量级更新ui的方法,在Fragment需要使用的时候要用getActivity.runOnUiThread开启线程 这种...

    Android 在子线程中更新UI的几种方法示例

    本文介绍了Android 在子线程中更新UI的几种方法示例,分享给大家,具体如下: 方式一:Handler和Message ① 实例化一个Handler并重写handlerMessage()方法 private Handler handler = newHandler() { public void...

    [安卓开源项目]Android-炫酷的3D音乐播放器-各种特效OpenGL.zip

    毕设安卓源码,分享给需要的人。 对于现阶段的Android开发而言,技术深度很大一部分就体现在对...例如一个线程可以有几个Looper可以对应几个Handler?(字节跳动、小米) 如何更新UI,为什么子线程不能更新UI?(美

    Android 实现界面刷新的几种方法

     Android提供了Invalidate方法实现界面刷新,但是Invalidate不能直接在线程中调用,因为他是违背了单线程模型:Android UI操作并不是线程安全的,并且这些操作必须在UI线程中调用。 Android程序中可以使用的界面...

    新版Android开发教程.rar

    Android 是一个专门针对移动设备的软件集,它包括一个操作系统,中间件和一些重要的应用程序。 Beta 版 的 Android SDK 提供了在 Android 平台上使用 JaVa 语言进行 Android 应用开发必须的工具和 API 接口。 特性 ...

    android-mvvm-coroutine:带有 MVVM 模式、android 架构、kotlin 协程、单元测试和 UI 测试的 Kotlin android 应用程序示例

    以下是我使用的几个库: //线程 // 设计组件//本地数据存储// 网络Moshi // JSON 解析器Picasso // 图片加载器Mockito // 单元测试Espresso // UI 测试架构概述: 我使用了几个外部示例来创建这个示例,主要来自这...

    详解Android UI更新的几种方法

    如果是在WT进行UI的更新,则会抛出异常,android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.(只有创建这个View的原

    异步线程AsyncTask

    AsyncTask直接继承于Object类 位置为android os AsyncTask 要使用AsyncTask工作我们要提供三个泛型参数 并重载几个方法 至少重载一个 "&gt;Android的AsyncTask比Handler更轻量级一些 适用于简单的异步处理 首先明确...

    Android APP启动多图滚动的UI引导页动画效果.rar

    Android APP 引导页动画效果,这个相信大家都熟悉,是软件入口的闪屏界面,安卓手机APP启动时多图滚动或者手指滑动切换的UI引导页动画效果,本实例引导页使用的pageview适配器,图片的下半部分有几个小圆点,显示...

    Android高级编程--源代码

    4.1 Android UI基本设计 74 4.2 View简介 74 4.2.1 使用View创建Activity(活动)用户界面 75 4.2.2 Android Widget工具箱 76 4.3 布局简介 77 4.4 创建新的View 78 4.4.1 修改现有的View 79 4.4.2 创建复合...

    深入理解Android:卷I--详细书签版

    在本章的拓展思考部分,笔者提出了几个问题,旨在激发读者深入思考和学习Android的欲望。    本书特色  笔者认为,本书最大的特点在于,较全面、系统、深入地讲解了Android系统中的几大重要组成部分的工作原理...

    [Android实例] 面试题集.zip

    [Android实例] 面试题集 需要的请下载 对于现阶段的Android开发而言,技术深度很大一部分就体现在对Android系统...例如一个线程可以有几个Looper可以对应几个Handler?(字节跳动、小米) 如何更新UI,为什么子线程不

    高焕堂关于Android讲义

    以下是其目录,有几个没找到,如有谁找到,请给我回下,谢谢啦! 1.高焕堂讲解 Intent-based Programming 2.高焕堂讲解 ContentProvider范例 3.实际演练Android仿真器之操作 4.Android与Cross Compiler之关系 5....

    Android编程实现异步消息处理机制的几种方法总结

    假如有耗时操作,比如:在子线程中下载文件,通知ui线程下载进度,ui线程去更新进度等,这个时候我们就需要用到异步消息处理。 一、什么是Handler Handler是Android提供用来异步更新UI的一套机制,也是一套消息处理...

    Android 中 EventBus 的使用之多线程事件处理

    Android中有很多种执行异步操作的方法(指平行于UI线程的)。AsyncTask对于用户来说是最简单的一种机制,并且只需要少量的设置代码即可。然而,它的使用是有局限的,正如Android官方文档中所描述的: AsyncTask被...

    Android 面试宝典

    5. Android中的动画有哪几类,它们的特点和区别是什么? 两种.一种是Tween动画.还有一种是Frame动画. Tween动画,这种实现方式...4)线程:UI thread通常就是main thread,而Android启动程序时会替它建立一个Message Queue.

    Android异步加载解决方案

    在介绍Android开发过程中,异步处理这个常见的技术问题之前,我们简单回顾下Android开发过程中需要注意的几个地方。 Android应用开发过程中必须遵循单线程模型(SingleThreadModel)的原则。因为Android的UI操作并不是...

    Android结合kotlin使用coroutine的方法实例

    最近入了Android坑,目前还处于疯狂学习的状态,所以很久都没有写...首先coroutine得有个调度器,英文叫做 “Dispatchers”,有这么几个: Dispatchers.Main 这里面的coroutine跑在主线程上,在Android里也就是UI线程

Global site tag (gtag.js) - Google Analytics