如何在ViewPager片段中处理图像回收?

时间:2015-10-20 06:41:42

标签: android android-fragments bitmap android-viewpager picasso

我有一个使用ViewPager的图像查看器。每个片段上都有一个大图像。这样可以正常工作一段时间,但是在足够的图像之后,应用程序内存不足。

要解决此问题,我尝试回收位图,但这会导致另一个问题:如果我向后滑动,则回收的位图会导致RuntimeException

java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@268f7cd3

片段代码如下所示:

Bitmap m_image = null;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
    View root = inflater.inflate(R.layout.fragment_image, container, false);

    final ImageView img = (ImageView)root.findViewById(R.id.ivImage);
    img.setVisibility(View.GONE);

    Picasso.with(getContext())
           .load(getArguments().getString("url"))
           .into(new Target()
           {
               @Override
               public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from)
               {
                   m_image = bitmap;
                   img.setImageBitmap(m_image);
                   img.setVisibility(View.VISIBLE);
               }

               @Override
               public void onBitmapFailed(Drawable errorDrawable)
               {
               }

               @Override
               public void onPrepareLoad(Drawable placeHolderDrawable)
               {
               }
           });

    return root;
}

@Override
public void onDestroyView()
{
    if(m_image != null)
    {
        m_image.recycle();
        m_image = null;
    }
    super.onDestroyView();
}

持有ViewPager的Activity看起来像这样:

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_image);

    final DataHandler dataHandler = getApp().getDataHandler();

    PagerAdapter adapter = new FragmentStatePagerAdapter(getSupportFragmentManager())
    {
        @Override
        public Fragment getItem(int position)
        {
            Entry e = dataHandler.get(position);
            Fragment f = new ImageFragment();
            Bundle args = new Bundle();
            args.putString("url", e.getURL());
            f.setArguments(args);
            return f;
        }

        @Override
        public int getCount()
        {
            return dataHandler.getCount();
        }
    });

    ViewPager pager = (ViewPager)findViewById(R.id.vpImages);
    pager.setAdapter(adapter);
}

1 个答案:

答案 0 :(得分:1)

使用Picasso时无需处理内存。如果你的片段是GCed,ImageView将负责回收与之相关的位图。

虽然提出了一些建议:

  • 如果您在项目中添加OkHttp作为依赖项,Picasso将自动添加网络缓存。缓存的图像加载速度更快,数据消耗更少。

  • 要仅使用您需要的内存,我会调整图像大小以匹配ImageView大小。为此,请使用: Picasso.with(context).fit().centerCrop().into(imageView);