## 如何查看一个app在安卓系统中的内存分配情况?
方法一:
1.启动android studio和虚拟机,建立连接。
2.打开cmd窗口,输入adb shell。
3.输入ps。
4.可以看到有一个name为应用包名的进程,这就是我们的app所在的进程
5.为了具体查看app所在进程的内存使用情况,需输入dumpsys meminfo +包名。
方法二:
float total_memory=
Runtime.getRuntime().totalMemory()*1.0f/1024/1024; float free_memory= Runtime.getRuntime().freeMemory()*1.0f/1024/1024; float max_memory= Runtime.getRuntime().maxMemory()*1.0f/1024/1024;
方法三:
打开android studio的android monitor。
方法四:
打开android studio的Tools→Android→Android Device Monitor。
ActivityManager manager= (ActivityManager)getSystemService(ACTIVITY_SERVICE);
int memory=manager.getMemoryClass(); int large=manager.getLargeMemoryClass();//大部分情况下二者相同
强引用就是平时的写法。
软引用的用法。(虚引用与之类似)
private Map<String, SoftReference<Bitmap>> imageCache = new HashMap<String, SoftReference<Bitmap>>(); public void addBitmapToCache(String path) { // 强引用的Bitmap对象 Bitmap bitmap = BitmapFactory.decodeFile(path); // 软引用的Bitmap对象 SoftReference<Bitmap> softBitmap = new SoftReference<Bitmap>(bitmap); //WeakReference<Bitmap> weakBitmap=new WeakReference<Bitmap>(bitmap); TranslateAnimation animation; // 添加该对象到Map中使其缓存 imageCache.put(path, softBitmap); } public Bitmap getBitmapByPath(String path) { // 从缓存中取软引用的Bitmap对象 SoftReference<Bitmap> softBitmap = imageCache.get(path); // 判断是否存在软引用 if (softBitmap == null) { return null; } // 取出Bitmap对象,如果由于内存不足Bitmap被回收,将取得空 return softBitmap.get(); }
考虑如下情景:有些成员变量使用几次后就不使用了,但仍占据着内存空间,它们随着Activity的销毁而被回收,即使GC触发垃圾回收也不会对其进行回收,此时可用把它们放在SoftReference中,放入与读取见上述代码,GC触发垃圾回收时就可对其进行回收了。
1.BitmapFactory.Options类
BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(getResources(),R.drawable.yin,options);//不直接加载,获取bitmap图片宽高 BitmapFactory.Options options2 = new BitmapFactory.Options(); options2.inSampleSize = scale; Bitmap bitmap1= BitmapFactory.decodeResource(getResources(),R.drawable.yin,options2);//scale越大,图片越模糊,所占内存越小
//RGB_565让ARGB只占两个字节,大小缩小一倍,且变化不明显
BitmapFactory.Options options=new BitmapFactory.Options(); options.inPreferredConfig= Bitmap.Config.RGB_565; Bitmap bitmap1= BitmapFactory.decodeResource(getResources(),R.drawable.yin,options);
//BitmapRegionDecoder类可以实现范围选取图片细节 BitmapRegionDecoder decoder= BitmapRegionDecoder.newInstance(,false); BitmapFactory.Options options2 = new BitmapFactory.Options(); bitmap=decoder.decodeRegion(new Rect(width/2-SCREEN_WIDTH/2+shiftpx, height/2-SCREEN_HEIGHT/2,width/2+SCREEN_WIDTH/2+shiftpx, height/2+SCREEN_HEIGHT/2),options2);
2.通过软引用。优点是让系统在内存不足时可以直接回收,缺点是回收没有优先级,可能回收的不是用过的而是将要显示的。
public class BitmapCache { static private BitmapCache cache; private ArrayMap<String,MySoftRe> hashRef; //软引用被回收后,回收对象放在这,可以查看哪些被回收了 private ReferenceQueue<Bitmap> queue; private BitmapCache(){ hashRef=new ArrayMap<>(); queue=new ReferenceQueue<>(); } /* 继承SoftReference,使得每一个实例都具有可识别的标识 */ private class MySoftRe extends SoftReference<Bitmap>{ private String key=""; public MySoftRe(Bitmap referent, ReferenceQueue<? super Bitmap> q,String key) { super(referent, q); this.key=key; } } public static BitmapCache getInstance(){ if (cache==null){ cache=new BitmapCache(); } return cache; } /* 以软引用的方式对一个bitmap对象的实例进行引用并保存该引用 */ public void addCacheBitmap(String key, Bitmap bitmap){ cleanCache(); MySoftRe msf=new MySoftRe(bitmap,queue,key); hashRef.put(key,msf); } public Bitmap getBitmap(String key){ Bitmap bitmap=null; try { if (hashRef.containsKey(key)){ MySoftRe msf=hashRef.get(key); bitmap=msf.get(); } return bitmap; }catch (NullPointerException e){ return null; } } private void cleanCache() { MySoftRe msf=null; while ((msf= (MySoftRe) queue.poll())!=null){ hashRef.remove(msf.key); } } public void clearCache(){ cleanCache(); hashRef.clear(); System.gc(); System.runFinalization(); } }
3.使用LRU Cache。
public class MemoryCache { private static final String TAG="jason"; //LinkedHashMap专门用来构建LRU算法,但是线程不安全 private Map<String,Bitmap> cache= Collections.synchronizedMap( new LinkedHashMap<String, Bitmap>(8,0.75f,true)); private long size=0;//MemoryCache已经分配的大小 private long limit=1000000; public MemoryCache(){ setLimit(Runtime.getRuntime().maxMemory()/4); } private void setLimit(long l) { limit=l; Log.d(TAG,"MemoryCache will use up to"+limit/1024/1024+"MB"); } public Bitmap get(String id){ try { if (!cache.containsKey(id)){ return null; } return cache.get(id); }catch (NullPointerException e){ return null; } } public void put(String id,Bitmap bitmap){ try { if (cache.containsKey(id)){ size-=getSizeInBytes(cache.get(id)); } cache.put(id,bitmap); size+=getSizeInBytes(bitmap); checkSize(); }catch (Throwable th){ th.printStackTrace(); } } private void checkSize() { Log.i(TAG,"cache size="+size+"length="+cache.size()); if (size>limit){ Iterator<Map.Entry<String,Bitmap>> iterator=cache.entrySet().iterator(); while (iterator.hasNext()){ Map.Entry<String,Bitmap> entry=iterator.next(); size-=getSizeInBytes(entry.getValue()); iterator.remove(); if (size<=limit){ break; } } Log.d(TAG,"Clean cache,new size="+cache.size()); } } private long getSizeInBytes(Bitmap bitmap) { if (bitmap==null) { return 0; } return bitmap.getRowBytes()*bitmap.getHeight(); } public void clear(){ cache.clear(); } }