在Android开发中,基本上很少有用到软引用或弱引用,这两个东东若用的很好,对自己开发的代码质量的提高有很大的帮助。若用的不好,会坑了自己。所以,在还没有真正的去了解它们之前,还是慎用比较好。

下面将通过两个Demo来结识软引用和弱引用在开发中的运用。

一. WeakReference:防止内存泄漏,要保证内存被虚拟机回收。

下面以一个时间更新的Demo来说明弱引用的运用。

1. main.xml文件代码如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="fill_parent"
  4. android:layout_height="fill_parent"
  5. android:orientation="vertical" >
  6. <com.stevenhu.wrt.DigitalClock
  7. android:layout_width="match_parent"
  8. android:layout_height="match_parent"
  9. android:orientation="horizontal">
  10. <TextView android:id="@+id/time"
  11. android:layout_width="wrap_content"
  12. android:layout_height="wrap_content"
  13. android:textSize="50pt"
  14. />
  15. <TextView android:id="@+id/ampm"
  16. android:layout_width="wrap_content"
  17. android:layout_height="wrap_content"
  18. android:textSize="25pt"
  19. />
  20. </com.stevenhu.wrt.DigitalClock>
  21. </LinearLayout>

2.自定义ViewGroup类DigitalClock的代码如下:

  1. package com.stevenhu.wrt;
  2. import java.lang.ref.WeakReference;
  3. import java.text.DateFormatSymbols;
  4. import java.util.Calendar;
  5. import android.content.BroadcastReceiver;
  6. import android.content.Context;
  7. import android.content.Intent;
  8. import android.content.IntentFilter;
  9. import android.database.ContentObserver;
  10. import android.graphics.Canvas;
  11. import android.os.Handler;
  12. import android.provider.Settings;
  13. import android.text.format.DateFormat;
  14. import android.util.AttributeSet;
  15. import android.view.View;
  16. import android.widget.LinearLayout;
  17. import android.widget.TextView;
  18. import android.widget.Toast;
  19. public class DigitalClock extends LinearLayout {
  20. // 12小时、24小时制
  21. private final static String M12 = "h:mm";
  22. private final static String M24 = "kk:mm";
  23. private Calendar mCalendar;
  24. private String mFormat;
  25. private TextView mDislpayTime;
  26. private AmPm mAmPm;
  27. private ContentObserver mFormatChangeObserver;
  28. private final Handler mHandler = new Handler();
  29. private BroadcastReceiver mReceiver;
  30. private Context mContext;
  31. public DigitalClock(Context context, AttributeSet attrs) {
  32. super(context, attrs);
  33. mContext = context;
  34. // TODO Auto-generated constructor stub
  35. }
  36. @Override
  37. protected void onFinishInflate() {
  38. // TODO Auto-generated method stub
  39. super.onFinishInflate();
  40. mDislpayTime = (TextView) this.findViewById(R.id.time);
  41. mAmPm = new AmPm(this);
  42. mCalendar = Calendar.getInstance();
  43. //设置时间显示格式
  44. setDateFormat();
  45. }
  46. @Override
  47. protected void onAttachedToWindow() {
  48. // TODO Auto-generated method stub
  49. super.onAttachedToWindow();
  50. //动态注册监听时间改变的广播
  51. if (mReceiver == null) {
  52. mReceiver = new TimeChangedReceiver(this);
  53. IntentFilter filter = new IntentFilter();
  54. filter.addAction(Intent.ACTION_TIME_TICK);
  55. filter.addAction(Intent.ACTION_TIME_CHANGED);
  56. filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
  57. mContext.registerReceiver(mReceiver, filter);
  58. }
  59. //注册监听时间格式改变的ContentObserver
  60. if (mFormatChangeObserver == null) {
  61. mFormatChangeObserver = new FormatChangeObserver(this);
  62. mContext.getContentResolver().registerContentObserver(
  63. Settings.System.CONTENT_URI, true, mFormatChangeObserver);
  64. }
  65. //更新时间
  66. updateTime();
  67. }
  68. @Override
  69. protected void onDetachedFromWindow() {
  70. // TODO Auto-generated method stub
  71. super.onDetachedFromWindow();
  72. if (mReceiver != null) {
  73. mContext.unregisterReceiver(mReceiver);
  74. }
  75. if (mFormatChangeObserver != null) {
  76. mContext.getContentResolver().unregisterContentObserver(
  77. mFormatChangeObserver);
  78. }
  79. mFormatChangeObserver = null;
  80. mReceiver = null;
  81. }
  82. static class AmPm {
  83. private TextView mAmPmTextView;
  84. private String mAmString, mPmString;
  85. AmPm(View parent) {
  86. mAmPmTextView = (TextView) parent.findViewById(R.id.ampm);
  87. String[] ampm = new DateFormatSymbols().getAmPmStrings();
  88. mAmString = ampm[0];
  89. mPmString = ampm[1];
  90. }
  91. void setShowAmPm(boolean show) {
  92. if (mAmPmTextView != null) {
  93. mAmPmTextView.setVisibility(show ? View.VISIBLE : View.GONE);
  94. }
  95. }
  96. void setIsMorning(boolean isMorning) {
  97. if (mAmPmTextView != null) {
  98. mAmPmTextView.setText(isMorning ? mAmString : mPmString);
  99. }
  100. }
  101. }
  102. /*时间刷新涉及到View的更新显示(特别是每秒刷新显示,这样的频率特别高),当然,此处的时间显示是每分钟更新一次
  103. * 所以在监听时间更新的广播中采用弱引用,防止在不断刷新当前界面View时产生内存泄露
  104. */
  105. private static class TimeChangedReceiver extends BroadcastReceiver {
  106. //采用弱引用
  107. private WeakReference<DigitalClock> mClock;
  108. private Context mContext;
  109. public TimeChangedReceiver(DigitalClock clock) {
  110. mClock = new WeakReference<DigitalClock>(clock);
  111. mContext = clock.getContext();
  112. }
  113. @Override
  114. public void onReceive(Context context, Intent intent) {
  115. // Post a runnable to avoid blocking the broadcast.
  116. final boolean timezoneChanged = intent.getAction().equals(
  117. Intent.ACTION_TIMEZONE_CHANGED);
  118. //从弱引用中获取对象
  119. final DigitalClock clock = mClock.get();
  120. if (clock != null) {
  121. clock.mHandler.post(new Runnable() {
  122. public void run() {
  123. if (timezoneChanged) {
  124. clock.mCalendar = Calendar.getInstance();
  125. }
  126. clock.updateTime();
  127. }
  128. });
  129. } else {
  130. try {
  131. mContext.unregisterReceiver(this);
  132. } catch (RuntimeException e) {
  133. // Shouldn't happen
  134. }
  135. }
  136. }
  137. };
  138. // 监听时间显示的格式改变
  139. private static class FormatChangeObserver extends ContentObserver {
  140. // 采用弱应用
  141. private WeakReference<DigitalClock> mClock;
  142. private Context mContext;
  143. public FormatChangeObserver(DigitalClock clock) {
  144. super(new Handler());
  145. mClock = new WeakReference<DigitalClock>(clock);
  146. mContext = clock.getContext();
  147. }
  148. @Override
  149. public void onChange(boolean selfChange) {
  150. DigitalClock digitalClock = mClock.get();
  151. //从弱引用中取出对象
  152. if (digitalClock != null) {
  153. //根据弱引用中取出的对象进行时间更新
  154. digitalClock.setDateFormat();
  155. digitalClock.updateTime();
  156. } else {
  157. try {
  158. mContext.getContentResolver().unregisterContentObserver(
  159. this);
  160. } catch (RuntimeException e) {
  161. // Shouldn't happen
  162. }
  163. }
  164. }
  165. }
  166. // 更新时间
  167. private void updateTime() {
  168. Toast.makeText(mContext, "updateTime", Toast.LENGTH_SHORT).show();
  169. mCalendar.setTimeInMillis(System.currentTimeMillis());
  170. CharSequence newTime = DateFormat.format(mFormat, mCalendar);
  171. mDislpayTime.setText(newTime);
  172. mAmPm.setIsMorning(mCalendar.get(Calendar.AM_PM) == 0);
  173. }
  174. private void setDateFormat() {
  175. // 获取时间制
  176. mFormat = android.text.format.DateFormat.is24HourFormat(getContext()) ? M24
  177. : M12;
  178. // 根据时间制显示上午、下午
  179. mAmPm.setShowAmPm(mFormat.equals(M12));
  180. }
  181. @Override
  182. protected void onDraw(Canvas canvas) {
  183. // TODO Auto-generated method stub
  184. super.onDraw(canvas);
  185. //Toast.makeText(mContext, "ddd", Toast.LENGTH_SHORT).show();
  186. }
  187. }

