获得手机内存方式一:
ActivityManager activityManager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
int memClass = activityManager.getMemoryClass();
int largeMemClass = activityManager.getLargeMemoryClass();
获得手机运行时内存情况:
float totalMemory = Runtime.getRuntime().totalMemory()/(1024*1024);
float freeMemory = Runtime.getRuntime().freeMemory()/(1024*1024);
float maxmemory = Runtime.getRuntime().maxMemory/(1024*1024);
adb shell 进入设备底层
ps 查看所有进程
dumpsys meminfo +包名 查看具体进程的详细堆栈信息
一个app通常就是一个进程对应一个虚拟机
GC只在Heap剩余空间不足时才触发垃圾回收
GC触发时,所有线程都是会被暂停的
APP内存限制机制
每个app分配的最大内存限制,随不同设备而不同
吃内存的大户:图片
数据结构优化:
频繁的字符串拼接用StringBuilder
ArrayMap SparseArray替换HashMap
内存抖动(频繁创建变量,并很快弃之不用)会引起频繁GC
对象复用
复用系统自带的资源
ListView/GridView的ConvertView复用
避免在onDraw方法里面执行对象的创建
内存泄漏:由于代码瑕疵,导致这块内存虽然停止不用了,但依然被其他东西引用这,是的GC没法对他回收,
内存泄漏会导致剩余可用Heap越来越少,频繁GC
用Application Context而不是Activity Context
注意Cursor对象是否及时关闭
OOM问题优化方法
注意临时BItmap对象的及时回收
避免Bitmap的浪费
加载Bitmap:缩放比例,解码格式,局部加载
示例如下:
package com.example.admin.myapplication.oom; import android.content.Intent; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.BitmapRegionDecoder; import android.graphics.Rect; import android.net.Uri; import android.os.Bundle; import android.provider.MediaStore; import android.support.v7.app.AppCompatActivity; import android.util.DisplayMetrics; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.ImageView; import com.example.admin.myapplication.R; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; public class OOMActivity extends AppCompatActivity { private ImageView img; private Bitmap bitmap; private File file = null; private int SCREEN_WIDTH, SCREEN_HEIGHT; private int shifpx = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main2); img = (ImageView) findViewById(R.id.img); DisplayMetrics dm = new DisplayMetrics(); dm = this.getResources().getDisplayMetrics(); SCREEN_WIDTH = dm.widthPixels; SCREEN_HEIGHT = dm.heightPixels; Log.e("oomactivity","screen_width:"+SCREEN_WIDTH); Button button = (Button) findViewById(R.id.choosepic); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { getPic(); } }); findViewById(R.id.picpoti).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { changePicOopti(); } }); findViewById(R.id.changergb).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { changeRGB(); } }); findViewById(R.id.partload).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { partLoad(); } }); findViewById(R.id.movepart).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { shifpx++; partLoad(); } }); } private void getPic(){ Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI); startActivityForResult(intent, 1); // String path = "/storage/emulated/0/qingming.jpg"; // bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.qingming); // img.setImageBitmap(bitmap); // Log.e("oomActivity","bitmap.length:"+bitmap.getByteCount()); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { try{ String path = getRealPathFromURI(data.getData()); file = new File(path); if (file == null) return; if (file.length()==0){ file .delete(); return; } Log.e("oomActivity","file;"+file.getName()+" ,length:"+file.length()); FileInputStream fin = new FileInputStream(file); bitmap = BitmapFactory.decodeStream(fin); Log.e("oomActivity","bitmap.lenght:"+bitmap.getByteCount()); Bitmap bitmap1 = BitmapFactory.decodeFile(path); Log.e("oomActivity","bitmap1.lenght:+"+bitmap1.getByteCount()); img.setImageBitmap(bitmap); }catch(Exception e){ e.printStackTrace(); Log.e("oomActivity",e.toString()); } } /** *缩放 */ private void changePicOopti(){ Log.e("oomActivity","---------------------------------------------"); if (file==null){ return; } try{ BitmapFactory.Options options= new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeStream(new FileInputStream(file),null,options); int width_tem = options.outWidth,height_tmp = options.outHeight; int scale = 2; while(true){ if (width_tem/scale<SCREEN_WIDTH){ break; } scale+=2; } scale=4; BitmapFactory.Options options1 = new BitmapFactory.Options(); options1.inSampleSize= scale; Log.e("oomActivity","bitmap.scale:"+scale); FileInputStream fileInputStream = new FileInputStream(file); bitmap = BitmapFactory.decodeStream(fileInputStream,null,options1); Log.e("oomActivity","scale_bitmap.length:"+bitmap.getByteCount()); img.setImageBitmap(bitmap); }catch (Exception e){ e.printStackTrace(); } } /** * 改变RGB */ private void changeRGB(){ Log.e("oomActivity","---------------------------------------------"); if (file != null){ BitmapFactory.Options options = new BitmapFactory.Options(); options.inPreferredConfig =Bitmap.Config.RGB_565; try { FileInputStream fileInputStream = new FileInputStream(file); bitmap = BitmapFactory.decodeStream(fileInputStream,null,options); Log.e("oomActivity","RGB+565_bitmap.length"+ bitmap.getByteCount()); img.setImageBitmap(bitmap); } catch (FileNotFoundException e) { e.printStackTrace(); Log.e("oomActivity",""+e.toString()); } } } /** * 局部显示 */ private void partLoad(){ if (file==null) return; try{ FileInputStream fileInputStream = new FileInputStream(file); BitmapFactory.Options options = new BitmapFactory.Options(); BitmapFactory.decodeStream(fileInputStream,null,options); int widht = options.outWidth; int height = options.outHeight; //设置显示图片的中心区域 fileInputStream = new FileInputStream(file); BitmapRegionDecoder bitmapRegionDecoder = BitmapRegionDecoder.newInstance(fileInputStream,false); BitmapFactory.Options options1 = new BitmapFactory.Options(); bitmap = bitmapRegionDecoder.decodeRegion(new Rect(widht/2-SCREEN_WIDTH/2+shifpx,height/2-SCREEN_HEIGHT/2,widht/2+SCREEN_WIDTH/2+shifpx,height/2+SCREEN_HEIGHT/2),options); img.setImageBitmap(bitmap); }catch(Exception e){ } } public String getRealPathFromURI(Uri contentUri){ String res = null; String proj = (MediaStore.Images.Media.DATA); Cursor cursor = this.getContentResolver().query(contentUri, new String[]{proj},null,null,null); if (cursor.moveToFirst()){ int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); res = cursor.getString((column_index)); } cursor.close(); return res; } }