One way to get the phone memory:
ActivityManager activityManager = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
int memClass = activityManager.getMemoryClass();
int largeMemClass = activityManager.getLargeMemoryClass();
Get the memory status of the phone when it is running:
float totalMemory = Runtime.getRuntime().totalMemory()/(1024*1024);
float freeMemory = Runtime.getRuntime().freeMemory()/(1024*1024);
float maxmemory = Runtime.getRuntime (). maxMemory / (1024 * 1024);
adb shell to enter the bottom layer of the device
ps to view all processes
dumpsys meminfo + package name to view the detailed stack information of a specific process
An app is usually a process corresponding to a virtual machine
GC only triggers garbage collection when the remaining space in the Heap is insufficient
When GC is triggered, all threads will be suspended
APP memory limit mechanism
The maximum memory limit allocated per app, which varies by device
Big memory eaters: pictures
Data structure optimization:
StringBuilder for frequent string concatenation
ArrayMap SparseArray替换HashMap
Memory thrashing (variables are created frequently and quickly discarded) causes frequent GCs
object reuse
Reuse the resources that come with the system
ConvertView reuse of ListView/GridView
Avoid performing object creation in the onDraw method
Memory leak : Due to code flaws, although this piece of memory has stopped being used, it is still referenced by other things. Yes, the GC cannot reclaim it.
Memory leaks will lead to less and less remaining available heap and frequent GC
Use Application Context instead of 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; } }