android - Android App 使用过多内存超过 500MB
问题描述
我在该活动上使用相机套件库,应用程序中的内存使用量过多可能是什么问题?
这是一个使用相机套件库的相机视图活动。captureButton
当用户点击并被调用时会收到相机结果,cameraView.captureImage()
并将结果发送到下一个预览活动。但是当仅打开活动并且尚未捕获图像时,我看到巨大的内存使用量。
我的活动代码:
public class PSLSelfieActivity extends AppCompatActivity {
private CameraKitView cameraView;
private FloatingActionButton captureButton, switchCamera, useGallery;
private String TAG = "ramiz";
private int orientation = 0;//0=pot,1=land
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pslselfie);
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
try {
cameraView = findViewById(R.id.camera);
captureButton = findViewById(R.id.captureButton);
useGallery = findViewById(R.id.useGalleryButton);
OrientationEventListener mOrientationListener = new OrientationEventListener(
getApplicationContext()) {
@Override
public void onOrientationChanged(int orientation) {
PSLSelfieActivity.this.orientation = orientation;
}
};
if (mOrientationListener.canDetectOrientation()) {
mOrientationListener.enable();
}
captureButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
cameraView.captureImage(new CameraKitView.ImageCallback() {
@Override
public void onImage(CameraKitView cameraKitView, byte[] bytes) {
Intent i = new Intent(PSLSelfieActivity.this, PSLSelfiePreview.class);
Bitmap b = loadBitmap(bytes);
Log.d(TAG, "OnCaptureImage: Bitmap Size= w=" + b.getWidth() + " h=" + b.getHeight());
PSLSelfiePreview.inputImage = b;
i.putExtra("orientation", orientation);
i.putExtra("flipImage", true);
startActivity(i);
}
});
}
});
useGallery.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent photoPickerIntent = new Intent(Intent.ACTION_PICK);
photoPickerIntent.setType("image/*");
startActivityForResult(photoPickerIntent, USE_GALLERY_REQUEST);
}
});
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getContext(), "There is some error with opening camera.", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
// Check which request we're responding to
if (requestCode == USE_GALLERY_REQUEST) {
// Make sure the request was successful
if (resultCode == RESULT_OK) {
try {
final Uri imageUri = data.getData();
final InputStream imageStream = getContentResolver().openInputStream(imageUri);
Intent i = new Intent(PSLSelfieActivity.this, PSLSelfiePreview.class);
Bitmap b = loadBitmap(imageUri);
Log.d(TAG, "onActivityResult: Bitmap Size= w=" + b.getWidth() + " h=" + b.getHeight());
PSLSelfiePreview.inputImage = b;
i.putExtra("orientation", 0);
i.putExtra("flipImage", false);
startActivity(i);
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(getContext(), "Cannot Load Image.", Toast.LENGTH_SHORT).show();
} catch (OutOfMemoryError e) {
e.printStackTrace();
Toast.makeText(getContext(), "Cannot Load Image. Image too Large.", Toast.LENGTH_SHORT).show();
}
} else {
}
}
}
@Override
protected void onStart() {
cameraView.onStart();
super.onStart();
}
@Override
protected void onResume() {
cameraView.onResume();
super.onResume();
}
@Override
protected void onPause() {
cameraView.onPause();
super.onPause();
}
@Override
protected void onStop() {
cameraView.onStop();
super.onStop();
}
@Override
protected void onDestroy() {
System.gc();
super.onDestroy();
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
cameraView.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public void onBackPressed() {
super.onBackPressed();
System.gc();
}
public Bitmap loadBitmap(byte[] bytes) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
Bitmap b = BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
options.inSampleSize = calculateInSampleSize(options, 480, 640);
Log.d(TAG, "loadBitmap: inSampleSize=" + options.inSampleSize);
options.inJustDecodeBounds = false;
return BitmapFactory.decodeByteArray(bytes, 0, bytes.length, options);
}
public Bitmap loadBitmap(Uri imageUri) throws IOException {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
final InputStream imageStream;
imageStream = getContentResolver().openInputStream(imageUri);
Bitmap b = BitmapFactory.decodeStream(imageStream, null, options);
options.inSampleSize = calculateInSampleSize(options, 480, 640);
Log.d(TAG, "loadBitmap: inSampleSize=" + options.inSampleSize);
options.inJustDecodeBounds = false;
final InputStream imageStreamNew;
imageStreamNew = getContentResolver().openInputStream(imageUri);
Bitmap outBitmap = BitmapFactory.decodeStream(imageStreamNew, null, options);
if (imageStream != null) {
imageStream.close();
}
if (imageStreamNew != null) {
imageStreamNew.close();
}
return outBitmap;
}
public int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
Log.d(TAG, "calculateInSampleSize: h=" + height + " - w=" + width);
if (width > height) {
int temp = reqHeight;
reqHeight = reqWidth;
reqWidth = temp;
}
Log.d(TAG, "calculateInSampleSize: updated h=" + height + " - w=" + width);
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) >= reqHeight
&& (halfWidth / inSampleSize) >= reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
private Context getContext() {
return this;
}
}
解决方案
推荐阅读
- r - JSTOR 的 XML 大循环中的内存和优化问题
- java - Spring过滤请求
- python - Googletrans API 错误 - 每日限制或阻止 IP?
- audiokit - AudioKit 可以在麦克风分析频率时播放声音吗?
- java - 如何将 Java Swing 应用程序与同一网络上的其他应用程序实例连接?
- python - 我有办法重写代码吗?,我似乎无法正确,我似乎无法正确获取输入
- authentication - 将文件中的自定义 JS 函数添加到 Svelte 应用程序的最佳方法是什么?
- git - 如果文件未更改,提交历史记录会丢失吗?
- r - kableExtra::collapse_rows 不适用于多行的长表头
- python - 如何将 Django asgi 项目部署到 Heroku?