Code Monkey home page Code Monkey logo

Comments (5)

wenmingvs avatar wenmingvs commented on July 25, 2024

我项目里面也遇到类似的,我是recyclerview嵌套了recyclerview,其中嵌套的那层RecyclerView用于显示微博图片,与你的情况应该很类似。我给你以下解决方案,应该能很好的解决这个问题

  1. 根据内容预先计算好GridView的高度,然后给GridView设置固定的高度,这样ListView在快速滑动的时候就不需要再去动态的计算高度了
//获取gridview的宽高参数
mParams = (LinearLayout.LayoutParams) ViewHolder.gridview.getLayoutParams();

/根据数据集mImageDatas的数量,计算展示这些数据集需要多少行,然后再乘以单个item的布局高度,得到总的gridview高度
mParams.height = (DensityUtil.dp2px(mContext, 110f)) * getImgLineCount(mImageDatas) + 
(DensityUtil.dp2px(mContext, 5f)) * getImgLineCount(mImageDatas);

//同上,根据数据集的内容,来计算一共需要多少列,如果是定值直接写常量即可,再乘以单个item的布局宽度,得到总的gridview的宽度
mParams.width = (DensityUtil.dp2px(mContext, 110f)) * 3 + (DensityUtil.dp2px(mContext, 5f)) * 2;

//设定参数
ViewHolder.gridview.setLayoutParams(mParams);
  1. 监听外层的ListView的滑动操作,在停止滑动的时候,才去加载图片
  2. 使用ImageLoader来统一管理每一个ImageView,尽可能的把缓存机制利用起来

from weibo.

t2314862168 avatar t2314862168 commented on July 25, 2024

@wenmingvs 你的解决方法应该有一定的效果,但是比如如果gridview里面的item的count 是300个,虽然一次性计算出来了高度,但是每一个item显示的时候都是new 出来的,没有复用viewholder,这样造成滑动的时候会出现ANR的情况吧(我自己用300个做过实验)

from weibo.

wenmingvs avatar wenmingvs commented on July 25, 2024

你好,每一个item并不会new出来,而是会去复用,new出来的是只是bitmap而已。你可以好好读一下这篇博客http://blog.csdn.net/guolin_blog/article/details/45586553

另外你说会出现ANR问题,能否发相关的Demo的github地址发我看看呢?我推测是你在listview内并没有做很好的复用,并且图片也没有做适当的裁剪,才会引起ANR问题的

from weibo.

t2314862168 avatar t2314862168 commented on July 25, 2024

@wenmingvs 刚去查阅了郭神的博客结合看了下源码,不管ListView或者是GridView的高度固定或者是不固定,RecyclerBin的机制会一直都有,这算是自己的理解误区。
由于代码是在公司的项目里面,我自己不太好抽离出来,我贴下我的核心代码。
首先是ListView的Adapter代码:

@Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.layout_dynamic_list_item,
                    parent, false);
        }
        // 省略代码...
        NoScrollGridView gridView = ViewHolder.get(convertView, R.id.gridview);
        // 省略代码...
        // 图片
        DynamicGridItemAdapter gridItemAdapter = null;
        if (!TextUtils.isEmpty(imageUrl)) {
            gridView.setVisibility(View.VISIBLE);
            gridView.setOnItemClickListener(new OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view,
                        int position, long id) {
                    handleGridItemClick(bean);
                }
            });
            if (gridView.getAdapter() != null) {
                gridItemAdapter = (DynamicGridItemAdapter) gridView
                        .getAdapter();
                gridItemAdapter.setUrlArray(new String[] { imageUrl });
            } else {
                gridItemAdapter = new DynamicGridItemAdapter();
                gridView.setAdapter(gridItemAdapter);
                gridItemAdapter.setUrlArray(new String[] { imageUrl });
            }
            // 很重要,让listview的onItemClick有效果
            GridViewUtils.updateGridViewLayoutParams(gridView, 3);
        } else {
            gridView.setVisibility(View.GONE);
        }
        // 省略代码...
        return convertView;
    }

ViewHolder的代码:

public class ViewHolder {
    /**
     * <T extends View> 泛型的声明 , T 表示方法的返回值
     * 
     * @param view
     * @param id
     * @return
     */
    public static <T extends View> T get(View view, int id) {
        SparseArray<View> viewHolder = (SparseArray<View>) view.getTag();
        if (viewHolder == null) {
            viewHolder = new SparseArray<View>();
            view.setTag(viewHolder);
        }
        View childView = viewHolder.get(id);
        if (childView == null) {
            childView = view.findViewById(id);
            viewHolder.put(id, childView);
        }
        return (T) childView;
    }
}

GridView的DynamicGridItemAdapter里面的代码为:

public class DynamicGridItemAdapter extends BaseAdapter {
    private ArrayList<String> urlList;
    String url = "http://pic.sc.chinaz.com/files/pic/pic9/201509/apic14886.jpg";

    public DynamicGridItemAdapter() {
        urlList = new ArrayList<String>();
    }

    public void setUrlArray(String[] urlArray) {
        urlList.clear();
        for (int i = 0; i < urlArray.length; i++) {
            urlList.add(urlArray[i]);
        }
        notifyDataSetChanged();
    }

    @Override
    public int getCount() {
        return urlList != null ? urlList.size() : 0;
    }

    @Override
    public Object getItem(int position) {
        return urlList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            LayoutInflater inflater = (LayoutInflater) parent.getContext()
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            convertView = inflater.inflate(
                    R.layout.layout_dynamic_list_grid_item, parent, false);
        }
//      DebugToolUtils.printTest("getView", "position===="+position+"$$$$$convertView====="+convertView);
        ImageView imageView = ViewHolder
                .get(convertView, R.id.iv_gridview_item);
//       ImageLoaderUtils.displayImage(url, imageView);
        ImageLoaderUtils.displayImage(urlList.get(position), imageView);
        return convertView;
    }
}

图片加载用的UIL(内存缓存和硬盘缓存都已经设置了),具体ImageLoaderUtils.displayImage代码:

/**
     * 加载图片
     * 
     * @param uri
     *            图片地址
     * @param imageView
     *            图片控件
     */
    public static void displayImage(String uri, ImageView imageView) {
        ImageAware imageAware = new ImageViewAware(imageView, false);
        ImageLoader.getInstance().displayImage(uri, imageAware,
                getCustomOptions());
    }

图片scaleType,我设置的是center

from weibo.

wenmingvs avatar wenmingvs commented on July 25, 2024

你好,我细看了adapter的代码,暂时没有发现不对的地方,根据你反馈的原因,引起崩溃的是ANR而不是OOM,所以我推测的原因有2点

  1. ListView在快速滑动时需要动态计算GridView的高度,大量的计算引起了UI线程的阻塞,所以会出现ANR问题
  2. 快速滑动的时候,加载图片又马上缓存图片,导致了频繁的GC操作,引起了内存抖动,加重了CPU的负担,也进一步推动了ANR问题的出现。

能否先尝试我以下2个方法,看看是否还会有ANR问题?

  1. 手动设置GridView的高度与宽度
  2. 监听ListView的滑动事件,滑动的时候不做图片的加载,只有在停止滑动了再去加载图片

如果添加这2个方法后,仍然出现ANR问题,再联系我

from weibo.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.