Take picture with android camera (intent) out of memory error
下面的代码有两个问题。它只是使用相机 android 的意图拍摄照片”onclick”,并在 ImageView 上显示图像。
在没有离开活动的情况下拍摄两三张图片后,当我旋转显示器时,它经常会因内存不足错误而崩溃。
当我第一次拍照时,它会刷新图像视图但是当我第二次或第三次拍照时……它不会刷新图片,直到我旋转屏幕
我想将图片保存在内部存储器而不是外部存储器上,但我不明白该怎么做,因为我尝试了几个教程,但它卡住了相机!
公共类 HandScryActivity 扩展 Activity {
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
|
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()); }
} |
你有内存泄漏。旋转屏幕导致内存耗尽的原因是屏幕旋转会自动破坏 Activity 并重建它。您可以通过覆盖 onPause 和 onStart 方法并在其中放置调试语句来证明这一点,然后旋转屏幕,您会看到它们被调用。你需要了解android Activity Lifecycle。
您有内存泄漏,因为您将这些图像的引用保存在内存中。您需要跟踪内存使用情况。当您倾斜屏幕时,旧的活动会留在内存中,并会创建一个新活动。为了让垃圾收集器收集不必要的对象,您必须确保代码中没有对它们的引用。有一些工具可以绘制应用程序的内存使用情况,以便您找出内存泄漏的位置:
按照此页面中的说明让 MAT 告诉您内存泄漏的位置:
android 中的内存分析工具?
- 在创建新的 onConfigurationChanges 之前,我尝试使用调试和 android 破坏活动。因此它应该销毁我所有的实例,不是吗?
-
您误解了 java 如何通过垃圾收集进行内存管理。简而言之,您需要了解”Reachable”内存和”Unreachable”内存之间的区别。你需要记住对象生命周期。您正在以很高的速度制作对象,而您并没有从内存中释放它们。这将解释它:java.sun.com/docs/books/performance/1st_edition/html/…
-
感谢您的回复,我阅读了所有内容,但我仍然没有明确的想法。你的意思是我创建 MtgMatch 实例的速度比垃圾收集器清理的速度快吗?因为一旦调用了destroy方法,它们就将无法访问,但GC不一定很快就会捡起它们?
-
当您调用新意图时,您传递的是对 myMatch 的引用,您需要将该部分取出,以便新活动无法访问旧活动的组件。垃圾收集器想要销毁它们,但它不能,因为你告诉它保留旧的活动以备不时之需。它正在耗尽智能手机上非常有限的内存。取出 //’intent.putExtra//’ 行,垃圾收集器将清理旧的活动。
-
但是我怎样才能将目的地传递给保存图片的相机意图呢?我想如果不是传递 myMatch.getUri,而是传递给它一个简单的 URI,情况会是一样的。为什么拍照后意图并没有消失,并且它的参考标记为收集?基本上..我怎样才能调整我的代码?
-
最后我开始使用堆监视器,我看到当触发图片的活动时,CPU 的使用率突然上升到 99.35%!我旋转屏幕多少次都没关系,它只是在 99.2% 到 99.6% 之间。我想如果 GC 稍微慢一点,它就会崩溃。所以我想这不是内存泄漏,只是软件内存不足。装有图像的 ImageView 占用大约 50% 的内存。我怎样才能减小那个尺寸?
试试这个,
在您从 onActivityResult.
获得的图像视图解码位图上设置图像之前
1 2 3
|
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 8;
Bitmap preview_bitmap = BitmapFactory.decodeStream(is, null, options);
|
在图像视图上设置解码后。
要解决您遇到的高内存使用率问题,您可能值得采取相机返回的文件,将其加载到位图,并使用位图工厂选项,将选项设置为使用示例尺寸。 (这会缩小图像,但很可能您不需要在 640×480 屏幕上显示 2560×1900 图像)查看本教程:http://tutorials-android.blogspot.co.il/2011/11/outofmemory-exception -when-decoding.html
-
这是旧的,但该链接很有用,但给出了错误的数据。缩小示例中的参数是 5,如果您阅读 API 的文档,它会说它会将其移动到最接近的 2 的较低幂,因此它被用作 4,而不是 1/5 或 20% 大小,图像小 4 倍或尺寸为 1/4 或尺寸为 1/16(宽 * 高)。
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/269007.html