首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >具有水平RecycleView get锁的RecycleView

具有水平RecycleView get锁的RecycleView
EN

Stack Overflow用户
提问于 2018-04-10 10:22:07
回答 1查看 124关注 0票数 2

我有一个大约5-6行的ListView,每一行都是一个显示水平片段的RecycleView。卡片(比如Netflix,家庭影院应用)

考虑因素:

  • 每个RecycleView大约有30-50个项目.
  • 每个ViewHolder都有一个“大”图片作为背景(大约300x260dp取决于设备屏幕大小,宽度约为设备屏幕的90% )
  • 图像是通过使用幻灯片加载的(代码如下)

我在SparseArray适配器中为RecycleViews创建了一个缓存( ListView ),以保持每个RecycleView的状态,否则每次离开屏幕时都会重新启动到0。

通过这样做,只要将每个RecycleView滚动到最后,它们中的一些就会被冻结。

尝试了几种解决办法:

  • 回顾了MAT,并重构了一些代码,以避免由于静态上下文而导致的泄漏。
  • 由于这些图像,MAT显然显示了大量的内存。
  • 缩小图像的大小
  • 隐藏图像
  • 创建ViewHolders缓存(没有工作)
  • 一旦幻灯片下载,为图像创建一个内存缓存
  • 使ViewHolders setIsRecyclable变为false

但是,所有这些选项都没有起作用,确保应用程序不被冻结的唯一方法是避免ListView缓存(如果将视图移出屏幕,则失去您访问的最后一个位置)。

滑动代码(我在这里尝试了几种选择:避免位图、避免内存缓存、向所有人更新磁盘策略)

代码语言:javascript
运行
复制
Glide.with(context).load(url)
                .asBitmap()
                .skipMemoryCache(true)
                .thumbnail(0.5f)
                .centerCrop()
                .error(placeHolderId)
                .diskCacheStrategy(DiskCacheStrategy.RESULT)
                //.priority(Priority.NORMAL)
                .dontAnimate()
                .into(new SimpleTarget<Bitmap>() {
                    @Override
                    public void onResourceReady(Bitmap bitmap, GlideAnimation anim) {
                        if (bitmap != null) {
                            imgView.setImageBitmap(bitmap);
                            //cache.put(url, bitmap);
                        } else {
                            imgView.setBackground(null);
                        }
                    }
                });

有什么建议吗?也许还有另一种选择来保持视图的状态而不需要缓存?

ListView适配器代码:

代码语言:javascript
运行
复制
@Override
public View getView(int position, View convertView, ViewGroup parent) {
            case TYPE_VENUE_FILTER: {
            View v;
            // Create a new view into the list.
            LayoutInflater inflater = (LayoutInflater) context
                        .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            if (inflater != null) {
                v = inflater.inflate(R.layout.fragment_venue_filter, parent, false);
            }

            // We need to get the exact filter to be displayed
            int index = position - FIRST_VENUE_FILTER_ROW;
            if (index < this.filters.size()) {
                VenueFilter filter = this.filters.get(index);

                // Recalculate the distance order
                filter.sortVenuesForLocation(this.lastLocation);

                // Set data into the view.
                VenueFilterFragment.loadFragment(this.context, v, filter, this.fm);
            }

            return v;
        }
}

更新11/04

我终于明白了。

  • 按建议在适配器上重用converView
  • 在ScrollListener中包含一个RecycleView,并将最后一个滚动位置存储在bean中,以便在重新访问时恢复它。

此代码位于适配器中,用于膨胀特定行(getView)。

代码语言:javascript
运行
复制
    // We should reset or recover the scroll state
    LinearLayoutManager llm = (LinearLayoutManager) filterContent.getLayoutManager();
    if (filter.offset > 0) {
        if (llm != null) llm.scrollToPosition(filter.offset + 1);
    } else {
        if (llm != null) llm.scrollToPosition(0);
    }

    // We need to clear every time. Because we are reusing the view
    recycleView.clearOnScrollListeners();

    // We need to create a new specific scroll listener
    recycleView.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);

            // Keeping the offset for a future load
            LinearLayoutManager llm = (LinearLayoutManager) recyclerView.getLayoutManager();
            if (llm != null) filter.offset = llm.findFirstVisibleItemPosition();
        }
    });
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-04-10 10:43:26

这是一个非常广泛和复杂的问题。您的布局很复杂,因此需要付出一定的努力才能使其高效。你可以做些什么来提高你的表现:

  • 所有RecyclerView应该在可能的情况下使用视图持有人。如果需要,请定义多个视图类型。父RecyclerView可能只有一种视图类型,即带有子RecyclerView的项。子RecyclerView也可以通过拥有一个RecycledViewPool来共享视图持有者。更多信息在这里:https://developer.android.com/reference/android/support/v7/widget/RecyclerView.RecycledViewPool.html
  • 确保所有布局尽可能平坦。您拥有的视图类型越多,这一点就越重要。
  • 滑动是图像加载的一个很好的选择。确保在可能的情况下使用缓存。下载后缓存图像,以减少对网络的影响。下载图像时使用占位符或进度条。当视图被重用以避免闪烁时,重置每个ImageView状态。
  • 取消不再需要加载的项的图像加载。这也会帮助你减少网络活动。
  • 您也可以恢复滚动位置,这里不应该有任何问题。这是一个单独的主题,您可以参考这个线程获得更多详细信息:How to save RecyclerView's scroll position using RecyclerView.State?
  • 盯着垫子,是的。重要的是要确保您没有使用太多的资源,这在这种情况下是非常容易的。

我希望这能帮上忙。祝好运!

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49751175

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档