Java 使用android摄像头拍照(意图)内存不足错误
下面的代码有两个问题。它只需使用android摄像头的意图拍摄“onclick”,并在ImageView上显示图像Java 使用android摄像头拍照(意图)内存不足错误,java,android,android-layout,mobile,android-intent,Java,Android,Android Layout,Mobile,Android Intent,下面的代码有两个问题。它只需使用android摄像头的意图拍摄“onclick”,并在ImageView上显示图像 在两到三张图片没有离开活动后,当我旋转显示器时,它会因outOfMemory错误而崩溃 当我第一次拍照时,它会刷新图像视图,但当我第二次或第三次拍照时,它不会刷新图像,直到我旋转屏幕 我想将图片保存在内部存储器而不是外部存储器上,但我不知道如何保存,因为我尝试了几个教程,但它会使相机出现问题 公共类活动扩展了活动{ private static int TAKE_PICTURE =
private static int TAKE_PICTURE = 1;
private MtgMatch myMatch;
private File handFile;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.handscry);
// Disable screen saver
getWindow().addFlags(LayoutParams.FLAG_KEEP_SCREEN_ON);
// Load match
myMatch = MtgMatch.getSingletonMtgMatch();
handFile = new File(Environment.getExternalStorageDirectory(), "test.jpg");
if (myMatch.getHandUri() != null) { loadPicture(); }
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
loadPicture();
}
// Handles onGame clicked buttons
public void btnHandClick(View v) {
Button clickedButton = (Button) v;
// according to clicked button
switch (clickedButton.getId()) {
case R.id.btnBackToGame:
this.finish();
break;
case R.id.btnTakePicture:
myMatch.setHandUri(Uri.fromFile(handFile));
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, myMatch.getHandUri());
startActivityForResult(intent, TAKE_PICTURE);
break;
default:
break;
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == TAKE_PICTURE) {
// Display image
if (resultCode == RESULT_OK) {
loadPicture();
} else if (resultCode == RESULT_CANCELED) {
// User cancelled the image capture
} else {
// Image capture failed, advise user
}
}
}
// Put the photo inside frame
private void loadPicture() {
ImageView img = (ImageView) findViewById(R.id.imgHand);
img.setImageURI(myMatch.getHandUri());
}
}
内存泄漏。旋转屏幕导致内存耗尽的原因是屏幕旋转会自动销毁并重建活动。您可以通过覆盖onPause和onStart方法并在其中放置调试语句来证明这一点,然后旋转屏幕,看到它们被调用。您需要了解d android活动生命周期 内存泄漏是因为您在内存中保留了对这些图像的引用。您需要跟踪内存使用情况。当您倾斜屏幕时,旧的活动会粘在内存中,并创建一个新的活动。为了让垃圾收集器收集不必要的对象,您必须确保没有引用代码中留给他们的。有一些工具可以图表显示应用程序的内存使用情况,以便您可以找出内存泄漏的位置: 按照本页中的说明让MAT告诉您内存泄漏的位置:
若要解决当前内存使用率高的问题,您可能需要获取相机返回的文件,将其加载到位图,然后使用位图工厂选项,将选项设置为使用样本大小。(这会缩小图像的比例,但很可能不需要640x480屏幕上显示的2560x1900图像)查看本教程:试试这个 在图像视图上设置图像之前,请解码从onActivityResult获得的位图
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap preview_bitmap = BitmapFactory.decodeStream(is, null, options);
解码后在图像视图上设置。我尝试了调试,android在配置更改上创建新实例之前会销毁活动。因此,它应该会销毁我的所有实例,不是吗?你误解了java如何通过垃圾收集进行内存管理。简单地说,你需要理解内存与配置更改之间的区别“可访问”和“不可访问”的内存。你需要记住对象的生命周期。你正在以很高的速度创建对象,而不是将它们从内存中释放出来。这可以解释:谢谢你的回答,我读了所有内容,但仍然没有清晰的想法。你是说我创建MtgMatch实例的速度比垃圾收集器清理的速度快吗?因为它们正在运行若要在调用destroy方法后立即无法访问,但GC不需要很快获取它们?当您调用新的intent时,您正在传递对myMatch的引用,您需要删除该部分,以便新活动无法访问旧活动的组件。垃圾收集器希望销毁它们,但它可以“t,因为你告诉它保留旧的活动,以备需要。这会耗尽智能手机上非常有限的内存。去掉'intent.putExtra'行,垃圾收集器会清理旧的活动。但是我如何将目的地传递给camera intent,在那里保存图片呢?我想如果,intead传递myMatch.getUri,我传递给它一个简单的URI,情况会是一样的。为什么在拍摄完照片后,意图并没有消失,它的引用被标记为要收集?基本上。我如何调整我的代码?这是旧的,但链接很有用,但给出了错误的数据。如果你阅读API的文档,它说它将其移动到最接近的2次幂,因此它被用作4,而不是1/5或20%的大小,图像的大小是4倍或1/4或1/16(宽度*高度)。