Android中的软引用(SoftRefrerence)和弱引用(WeakReference)
来源:互联网 发布:多维数据可视化方法 编辑:程序博客网 时间:2024/05/21 09:48
在Android开发中,基本上很少有用到软引用或弱引用,这两个东东若用的很好,对自己开发的代码质量的提高有很大的帮助。若用的不好,会坑了自己。所以,在还没有真正的去了解它们之前,还是慎用比较好。
下面将通过两个Demo来结识软引用和弱引用在开发中的运用。
一. WeakReference:防止内存泄漏,要保证内存被虚拟机回收。
下面以一个时间更新的Demo来说明弱引用的运用。
1. main.xml文件代码如下:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <com.stevenhu.wrt.DigitalClock android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <TextView android:id="@+id/time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="50pt" /> <TextView android:id="@+id/ampm" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="25pt" /> </com.stevenhu.wrt.DigitalClock></LinearLayout>2.自定义ViewGroup类DigitalClock的代码如下:
package com.stevenhu.wrt;import java.lang.ref.WeakReference;import java.text.DateFormatSymbols;import java.util.Calendar;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.database.ContentObserver;import android.graphics.Canvas;import android.os.Handler;import android.provider.Settings;import android.text.format.DateFormat;import android.util.AttributeSet;import android.view.View;import android.widget.LinearLayout;import android.widget.TextView;import android.widget.Toast;public class DigitalClock extends LinearLayout {// 12小时、24小时制private final static String M12 = "h:mm";private final static String M24 = "kk:mm";private Calendar mCalendar;private String mFormat;private TextView mDislpayTime;private AmPm mAmPm;private ContentObserver mFormatChangeObserver;private final Handler mHandler = new Handler();private BroadcastReceiver mReceiver;private Context mContext;public DigitalClock(Context context, AttributeSet attrs) {super(context, attrs);mContext = context;// TODO Auto-generated constructor stub}@Overrideprotected void onFinishInflate() {// TODO Auto-generated method stubsuper.onFinishInflate();mDislpayTime = (TextView) this.findViewById(R.id.time);mAmPm = new AmPm(this);mCalendar = Calendar.getInstance();//设置时间显示格式setDateFormat();}@Overrideprotected void onAttachedToWindow() {// TODO Auto-generated method stubsuper.onAttachedToWindow();//动态注册监听时间改变的广播if (mReceiver == null) {mReceiver = new TimeChangedReceiver(this);IntentFilter filter = new IntentFilter();filter.addAction(Intent.ACTION_TIME_TICK);filter.addAction(Intent.ACTION_TIME_CHANGED);filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);mContext.registerReceiver(mReceiver, filter);}//注册监听时间格式改变的ContentObserverif (mFormatChangeObserver == null) {mFormatChangeObserver = new FormatChangeObserver(this);mContext.getContentResolver().registerContentObserver(Settings.System.CONTENT_URI, true, mFormatChangeObserver);}//更新时间updateTime();}@Overrideprotected void onDetachedFromWindow() {// TODO Auto-generated method stubsuper.onDetachedFromWindow();if (mReceiver != null) {mContext.unregisterReceiver(mReceiver);}if (mFormatChangeObserver != null) {mContext.getContentResolver().unregisterContentObserver(mFormatChangeObserver);}mFormatChangeObserver = null;mReceiver = null;}static class AmPm {private TextView mAmPmTextView;private String mAmString, mPmString;AmPm(View parent) {mAmPmTextView = (TextView) parent.findViewById(R.id.ampm);String[] ampm = new DateFormatSymbols().getAmPmStrings();mAmString = ampm[0];mPmString = ampm[1];}void setShowAmPm(boolean show) {if (mAmPmTextView != null) {mAmPmTextView.setVisibility(show ? View.VISIBLE : View.GONE);}}void setIsMorning(boolean isMorning) {if (mAmPmTextView != null) {mAmPmTextView.setText(isMorning ? mAmString : mPmString);}}}/*时间刷新涉及到View的更新显示(特别是每秒刷新显示,这样的频率特别高),当然,此处的时间显示是每分钟更新一次 * 所以在监听时间更新的广播中采用弱引用,防止在不断刷新当前界面View时产生内存泄露 */private static class TimeChangedReceiver extends BroadcastReceiver {//采用弱引用private WeakReference<DigitalClock> mClock;private Context mContext;public TimeChangedReceiver(DigitalClock clock) {mClock = new WeakReference<DigitalClock>(clock);mContext = clock.getContext();}@Overridepublic void onReceive(Context context, Intent intent) {// Post a runnable to avoid blocking the broadcast.final boolean timezoneChanged = intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED);//从弱引用中获取对象final DigitalClock clock = mClock.get();if (clock != null) {clock.mHandler.post(new Runnable() {public void run() {if (timezoneChanged) {clock.mCalendar = Calendar.getInstance();}clock.updateTime();}});} else {try {mContext.unregisterReceiver(this);} catch (RuntimeException e) {// Shouldn't happen}}}};// 监听时间显示的格式改变private static class FormatChangeObserver extends ContentObserver {// 采用弱应用private WeakReference<DigitalClock> mClock;private Context mContext;public FormatChangeObserver(DigitalClock clock) {super(new Handler());mClock = new WeakReference<DigitalClock>(clock);mContext = clock.getContext();}@Overridepublic void onChange(boolean selfChange) {DigitalClock digitalClock = mClock.get();//从弱引用中取出对象if (digitalClock != null) {//根据弱引用中取出的对象进行时间更新digitalClock.setDateFormat();digitalClock.updateTime();} else {try {mContext.getContentResolver().unregisterContentObserver(this);} catch (RuntimeException e) {// Shouldn't happen}}}}// 更新时间private void updateTime() {Toast.makeText(mContext, "updateTime", Toast.LENGTH_SHORT).show();mCalendar.setTimeInMillis(System.currentTimeMillis());CharSequence newTime = DateFormat.format(mFormat, mCalendar);mDislpayTime.setText(newTime);mAmPm.setIsMorning(mCalendar.get(Calendar.AM_PM) == 0);}private void setDateFormat() {// 获取时间制mFormat = android.text.format.DateFormat.is24HourFormat(getContext()) ? M24: M12;// 根据时间制显示上午、下午mAmPm.setShowAmPm(mFormat.equals(M12));}@Overrideprotected void onDraw(Canvas canvas) {// TODO Auto-generated method stubsuper.onDraw(canvas);//Toast.makeText(mContext, "ddd", Toast.LENGTH_SHORT).show();}}3.MainActivity的代码如下:
package com.stevenhu.wrt;import android.app.Activity;import android.os.Bundle;public class MainActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); }}
二. SoftReference:实现缓存机制
下面的Demo实现从网络上获取图片,然后将获取的图片显示的同时,通过软引用缓存起来。当下次再去网络上获取图片时,首先会检查要获取的图片缓存中是否存在,若存在,直接取出来,不需要再去网络上获取。
1.main.xml文件代码如下:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <Button android:id="@+id/get_image" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="get Image"/> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <ImageView android:id="@+id/one" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <ImageView android:id="@+id/two" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <ImageView android:id="@+id/three" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout> </LinearLayout>2.实现异步加载图片功能的类AsyncImageLoader代码如下:
package com.stevenhu.lit;import java.lang.ref.SoftReference;import java.net.URL;import java.util.HashMap;import java.util.Map;import android.graphics.drawable.Drawable;import android.os.Handler;import android.os.Message;//实现图片异步加载的类public class AsyncImageLoader {//以Url为键,SoftReference为值,建立缓存HashMap键值对。private Map<String, SoftReference<Drawable>> mImageCache = new HashMap<String, SoftReference<Drawable>>();//实现图片异步加载public Drawable loadDrawable(final String imageUrl, final ImageCallback callback){//查询缓存,查看当前需要下载的图片是否在缓存中if(mImageCache.containsKey(imageUrl)){SoftReference<Drawable> softReference = mImageCache.get(imageUrl);if (softReference.get() != null){return softReference.get();}}final Handler handler = new Handler(){@Overridepublic void dispatchMessage(Message msg) {//回调ImageCallbackImpl中的imageLoad方法,在主线(UI线程)中执行。callback.imageLoad((Drawable)msg.obj);}};/*若缓存中没有,新开辟一个线程,用于进行从网络上下载图片, * 然后将获取到的Drawable发送到Handler中处理,通过回调实现在UI线程中显示获取的图片 */new Thread(){public void run() {Drawable drawable = loadImageFromUrl(imageUrl);//将得到的图片存放到缓存中mImageCache.put(imageUrl, new SoftReference<Drawable>(drawable));Message message = handler.obtainMessage(0, drawable);handler.sendMessage(message);};}.start();//若缓存中不存在,将从网上下载显示完成后,此处返回null;return null;}//定义一个回调接口public interface ImageCallback{void imageLoad(Drawable drawable);}//通过Url从网上获取图片Drawable对象;protected Drawable loadImageFromUrl(String imageUrl){try {return Drawable.createFromStream(new URL(imageUrl).openStream(),"debug");} catch (Exception e) {// TODO: handle exceptionthrow new RuntimeException(e);}}}3. 实现ImageCallback回调接口的类ImageCallbackImpl代码如下:
package com.stevenhu.lit;import android.graphics.drawable.Drawable;import android.widget.ImageView;import com.stevenhu.lit.AsyncImageLoader.ImageCallback;public class ImageCallbackImpl implements ImageCallback{private ImageView mImageView;public ImageCallbackImpl(ImageView imageView){mImageView = imageView;}//在ImageView中显示从网上获取的图片@Overridepublic void imageLoad(Drawable drawable) {// TODO Auto-generated method stubmImageView.setImageDrawable(drawable);}}4.MainActivity的代码如下:
package com.stevenhu.lit;import android.app.Activity;import android.graphics.drawable.Drawable;import android.os.Bundle;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.ImageView;public class MainActivity extends Activity implements OnClickListener{//创建异步加载图片类对象private AsyncImageLoader mImageLoader = new AsyncImageLoader(); /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Button get = (Button)findViewById(R.id.get_image); get.setOnClickListener(this); } private void loadImage(final String url, final int id) { ImageView imageView = (ImageView)findViewById(id); ImageCallbackImpl callbackImpl = new ImageCallbackImpl(imageView); Drawable cacheImage = mImageLoader.loadDrawable(url, callbackImpl); //若缓存中存在,直接取出来显示 if (cacheImage != null) { imageView.setImageDrawable(cacheImage); } }@Overridepublic void onClick(View v) {// TODO Auto-generated method stubif (v.getId() == R.id.get_image){//从网络上获取海贼王的三张图片显示loadImage("http://wenwen.soso.com/p/20111003/20111003194816-1615366606.jpg", R.id.one); loadImage("http://t10.baidu.com/it/u=2492256852,4267838923&fm=23&gp=0.jpg", R.id.two); loadImage("http://wenwen.soso.com/p/20100410/20100410102416-1948049438.jpg", R.id.three);}}}
最后,对于这两者,作个小总结:
1. SoftReference<T>:软引用-->当虚拟机内存不足时,将会回收它指向的对象;需要获取对象时,可以调用get方法。
2. WeakReference<T>:弱引用-->随时可能会被垃圾回收器回收,不一定要等到虚拟机内存不足时才强制回收。要获取对象时,同样可以调用get方法。
3. WeakReference一般用来防止内存泄漏,要保证内存被虚拟机回收,SoftReference多用作来实现缓存机制(cache);
两个Demo的下载链接如下:http://download.csdn.net/detail/stevenhu_223/6855591 5 0
- Android中的软引用(SoftRefrerence)和弱引用(WeakReference)
- Android中的软引用(SoftRefrerence)和弱引用(WeakReference)
- Android中的软引用(SoftRefrerence)和弱引用(WeakReference)
- Android中的软引用(SoftRefrerence)和弱引用(WeakReference)
- Android中的软引用(SoftRefrerence)和弱引用(WeakReference)介绍
- Android中的软引用(SoftRefrerence)和弱引用(WeakReference)
- Android中的软引用(SoftRefrerence)和弱引用(WeakReference)
- Android中的软引用(SoftRefrerence)和弱引用(WeakReference)
- Android中的软引用(SoftRefrerence)和弱引用(WeakReference)
- Android-软引用(SoftRefrerence)和弱引用(WeakReference)
- Android 图片三级缓存之内存缓存(告别软引用(SoftRefrerence)和弱引用(WeakReference))
- Android 图片三级缓存之内存缓存(告别软引用(SoftRefrerence)和弱引用(WeakReference))
- Android 图片三级缓存之内存缓存(告别软引用(SoftRefrerence)和弱引用(WeakReference))
- Android 图片三级缓存之内存缓存(告别软引用(SoftRefrerence)和弱引用(WeakReference))
- Android 图片三级缓存之内存缓存(告别软引用(SoftRefrerence)和弱引用(WeakReference))
- Android 图片三级缓存之内存缓存(告别软引用(SoftRefrerence)和弱引用(WeakReference))
- Android 图片三级缓存之内存缓存(告别软引用(SoftRefrerence)和弱引用(WeakReference))
- Android 图片三级缓存之内存缓存(告别软引用(SoftRefrerence)和弱引用(WeakReference))
- iOS开发ASIHttpRequest介绍(四)--ASIHTTPRequest身份验证
- uva Diatribe against Pigeonholes (模拟 但是被分在DP的类别中)
- Maven Error
- 入门Python自带编辑器IDLE
- git的使用注意事项
- Android中的软引用(SoftRefrerence)和弱引用(WeakReference)
- Cache学习(UC, WC)
- 基于arm的一个简单的led驱动
- 字符串对点按段翻转
- layout_gravity 和 Relativelayout
- js数组的操作
- 树状数组求逆序数
- ThinkPad产品如何升级BIOS程序
- IOS 实战xmpp