3.MainActivity的代码如下:

  1. package com.stevenhu.wrt;
  2. import android.app.Activity;
  3. import android.os.Bundle;
  4. public class MainActivity extends Activity {
  5. /** Called when the activity is first created. */
  6. @Override
  7. public void onCreate(Bundle savedInstanceState) {
  8. super.onCreate(savedInstanceState);
  9. setContentView(R.layout.main);
  10. }
  11. }

二. SoftReference:实现缓存机制

下面的Demo实现从网络上获取图片,然后将获取的图片显示的同时,通过软引用缓存起来。当下次再去网络上获取图片时,首先会检查要获取的图片缓存中是否存在,若存在,直接取出来,不需要再去网络上获取。

1.main.xml文件代码如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="fill_parent"
  4. android:layout_height="fill_parent"
  5. android:orientation="vertical" >
  6. <Button
  7. android:id="@+id/get_image"
  8. android:layout_width="fill_parent"
  9. android:layout_height="wrap_content"
  10. android:text="get Image"/>
  11. <LinearLayout
  12. android:layout_width="match_parent"
  13. android:layout_height="match_parent"
  14. android:orientation="vertical">
  15. <ImageView
  16. android:id="@+id/one"
  17. android:layout_width="wrap_content"
  18. android:layout_height="wrap_content"/>
  19. <ImageView
  20. android:id="@+id/two"
  21. android:layout_width="wrap_content"
  22. android:layout_height="wrap_content"/>
  23. <ImageView
  24. android:id="@+id/three"
  25. android:layout_width="wrap_content"
  26. android:layout_height="wrap_content"/>
  27. </LinearLayout>
  28. </LinearLayout>

