2012-04-15 56 views
2

我有两个麻烦与下面的代码。它只是使用相机android的意图拍摄照片“onclick”,并在ImageView上显示图像。用安卓相机拍摄图片(意图)内存不足错误

  1. 在没有离开活动的两三张照片后,经常在我旋转显示屏时出现outOfMemory错误。
  2. 当我拍摄照片第一次,它刷新的ImageView但是当我做第二次,第三次......它不会刷新照片,直到我旋转屏幕
  3. 我想保存在内部存储图片而不是外在的,但我不明白如何去做,因为我尝试了几个教程,它塞住了相机!

    公共类HandScryActivity延伸活动{

    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()); 
    } 
    
    } 
    

回答

3

您有内存泄漏。旋转屏幕导致内存耗尽的原因是屏幕旋转会自动破坏活动并重建它。您可以通过重写onPause和onStart方法并在其中放置调试语句来证明这一点,然后旋转屏幕并看到它们被调用。您需要了解android Activity Lifecycle。

您有内存泄漏,因为您在内存中保留对这些图像的引用。你需要跟踪内存使用情况。当你倾斜屏幕时,旧的活动在内存中继续存在,并创建一个新的活动。为了让垃圾收集器收集不必要的对象,您必须确保代码中没有引用留给他们。有工具来画出你应用程序的内存使用情况,以便您可以找出内存泄漏是:

按照指示在这个页面有MAT告诉你在哪里内存泄漏是:

Memory Analyzer Tool in android?

+0

我试着用debug和android在创建新的onConfigurationChanges之前销毁活动。因此它应该销毁我所有的实例,不是吗? – 2012-04-15 16:49:46

+1

你误解了java如何用垃圾回收进行内存管理。简而言之,您需要了解“可达”内存与“无法访问”内存之间的区别。你需要记住对象生命周期。你以高速度制作物体,而不是从记忆中释放它们。这将解释它:http://java.sun.com/docs/books/performance/1st_edition/html/JPAppGC.fm.html – 2012-04-15 17:11:54

+0

感谢您的回复,我读了一切,但我仍然没有清晰的想法。你的意思是我创建MtgMatch的实例比垃圾收集器可以清理更快吗?因为一旦销毁方法被调用,它们将不可达,但是GC不一定很快就要拿起它们呢? – 2012-04-15 17:38:42

0

要修复您遇到的高内存使用情况,可能值得您采取相机返回的文件,将其加载到位图以及使用位图工厂选项,设置选项以使用样本大小。 (此按比例缩小的图像,但最有可能你并不需要一个640x480的屏幕上显示的图像2560x1900)看看这个教程:之前对图像视野解码位图图像集http://tutorials-android.blogspot.co.il/2011/11/outofmemory-exception-when-decoding.html

+0

这是旧的,但该链接是有用的,但发出了错误的数据。如果您阅读API的文档,它会说它将其移动到最接近的较低的2的幂,所以它被用作4,而不是1/5或20%大小,图像尺寸减小4倍或1/4尺寸(宽度*高度)。 – SWoo 2014-09-17 17:16:00

0

试试这个,

这你从onActivityResult获得。

BitmapFactory.Options options = new BitmapFactory.Options(); 
options.inSampleSize = 8; 
Bitmap preview_bitmap = BitmapFactory.decodeStream(is, null, options); 

解码后设置在图像视图。