- 浏览: 505527 次
- 性别:
- 来自: 深圳
文章分类
- 全部博客 (200)
- java基础 (30)
- ajax (19)
- 乱写 (5)
- groovy (2)
- db (8)
- gwt (0)
- jee (2)
- 我关注的开源 (1)
- RIA AIR (1)
- spring (11)
- lucene (0)
- 工具 (10)
- 百科 (2)
- linux (6)
- android (40)
- 移动开发 (21)
- 代码片断 (15)
- tomcat (1)
- css (1)
- html5 (2)
- jquery (2)
- playframework (3)
- web (2)
- nio (3)
- design (1)
- nosql (3)
- 日志 (12)
- mysql (4)
- 图表 (1)
- python (3)
- ruby (1)
- git (0)
- hibernate (1)
- springboot (1)
- guava (1)
- mybatis (0)
- 工作问题 (3)
- php (1)
最新评论
-
linzm1990:
踩了很多坑啊。。。。
hibernate @Nofound 与@ManyToOne fetch lazy的问题 -
Ccccrrrrrr:
...
转: Spring boot 文件上传 -
rmzdb:
兄弟,你这个东西,在ie内核的浏览器,貌似不识别 文件名
工作问题:http下载文件,中文文件名在firefox下乱码问题 -
107x:
问题解决了,谢谢!
工作问题:http下载文件,中文文件名在firefox下乱码问题 -
klxqljq:
额鹅鹅鹅
android布局实现头尾固定, 中间多余内容可以滚动
LinearLayout 布局,其下放了5个ImageView
我们将演示的逻辑是异步从服务器上下载5张不同图片,依次放入这5个ImageView。上下2个TextView 是为了方便我们看是否阻塞了UI的显示。
当然 AndroidManifest.xml 文件中要配置好网络访问权限。
Handler+Runnable模式
我们先看一个并不是异步线程加载的例子,使用 Handler+Runnable模式。
这里为何不是新开线程的原因请参看这篇文章:Android Runnable 运行在那个线程 这里的代码其实是在UI 主线程中下载图片的,而不是新开线程。
我们运行下面代码时,会发现他其实是阻塞了整个界面的显示,需要所有图片都加载完成后,才能显示界面
Handler+Thread+Message模式
这种模式使用了线程,所以可以看到异步加载的效果。
这时候我们可以看到实现了异步加载, 界面打开时,五个ImageView都是没有图的,然后在各自线程下载完后才把图自动更新上去
Handler+ExecutorService(线程池)+MessageQueue模式
能开线程的个数毕竟是有限的,我们总不能开很多线程,对于手机更是如此。
这个例子是使用线程池。Android拥有与Java相同的ExecutorService实现,我们就来用它。
线程池的基本思想还是一种对象池的思想,开辟一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理。当有线程任务时,从池中取一个,执行完成后线程对象归池,这样可以避免反复创建线程对象所带来的性能开销,节省了系统的资源。
线程池的信息可以参看这篇文章:Java&Android的线程池-ExecutorService 下面的演示例子是创建一个可重用固定线程数的线程池。
这里我们象第一步一样使用了 handler.post(new Runnable() { 更新前段显示当然是在UI主线程,我们还有 executorService.submit(new Runnable() { 来确保下载是在线程池的线程中。
Handler+ExecutorService(线程池)+MessageQueue+缓存模式
下面比起前一个做了几个改造:
说明:
final参数是指当函数参数为final类型时,你可以读取使用该参数,但是无法改变该参数的值。参看:Java关键字final、static使用总结
这里使用SoftReference 是为了解决内存不足的错误(OutOfMemoryError)的,更详细的可以参看:内存优化的两个类:SoftReference 和 WeakReference
参考资料
Android异步加载图像小结
http://blog.csdn.net/sgl870927/archive/2011/03/29/6285535.aspx
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TextView android:text="图片区域开始" android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content"> </TextView> <ImageView android:id="@+id/imageView1" android:layout_height="wrap_content" android:src="@drawable/icon" android:layout_width="wrap_content"> </ImageView> <ImageView android:id="@+id/imageView2" android:layout_height="wrap_content" android:src="@drawable/icon" android:layout_width="wrap_content"> </ImageView> <ImageView android:id="@+id/imageView3" android:layout_height="wrap_content" android:src="@drawable/icon" android:layout_width="wrap_content"> </ImageView> <ImageView android:id="@+id/imageView4" android:layout_height="wrap_content" android:src="@drawable/icon" android:layout_width="wrap_content"> </ImageView> <ImageView android:id="@+id/imageView5" android:layout_height="wrap_content" android:src="@drawable/icon" android:layout_width="wrap_content"> </ImageView> <TextView android:text="图片区域结束" android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content"> </TextView> </LinearLayout>
我们将演示的逻辑是异步从服务器上下载5张不同图片,依次放入这5个ImageView。上下2个TextView 是为了方便我们看是否阻塞了UI的显示。
当然 AndroidManifest.xml 文件中要配置好网络访问权限。
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
Handler+Runnable模式
我们先看一个并不是异步线程加载的例子,使用 Handler+Runnable模式。
这里为何不是新开线程的原因请参看这篇文章:Android Runnable 运行在那个线程 这里的代码其实是在UI 主线程中下载图片的,而不是新开线程。
我们运行下面代码时,会发现他其实是阻塞了整个界面的显示,需要所有图片都加载完成后,才能显示界面
import java.io.IOException; import java.net.URL; import android.app.Activity; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Handler; import android.os.SystemClock; import android.util.Log; import android.widget.ImageView; public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); loadImage("http://www.baidu.com/img/baidu_logo.gif", R.id.imageView1); loadImage(http://www.chinatelecom.com.cn/images/logo_new.gif", R.id.imageView2); loadImage("http://cache.soso.com/30d/img/web/logo.gif, R.id.imageView3); loadImage("http://csdnimg.cn/www/images/csdnindex_logo.gif", R.id.imageView4); loadImage("http://images.cnblogs.com/logo_small.gif", R.id.imageView5); } private Handler handler = new Handler(); private void loadImage(final String url, final int id) { handler.post(new Runnable() { public void run() { Drawable drawable = null; try{ drawable = Drawable.createFromStream( new URL(url).openStream(), "image.gif"); }catch (IOException e){ Log.d("test", e.getMessage()); } if (drawable == null){ Log.d("test", "null drawable"); }else{ Log.d("test", "not null drawable"); } // 为了测试缓存而模拟的网络延时 SystemClock.sleep(2000); ((ImageView) MainActivity.this.findViewById(id)).setImageDrawable(drawable); } }); } }
Handler+Thread+Message模式
这种模式使用了线程,所以可以看到异步加载的效果。
import java.io.IOException; import java.net.URL; import android.app.Activity; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.SystemClock; import android.util.Log; import android.widget.ImageView; public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); loadImage2("http://www.baidu.com/img/baidu_logo.gif", R.id.imageView1); loadImage2("http://www.chinatelecom.com.cn/images/logo_new.gif", R.id.imageView2); loadImage2("http://cache.soso.com/30d/img/web/logo.gif", R.id.imageView3); loadImage2("http://csdnimg.cn/www/images/csdnindex_logo.gif", R.id.imageView4); loadImage2("http://images.cnblogs.com/logo_small.gif", R.id.imageView5); } final Handler handler2 = new Handler() { @Override public void handleMessage(Message msg){ ((ImageView) MainActivity.this.findViewById(msg.arg1)) .setImageDrawable((Drawable) msg.obj); } }; // 采用handler+Thread模式实现多线程异步加载 private void loadImage2(final String url, final int id) { Thread thread = new Thread() { @Override public void run() { Drawable drawable = null; try{ drawable = Drawable.createFromStream( new URL(url).openStream(), "image.png"); }catch (IOException e){ Log.d("test", e.getMessage()); } // 模拟网络延时 SystemClock.sleep(2000); Message message = handler2.obtainMessage(); message.arg1 = id; message.obj = drawable; handler2.sendMessage(message); } }; thread.start(); thread = null; } }
这时候我们可以看到实现了异步加载, 界面打开时,五个ImageView都是没有图的,然后在各自线程下载完后才把图自动更新上去
Handler+ExecutorService(线程池)+MessageQueue模式
能开线程的个数毕竟是有限的,我们总不能开很多线程,对于手机更是如此。
这个例子是使用线程池。Android拥有与Java相同的ExecutorService实现,我们就来用它。
线程池的基本思想还是一种对象池的思想,开辟一块内存空间,里面存放了众多(未死亡)的线程,池中线程执行调度由池管理器来处理。当有线程任务时,从池中取一个,执行完成后线程对象归池,这样可以避免反复创建线程对象所带来的性能开销,节省了系统的资源。
线程池的信息可以参看这篇文章:Java&Android的线程池-ExecutorService 下面的演示例子是创建一个可重用固定线程数的线程池。
import java.io.IOException; import java.net.URL; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import android.app.Activity; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.SystemClock; import android.util.Log; import android.widget.ImageView; public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.main); loadImage3("http://www.baidu.com/img/baidu_logo.gif", R.id.imageView1); loadImage3("http://www.chinatelecom.com.cn/images/logo_new.gif", R.id.imageView2); loadImage3("http://cache.soso.com/30d/img/web/logo.gif", R.id.imageView3); loadImage3("http://csdnimg.cn/www/images/csdnindex_logo.gif", R.id.imageView4); loadImage3("http://images.cnblogs.com/logo_small.gif", R.id.imageView5); } private Handler handler = new Handler(); private ExecutorService executorService = Executors.newFixedThreadPool(5); // 引入线程池来管理多线程 private void loadImage3(final String url, final int id) { executorService.submit(new Runnable() { public void run() { try { final Drawable drawable = Drawable.createFromStream(new URL(url).openStream(), "image.png"); // 模拟网络延时 SystemClock.sleep(2000); handler.post(new Runnable() { public void run(){ ((ImageView) MainActivity.this.findViewById(id)) .setImageDrawable(drawable); } }); } catch (Exception e){ throw new RuntimeException(e); } } }); } }
这里我们象第一步一样使用了 handler.post(new Runnable() { 更新前段显示当然是在UI主线程,我们还有 executorService.submit(new Runnable() { 来确保下载是在线程池的线程中。
Handler+ExecutorService(线程池)+MessageQueue+缓存模式
下面比起前一个做了几个改造:
- 把整个代码封装在一个类中
- 为了避免出现同时多次下载同一幅图的问题,使用了本地缓存
import java.lang.ref.SoftReference; import java.net.URL; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.SystemClock; public class AsyncImageLoader3 { // 为了加快速度,在内存中开启缓存(主要应用于重复图片较多时,或者同一个图片要多次被访问,比如在ListView时来回滚动) public Map<String, SoftReference<Drawable>> imageCache = new HashMap<String, SoftReference<Drawable>>(); private ExecutorService executorService = Executors.newFixedThreadPool(5); // 固定五个线程来执行任务 private final Handler handler = new Handler(); /** * @param imageUrl 图像url地址 @param callback 回调接口 @return 返回内存中缓存的图像,第一次加载返回null */ public Drawable loadDrawable(final String imageUrl, final ImageCallback callback) { // 如果缓存过就从缓存中取出数据 if (imageCache.containsKey(imageUrl)){ SoftReference<Drawable> softReference = imageCache.get(imageUrl); if (softReference.get() != null){ return softReference.get(); } } // 缓存中没有图像,则从网络上取出数据,并将取出的数据缓存到内存中 executorService.submit(new Runnable() { public void run() { try { final Drawable drawable = loadImageFromUrl(imageUrl); imageCache.put(imageUrl, new SoftReference<Drawable>(drawable)); handler.post(new Runnable() { public void run(){ callback.imageLoaded(drawable); } }); } catch (Exception e){ throw new RuntimeException(e); } } }); return null; } // 从网络上取数据方法 protected Drawable loadImageFromUrl(String imageUrl) { try{ // 测试时,模拟网络延时,实际时这行代码不能有 SystemClock.sleep(2000); return Drawable.createFromStream(new URL(imageUrl).openStream(), "image.png"); }catch (Exception e){ throw new RuntimeException(e); } } // 对外界开放的回调接口 public interface ImageCallback{ // 注意 此方法是用来设置目标对象的图像资源 public void imageLoaded(Drawable imageDrawable); } }
说明:
final参数是指当函数参数为final类型时,你可以读取使用该参数,但是无法改变该参数的值。参看:Java关键字final、static使用总结
这里使用SoftReference 是为了解决内存不足的错误(OutOfMemoryError)的,更详细的可以参看:内存优化的两个类:SoftReference 和 WeakReference
import android.app.Activity; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.widget.ImageView; public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState){ uper.onCreate(savedInstanceState); setContentView(R.layout.main); loadImage4("http://www.baidu.com/img/baidu_logo.gif", R.id.imageView1); loadImage4("http://www.chinatelecom.com.cn/images/logo_new.gif", R.id.imageView2); loadImage4("http://cache.soso.com/30d/img/web/logo.gif", R.id.imageView3); loadImage4("http://csdnimg.cn/www/images/csdnindex_logo.gif", R.id.imageView4); loadImage4("http://images.cnblogs.com/logo_small.gif", R.id.imageView5); } private AsyncImageLoader3 asyncImageLoader3 = new AsyncImageLoader3(); // 引入线程池,并引入内存缓存功能,并对外部调用封装了接口,简化调用过程 private void loadImage4(final String url, final int id) { // 如果缓存过就会从缓存中取出图像,ImageCallback接口中方法也不会被执行 Drawable cacheImage = asyncImageLoader3.loadDrawable(url, new AsyncImageLoader3.ImageCallback() { // 请参见实现:如果第一次加载url时下面方法会执行 public void imageLoaded(Drawable imageDrawable){ ((ImageView) findViewById(id)) .setImageDrawable(imageDrawable); } }); if (cacheImage != null){ ((ImageView) findViewById(id)).setImageDrawable(cacheImage); } } }
参考资料
Android异步加载图像小结
http://blog.csdn.net/sgl870927/archive/2011/03/29/6285535.aspx
发表评论
-
android listview
2012-07-13 17:37 926ListView与Button的共存问题解决, 解决在list ... -
米聊所采用的一些技术
2012-01-31 09:52 2079nginx upstream fallback 设置 up ... -
android常用颜色
2011-11-07 08:49 1277常用颜色值: 可以完美的颜色比对的网站: http://w ... -
dialog,activity 屏蔽Home键详解
2011-11-03 09:39 0http://www.iteye.com/topic/1116 ... -
android SlidingDrawer example
2011-11-03 09:35 0http://disanji.net/2010/12/16/a ... -
play flash swf file in android with webview
2011-11-03 09:34 0http://androidforums.com/applic ... -
AnimationDrawable 在Dialog中不能动画的原因(转)
2011-11-03 09:33 1302原来在dialog的onCreate onStart调用的时候 ... -
Free Android UI library & component roundup
2011-11-03 09:27 1145http://java.dzone.com/articles/ ... -
Android Fundamentals: Scheduling Recurring Tasks
2011-11-03 09:26 982http://mobile.tutsplus.com/tuto ... -
Android ListView pull up to refresh 改造(转)
2011-11-03 09:25 2096转自: http://dengyin2000.iteye.co ... -
Android中dp和px之间进行转换
2011-11-03 09:02 2258在xml布局文件中,我们既可以设置px,也可以设置dp(或者d ... -
view的setTag() 和 getTag()应用
2011-10-31 12:19 29932View中的setTag(Onbect)表示给View添加一个 ... -
使用getIdentifier()获取资源Id
2011-10-31 12:15 8456使用getIdentifier()获取资源Id int i ... -
ListView的长按菜单___源码分析
2011-10-24 09:28 2590ListView的长按菜单___源码分析 Android的l ... -
让你的Android程序兼容多种分辨率
2011-10-24 09:20 1022http://www.android123.com.cn/an ... -
andr菜单
2011-10-24 09:18 1207Android 菜单 菜单分为两种:系统菜单和上下文菜单。 ... -
Android 长按显示上下文菜单代码
2011-10-24 09:14 5937Android 长按显示上下文 ... -
Android Asynchronous Http Client
2011-10-19 10:27 2904转自: loopj.com/android-async-htt ... -
Android canvas.drawBitmap实现透明效果
2011-09-02 14:22 23433以下是针对,canvas.drawBitmap方法实施透明效 ... -
android资源别名
2011-08-30 14:24 2319详细请参考: http://developer.android ...
相关推荐
这个"Android演化理解 Android 异步加载图片.zip"源码资源提供了对Android平台图片加载机制演进的理解和实现方法。以下是这个主题涵盖的一些关键知识点: 1. UI线程与工作线程:Android系统的主线程(UI线程)负责...
Android演化理解 Android 异步加载图片.zip项目安卓应用源码下载Android演化理解 Android 异步加载图片.zip项目安卓应用源码下载 1.适合学生毕业设计研究参考 2.适合个人学习研究参考 3.适合公司开发项目技术参考
演化理解 Android 异步加载图片.zip安卓程序源码资源下载演化理解 Android 异步加载图片.zip安卓程序源码资源下载 1.适合学生做毕业设计用 2.适合程序员学习研究用 3.适合新手自学研究使用
演化理解 Android 异步加载图片.zip项目安卓应用源码下载演化理解 Android 异步加载图片.zip项目安卓应用源码下载 1.适合学生毕业设计研究参考 2.适合个人学习研究参考 3.适合公司开发项目技术参考
在深入理解Android异步加载图片的过程中,还需要掌握Bitmap类的使用和内存管理。Bitmap对象占用了大量的内存,不当使用可能导致内存泄漏或内存抖动。因此,需要合理地配置Bitmap的配置参数,如Bitmap.Config,以及...
这个"Android演化理解 Android 异步加载图片"的压缩包文件提供了关于如何在Android平台处理图片加载的源码参考,这对于开发者来说是极其宝贵的资源。 首先,我们要了解为什么需要异步加载图片。在移动设备上,内存...
Android安卓项目源码-演化理解 Android 异步加载图片.zip
本资源"Android参考源码-演化理解 Android 异步加载图片.zip"提供了一套用于学习和参考的源代码,帮助开发者深入理解Android平台下图片异步加载的实现原理。下面,我们将详细探讨这一主题。 首先,我们要了解为什么...
"演化理解 Android 异步加载图片.zip"这个资源包,显然提供了一些关于如何在Android应用中实现高效图片异步加载的源码示例。以下是对这个主题的详细讲解: 首先,我们需要理解为什么需要异步加载图片。在Android...
本资料包"安卓图片加载缓存相关-演化理解Android异步加载图片.rar"主要探讨了Android平台上图片异步加载和缓存的策略。 首先,我们来看"Android异步加载图片"这个主题。在Android系统中,由于UI线程不能进行耗时...
总的来说,这个项目为Android开发者提供了一个实践平台,通过学习和分析源码,可以加深对Android异步加载图片机制的理解,提升实际开发技能。同时,它也是完成毕业设计的一个优秀案例,对于即将毕业的学生来说,能够...
本资料包"安卓Android源码——演化理解 Android 异步加载图片.zip"深入探讨了Android平台下图片异步加载的原理与实践,旨在帮助开发者更高效地处理这一问题。 首先,我们来了解一下Android图片异步加载的基本概念。...
总结起来,这个源码包提供了Android异步加载图片的多种实现方式,涵盖了从早期的Universal Image Loader到现代的Glide、Fresco,以及Kotlin协程的使用。通过深入研究这些源码,开发者不仅可以掌握异步加载图片的最佳...
下面将详细探讨Android异步加载图片的原理、方法和最佳实践。 1. **异步加载图片的重要性**: - 用户体验:避免因图片加载导致的UI卡顿,提高应用响应速度。 - 资源优化:减少内存占用,防止OOM(OutOfMemory)...
在Android应用开发中,...综上所述,Android异步加载图片是一个涉及多方面技术的综合课题,包括异步编程模型、图片库选择、缓存策略、资源管理等。理解和掌握这些知识点,对于开发流畅、高效的Android应用至关重要。
这个"Android演化理解Android异步加载图片"的项目,是针对Android源码的学习和毕业设计的一个实例,旨在帮助开发者深入理解如何在Android平台上有效地处理图片加载,以避免UI阻塞,提高应用性能。 首先,我们需要...
免责声明:资料部分来源于合法的互联网渠道收集和整理,部分自己学习积累成果,供大家学习参考与交流。收取的费用仅用于收集和整理资料耗费时间的酬劳。 本人尊重原创作者或出版方,资料版权归原作者或出版方所有,...