2.实现异步加载图片功能的类AsyncImageLoader代码如下:

  1. package com.stevenhu.lit;
  2. import java.lang.ref.SoftReference;
  3. import java.net.URL;
  4. import java.util.HashMap;
  5. import java.util.Map;
  6. import android.graphics.drawable.Drawable;
  7. import android.os.Handler;
  8. import android.os.Message;
  9. //实现图片异步加载的类
  10. public class AsyncImageLoader
  11. {
  12. //以Url为键,SoftReference为值,建立缓存HashMap键值对。
  13. private Map<String, SoftReference<Drawable>> mImageCache =
  14. new HashMap<String, SoftReference<Drawable>>();
  15. //实现图片异步加载
  16. public Drawable loadDrawable(final String imageUrl, final ImageCallback callback)
  17. {
  18. //查询缓存,查看当前需要下载的图片是否在缓存中
  19. if(mImageCache.containsKey(imageUrl))
  20. {
  21. SoftReference<Drawable> softReference = mImageCache.get(imageUrl);
  22. if (softReference.get() != null)
  23. {
  24. return softReference.get();
  25. }
  26. }
  27. final Handler handler = new Handler()
  28. {
  29. @Override
  30. public void dispatchMessage(Message msg)
  31. {
  32. //回调ImageCallbackImpl中的imageLoad方法,在主线(UI线程)中执行。
  33. callback.imageLoad((Drawable)msg.obj);
  34. }
  35. };
  36. /*若缓存中没有,新开辟一个线程,用于进行从网络上下载图片,
  37. * 然后将获取到的Drawable发送到Handler中处理,通过回调实现在UI线程中显示获取的图片
  38. */
  39. new Thread()
  40. {
  41. public void run()
  42. {
  43. Drawable drawable = loadImageFromUrl(imageUrl);
  44. //将得到的图片存放到缓存中
  45. mImageCache.put(imageUrl, new SoftReference<Drawable>(drawable));
  46. Message message = handler.obtainMessage(0, drawable);
  47. handler.sendMessage(message);
  48. };
  49. }.start();
  50. //若缓存中不存在,将从网上下载显示完成后,此处返回null;
  51. return null;
  52. }
  53. //定义一个回调接口
  54. public interface ImageCallback
  55. {
  56. void imageLoad(Drawable drawable);
  57. }
  58. //通过Url从网上获取图片Drawable对象;
  59. protected Drawable loadImageFromUrl(String imageUrl)
  60. {
  61. try {
  62. return Drawable.createFromStream(new URL(imageUrl).openStream(),"debug");
  63. } catch (Exception e) {
  64. // TODO: handle exception
  65. throw new RuntimeException(e);
  66. }
  67. }
  68. }

