Android中的ImageView导致应用崩溃

时间:2010-07-06 04:56:00

标签: android

我的应用程序正在使用存储在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]  

3 个答案:

答案 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,你只需要用参数调用方法,就会显示图像。