用Glide加载图片到Recyclerview中有时候只显示占位图的问题

转载请标注:http://blog.csdn.net/friendlychen/article/details/76436806

1、IllegalArgumentException: You cannot start a load for a destroyed activity

这是使用Glide加载图片经常遇到的问题,这个问题在我的《Android解决bug的思路:追本溯源》http://blog.csdn.net/friendlychen/article/details/73299095一文中做了深入分析,当时的分析是找到相应错误提示的源码:

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
    private static void assertNotDestroyed(Activity activity) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && activity.isDestroyed()) {
            throw new IllegalArgumentException("You cannot start a load for a destroyed activity");
        }
    }

这里就是产生报错地方的源码,这里是抛出IllegalArgumentException异常,看源码可知抛出异常的条件有两个, 一个条件是Android版本号大于J,另一个条件activity.isDestroyed()都为真时,才抛出这个异常。现在Android版本号基本都是大约J了,而当我们activity销毁后,Glide还在工作,这时就抛出了这个异常了。也就是说当Activity会销毁了,则抛出了异常,为什么会这样呢?因为我们的Glide是有生命周期的,Glide.with()中传入的context参数就是代表了Glide生命周期,比如传入Activity的Context则当Activity销毁时,Glide应该停止加载数据,毕竟这时即使Glide加载了数据也没地方显示呀,这不是浪费流量吗。因此当Activity结束时,Glide也要停止加载数据。
最后得出的解决方法是尽量使用全局的生命周期,也就是Glide.with(context.getApplicaiontContext()).into(imageView);

2、用Glide加载图片显示在Recyclerview中结果有时候只显示占位图

这个跟业务场景有关,我们项目中加载图片比较多,在一个A Activity中用Glide加载图片在Recyclerview正常显示了图片,点击某个item后进去B Activity,B中继续用Glide加载图片,结果返回到A Activity,上下滑动Recyclerview时结果全部都是占位图。
花了大量的时间,发现我们在B Activity中的onDestroy方法中加入了Glide.with(context.getApplicationContext()).pauseRequests();
这里的with()方法中传入的是全局Context,则当关闭Glide时,则相当于关闭了这个应用的Glide加载图片,于是A Activity中的Glide加载图片也关了。当Recyclerview中滑动时,本来应用是显示Glide缓存中的图片,结果关闭了Glide加载数据,就连缓存的图片都不能加载了,图片区域就显示了占位图。
这里可以在需要加载图片的地方及时加上Glide.with(context.getApplicationContext()).resumeRequests()
我们项目是在Recyclerview的滑动监听中判断是否滑动来决定是否启动Glide加载:

 mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);

                switch (newState) {
                    case 0:
                        startGlide(true);
                        break;
                    case 1:
                        startGlide(true);
                        break;
                    case 2:
                        startGlide(false);
                        break;
                }
            }

            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                super.onScrolled(recyclerView, dx, dy);

            }
        });

我们在Recyclerview中的滑动事件中进行监听,当暂停和拖拽滑动时开启Glide加载图片,当滑动后自然沉降状态时停止Glide,其中startGlide()中的代码是:

    private boolean mAlreadyStart = true;//是否已经开启Glide加载图片
    private void startGlide(boolean start) {
        if (mAlreadyStart) {
            if (start) {
                return;
            }
            mAlreadyStart = false;
                   Glide.with(Context.getApplicationContext()).pauseRequests();
        } else {
            if (!start) {
                return;
            }
            mAlreadyStart = true;
            Glide.with(Context.getApplicationContext()).resumeRequests();
        }
    }

这里就解决了我项目中的问题,还可以实现在滑动时加载图片不滑动就不加载图片,也可以很好的避免不必要的加载。
有什么问题也可以留言提问哈。欢迎各位看官留言提出意见,谢啦。

你可能感兴趣的:(Android)