3. 实现ImageCallback回调接口的类ImageCallbackImpl代码如下:

  1. package com.stevenhu.lit;
  2. import android.graphics.drawable.Drawable;
  3. import android.widget.ImageView;
  4. import com.stevenhu.lit.AsyncImageLoader.ImageCallback;
  5. public class ImageCallbackImpl implements ImageCallback
  6. {
  7. private ImageView mImageView;
  8. public ImageCallbackImpl(ImageView imageView)
  9. {
  10. mImageView = imageView;
  11. }
  12. //在ImageView中显示从网上获取的图片
  13. @Override
  14. public void imageLoad(Drawable drawable)
  15. {
  16. // TODO Auto-generated method stub
  17. mImageView.setImageDrawable(drawable);
  18. }
  19. }

4.MainActivity的代码如下:

  1. package com.stevenhu.lit;
  2. import android.app.Activity;
  3. import android.graphics.drawable.Drawable;
  4. import android.os.Bundle;
  5. import android.view.View;
  6. import android.view.View.OnClickListener;
  7. import android.widget.Button;
  8. import android.widget.ImageView;
  9. public class MainActivity extends Activity implements OnClickListener
  10. {
  11. //创建异步加载图片类对象
  12. private AsyncImageLoader mImageLoader = new AsyncImageLoader();
  13. /** Called when the activity is first created. */
  14. @Override
  15. public void onCreate(Bundle savedInstanceState)
  16. {
  17. super.onCreate(savedInstanceState);
  18. setContentView(R.layout.main);
  19. Button get = (Button)findViewById(R.id.get_image);
  20. get.setOnClickListener(this);
  21. }
  22. private void loadImage(final String url, final int id)
  23. {
  24. ImageView imageView = (ImageView)findViewById(id);
  25. ImageCallbackImpl callbackImpl = new ImageCallbackImpl(imageView);
  26. Drawable cacheImage = mImageLoader.loadDrawable(url, callbackImpl);
  27. //若缓存中存在,直接取出来显示
  28. if (cacheImage != null)
  29. {
  30. imageView.setImageDrawable(cacheImage);
  31. }
  32. }
  33. @Override
  34. public void onClick(View v) {
  35. // TODO Auto-generated method stub
  36. if (v.getId() == R.id.get_image)
  37. {
  38. //从网络上获取海贼王的三张图片显示
  39. loadImage("http://wenwen.soso.com/p/20111003/20111003194816-1615366606.jpg", R.id.one);
  40. loadImage("http://t10.baidu.com/it/u=2492256852,4267838923&fm=23&gp=0.jpg", R.id.two);
  41. loadImage("http://wenwen.soso.com/p/20100410/20100410102416-1948049438.jpg", R.id.three);
  42. }
  43. }
  44. }

最后,对于这两者,作个小总结:

1.  SoftReference<T>:软引用-->当虚拟机内存不足时,将会回收它指向的对象;需要获取对象时,可以调用get方法。

2.  WeakReference<T>:弱引用-->随时可能会被垃圾回收器回收,不一定要等到虚拟机内存不足时才强制回收。要获取对象时,同样可以调用get方法。

3. WeakReference一般用来防止内存泄漏,要保证内存被虚拟机回收,SoftReference多用作来实现缓存机制(cache);

note:转自http://blog.csdn.net/stevenhu_223/article/details/18360397

