我的应用程序正在使用存储在SD卡上或直接在手机上存储的照片。
我有2个似乎遇到某种问题的活动(查看和编辑记录的附加信息)。单个记录通过存储提供相关照片位置的URI来引用照片。
当我点击我的View活动时,我传递了URI,然后使用URI设置了ImageView。在View Activity中,我有一个菜单选项,允许您访问Edit Activity。单击“编辑”时,我再次传递照片的URI,并使用URI设置ImageView。这两项活动都表现得很好。
但是,当我单击“后退”按钮从“编辑”移动到“视图”时,应用程序崩溃。最初崩溃是OutOfMemory Exception。我通过在两个活动中的onPause函数中添加对((BitmapDrawable)mImageView.getDrawable()).getBitmap().recycle()
的调用来克服此异常。
使用回收代码,执行从Edit返回View,然后在某处崩溃。我已经逐步完成了生命周期功能,并且执行成功完成,除了onCreate。执行永远不会再次进入创造状态。
我知道它与ImageView有关,因为当我在View活动中从布局中删除ImageView时,崩溃不再发生。
以下是崩溃发生时的初始堆栈跟踪:
Thread [<3> main] (Suspended (exception RuntimeException))
ViewRoot.draw(boolean) line: 1356
ViewRoot.performTraversals() line: 1097
ViewRoot.handleMessage(Message) line: 1613
ViewRoot(Handler).dispatchMessage(Message) line: 99
Looper.loop() line: 123
ActivityThread.main(String[]) line: 4203
Method.invokeNative(Object, Object[], Class, Class[], Class, int, boolean) line: not available [native method]
Method.invoke(Object, Object...) line: 521
ZygoteInit$MethodAndArgsCaller.run() line: 791
ZygoteInit.main(String[]) line: 549
NativeStart.main(String[]) line: not available [native method]
在这个堆栈跟踪之后,如果我继续在Eclipse中推送“Step Over”,堆栈跟踪就会像这样结束:
Thread [<3> main] (Suspended)
ThreadGroup.uncaughtException(Thread, Throwable) line: 884
NativeStart.main(String[]) line: not available [native method]
答案 0 :(得分:1)
如果您要从“活动优先”更改为“第二个”,则“活动优先”将暂停。然后onPause方法将回收Bitmap 如果从Back Second切换回First Activity First已经存在,则无需再次调用onCreateMethod。相反,只有onResume方法被调用,告诉活动它再次出现在屏幕上。此时,imageview会尝试将图像绘制到屏幕上,但由于图像被回收,因此应用程序崩溃。
如果你真的需要回收位图,你必须在调用你活动的超级onResume方法之前在onResume方法中重置它。
答案 1 :(得分:1)
我找到了解决这个问题的方法。
我能够找到这个其他解决方案部分归功于Janusz的回答。在我的View和Edit类中,我添加了一个私有的Bitmap类变量(mBitmap)。在onCreate中,我检索并存储我的图像位置的URI。在onPause中,我回收了位图。在onResume中,我更新了这个函数以使用新的类变量mBitmap(我确信有更好的方法来设置Bitmap,所以每个人都可以随意指出它)。此外,使用这个新代码,我最初在Edit类中遇到了崩溃。如果你去编辑,然后点击“主页”按钮,应用程序将崩溃。我发现该问题的解决方案是在Edit.onPause中将图像视图的Bitmap设置为null。问题是imageView保留了一个指向Bitmap的指针,即使我已经回收了位图。见Android "Trying to use recycled bitmap" error?:
protected void onResume()
{
mBitmap = null;
try
{
mBitmap = Bitmap.createBitmap(Media.getBitmap(this.getContentResolver(), mPicUri));
}
catch(Exception e)
{}
mImageView.setImageBitmap(mBitmap);
mImageView.setAdjustViewBounds(true);
mImageView.setMaxHeight(100); //purposely showing image as 100x100 picture
mImageView.setMaxWidth(100);
mImageView.invalidate();
super.onResume();
}
protected void onCreate()
{
mPicUri = //the picuture location URI
}
protected void onPause()
{
mBitmap.recycle();
mImageView.setImageBitmap(null); //in my Edit class
}
答案 2 :(得分:0)
从流中显示位图图像并在ImageView中显示它而不会导致任何崩溃的最佳方法是:
public void getImage(final ImageView imageView , final String picUrl) {
class GetImage extends AsyncTask<String,Void,Bitmap> {
@Override
protected void onPreExecute() {
super.onPreExecute();
Log.i("Download","Profile Picture Downloaded");
}
@Override
protected void onPostExecute(Bitmap b) {
super.onPostExecute(b);
imageView.setImageBitmap(b);
}
@Override
protected Bitmap doInBackground(String... params) {
URL url = null;
Bitmap image = null;
Bitmap finalImage=null;
try {
url = new URL(picUrl);
image = BitmapFactory.decodeStream(url.openConnection().getInputStream());
finalImage= resize(image,120,120);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return finalImage;
}
}
GetImage gi = new GetImage();
gi.execute();
}
这些方法有2个参数,ImageView将包含我们的Image和Image URL,你只需要用参数调用方法,就会显示图像。