【问题标题】:Glide and recyclerview, too much memoryGlide和recyclerview,内存太大
【发布时间】:2019-03-24 23:20:49
【问题描述】:

我使用 Glide 下载图像(每个约 4Kb)和一个带有网格布局的 recyclerview 来显示它。我将图像 url 存储在 lru 缓存中。在 onBindViewHolder() 中,我获取图像 url 并使用 Glide 显示如下:

 Glide.with(mMainActivity).load(item.getPosterPath()).thumbnail(0.5f).into(holder.posterPath);

问题是,在 300 张图像后,应用程序进入内存不足异常,这是 Android 分析器信息:

这是我的 recyclerview 适配器:

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list_content, parent, false));
}



@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
    Item item = mItems.get(position);
    if (item!= null) {
        holder.itemView.setTag(item);
        Glide.with(mMainActivity).load(item.getPosterPath()).apply(ro).thumbnail(0.5f).into(holder.posterPath);

        holder.itemView.setOnClickListener(mOnClickListener);
    }
}

class ViewHolder extends RecyclerView.ViewHolder {
    private ImageView posterPath;
    private TextView originalName;

    ViewHolder(View view) {
        super(view);
        posterPath = itemView.findViewById(R.id.poster);
    }
}

这是我的结构:

public static LruCache<Integer, Item> mItemMap = new LruCache<>(20);

物品在哪里:

public class Item {
    private String mId;
    private String mOriginalName;
    private String mFirstAirDate;
    private String mLanguage;
    private String mOverview;
    private String mPosterPath;
    private int itemPos;

    Item(String id, String originalName, String firstAirDate, String language, String posterPath, String overview, int itemPos) {
        this.mId = id;
        this.mOriginalName = originalName;
        this.mFirstAirDate = firstAirDate;
        this.mLanguage = language;
        this.mOverview = overview;
        this.mPosterPath = posterPath;
        this.itemPos = itemPos;
    }

    /**
     * Getters.
     */
}

我的 recyclerview 滚动适配器:

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

    visibleItemCount = recyclerView.getChildCount();
    totalItemCount = mGridLayoutManager.getItemCount();
    firstVisibleItem = mGridLayoutManager.findFirstVisibleItemPosition();

    if (loading) {
        if (totalItemCount > previousTotal) {
            loading = false;
            previousTotal = totalItemCount;
        }
    }
    if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + visibleThreshold)) {
        current_page++;
        onLoadMore(current_page);

        loading = true;
    }
}

这就是我从互联网获取新数据的方式:

   public void newItem() {
    currentPage++;
    String URL = "myurl";
    RestClient.get(URL, null, mHandler);
}

mHandler 在哪里:

mHandler = new JsonHttpResponseHandler() {
        @Override
        public void onSuccess(int statusCode, Header[] headers, JSONObject response) {

            try {
                results = (JSONArray) response.get("results");
                for (int i = 0; i < results.length(); i++) {
                    obj = results.getJSONObject(i);

                    id = obj.get("id").toString();
                    posterPath = obj.get("poster_path").toString();

                    if (!posterPath.equals("null")) {
                        mItem.add(ItemList.createItem(id, null, null, null, POSTER_BASE_URL+posterPath, null, itemPos));
                        itemPos++;
                    }
                }
                notifySubscriber();
            } catch (JSONException e) {
                Log.d("JSON", "Error in parsing json.");
            }
        }
    };

这是我的 RestClient:

private static AsyncHttpClient client = new AsyncHttpClient();

public static void get(String url, RequestParams params, AsyncHttpResponseHandler responseHandler) {
    client.get(getAbsoluteUrl(url), params, responseHandler);

}

所有 byte[] 分配是在何时何地进行的?

【问题讨论】:

  • 显示缓存的使用情况。
  • @JeffreyBlattman 我该怎么办?
  • 你需要展示更多的“东西”,我的意思是,一个屏幕截图和一条通用的线不会有太大的作用。一般来说,除非你需要,否则尽量避免使用 Activity/Fragment 作为上下文,除非你确定上下文的用途(以及谁将保留引用)。我会要求你尽最大努力用更多信息来扩展你的问题,因为它是对每个人的猜测,包括你。 :)
  • 好的,谢谢!我已经更新了一些代码。

标签: android android-recyclerview out-of-memory android-glide


【解决方案1】:

我真的不知道会发生什么,但我会留意两件事:

  1. 我会查看http://bumptech.github.io/glide/int/recyclerview.html,看看您是否遵循他们的正确做法。
  2. 我会使用Glide.with(holder.getContext()).load(…。

您正在传递或使用mMainActivity,这就是我假设您的Activity 的引用。绝对没有必要在那里引用整个 Activity。你有视图并且你在视图的上下文中加载图像(你绑定的 ViewHolder),所以从那里删除泄漏。

【讨论】:

  • 好的,谢谢,我已经用 Glide.with(holder.itemView) 进行了更新,但没有任何改变。
  • 但是,我确信问题不在于图像,因为 android profiler 显示图像的 ram 使用率很低。问题是我不明白所有 byte[] 分配的地点和时间(你可以在最新的屏幕中看到)
  • 哈哈哈哈我的意思是你在回收站视图中加载的几张图片;)
  • 我解决了内存泄漏添加 holder.posterPath.setImageDrawable(null);在 onViewRecycled 事件中。
  • 很高兴听到,但我不确定这是否隐藏了另一个问题。谁在保留视图,进而保留图像 (byte[])?一个完全的谜。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-09
  • 1970-01-01
  • 1970-01-01
  • 2012-07-27
相关资源
最近更新 更多