android WeakReference(弱引用 防止内存泄漏)与SoftReference(软引用 实现缓存机制(cache))的更多相关文章

  1. Android性能优化之避免内存泄漏的建议

    在android程序开发中,内存泄漏问题是比较常见的问题,相信有过一些android编程经历的程序猿都遇到过各种各样的内存泄漏.内存泄漏是造成应用程序OOM的主要原因之一,是编程中必须避免的问题.下面 ...

  2. android内存优化发展——使用软引用

    整个Android开发者一定是遇到了内存溢出这个头疼的问题,一旦这个问题.很难直接决定我们的应用程序是哪里出了问题,为了找到问题的解决方案,必须累积发行通过一些内存分析工具高速定位和强大的体验,现在详 ...

  3. 安卓android WebView Memory Leak WebView内存泄漏

    Android WebView Memory Leak WebView内存泄漏 在这次开发过程中,需要用到webview展示一些界面,但是加载的页面如果有很多图片就会发现内存占用暴涨,并且在退出该界面 ...

  4. 用Linkedhashmap的LRU特性及SoftReference软引用构建二级缓存

    LRU: least recently used(近期最少使用算法).LinkedHashMap构造函数可以指定其迭代顺序:LinkedHashMap(int initialCapacity, flo ...

  5. Android学习笔记之SoftReference软引用,弱引用WeakReference

    SoftReference可以用于bitmap缓存 WeakReference 可以用于handler 非静态内部类和匿名内部类容易造成内存泄漏 private Handler mRemoteHand ...

  6. Java 理论与实践: 用弱引用堵住内存泄漏---转载

    要让垃圾收集(GC)回收程序不再使用的对象,对象的逻辑 生命周期(应用程序使用它的时间)和对该对象拥有的引用的实际 生命周期必须是相同的.在大多数时候,好的软件工程技术保证这是自动实现的,不用我们对对 ...

  7. Java 理论与实践: 用弱引用堵住内存泄漏

    弱引用使得表达对象生命周期关系变得容易了 虽然用 Java™ 语言编写的程序在理论上是不会出现“内存泄漏”的,但是有时对象在不再作为程序的逻辑状态的一部分之后仍然不被垃圾收集.本月,负责保障应用程序健 ...

  8. 分析ThreadLocal的弱引用与内存泄漏问题

    目录 一.介绍 二.问题提出 2.1内存原理图 2.2几个问题 三.回答问题 3.1为什么会出现内存泄漏 3.2若Entry使用弱引用 3.3弱引用配合自动回收 四.总结 一.介绍 之前使用Threa ...

  9. Android WebView Memory Leak WebView内存泄漏

    在这次开发过程中,需要用到webview展示一些界面,但是加载的页面如果有很多图片就会发现内存占用暴涨,并且在退出该界面后,即使在包含该webview的Activity的destroy()方法中,使用 ...

随机推荐

  1. Codeforces Round #323 (Div. 1) A. GCD Table

    A. GCD Table time limit per test 2 seconds memory limit per test 256 megabytes input standard input ...

  2. Australian troops to the fight against Islamic State militants.

    He arrived in Arnhem Land on Sunday, honouring an election promise to spend a week every year in an ...

  3. STM32中断管理函数

    CM3 内核支持256 个中断,其中包含了16 个内核中断和240 个外部中断,并且具有256 级的可编程中断设置.但STM32 并没有使用CM3 内核的全部东西,而是只用了它的一部分. STM32 ...

  4. patchca验证码的使用

    /** * 生成验证码 */ private static RandomFontFactory ff = null; // 自定义验证码图片背景 private static MyCustomBack ...

  5. html页面3秒后自动跳转的方法有哪些

    在进行web前端开发实战练习时,我们常常遇到一种问题就是,web前端开发应该如何实现页面N秒之后自动跳转呢?通过查找相关html教程,总结了3个方法: 方法1: 最简单的一种:直接在前面<hea ...

  6. python简易爬虫来实现自动图片下载

    菜鸟新人刚刚入住博客园,先发个之前写的简易爬虫的实现吧,水平有限请轻喷. 估计利用python实现爬虫的程序网上已经有太多了,不过新人用来练手学习python确实是个不错的选择.本人借鉴网上的部分实现 ...

  7. myeclipse2014 svn插件添加

    http://blog.csdn.net/sushengmiyan/article/details/38342411

  8. Java随笔一

    1.继承:子类调用超类构造器时,super调用构造器的语句必须是子类构造器的第一条语句: Java没有多继承,但是可以构造实现多个接口的类: 2.多态:Java 中,对象变量是多态的.一个父类变量既可 ...

  9. W3C代码标准规范

    一.目的: 为什么要遵循标准我们作为生产者实际上只是位于中游,既不是上游的浏览器制造商,他们是标准的真正制定者,也不算是下游,他们是浏览器的终端使用者.这个角色就意味着我们位于一个接口的位置,我们需要 ...

  10. PHP之数组array

    $switching = array(         10, // key = 0                    5    =>  6,                    3    ...