Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/351.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用android摄像头拍照(意图)内存不足错误_Java_Android_Android Layout_Mobile_Android Intent - Fatal编程技术网

Java 使用android摄像头拍照(意图)内存不足错误

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 =

下面的代码有两个问题。它只需使用android摄像头的意图拍摄“onclick”,并在ImageView上显示图像

  • 在两到三张图片没有离开活动后,当我旋转显示器时,它会因outOfMemory错误而崩溃
  • 当我第一次拍照时,它会刷新图像视图,但当我第二次或第三次拍照时,它不会刷新图像,直到我旋转屏幕
  • 我想将图片保存在内部存储器而不是外部存储器上,但我不知道如何保存,因为我尝试了几个教程,但它会使相机出现问题

    公共类活动扩展了活动{

    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(宽度*高度)。