ListView和GridView多次调用GetView的现象和解决办法

背景:以前遇到过,最近又碰到了,就总结一下吧
一.ListView
(1)出现原因

是因为listView的高度不确定,一般用的是wrap_content,导致系统需要不断地测量,也就是多测调用onMeasure方法,所以就多次调用getView,所以解决方法也挺简单,把宽高写死(精确给个数字,或者match_parent).


(2)解决方法

adapter.java

    package com.dx.text0808;
     
    import android.content.Context;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    import android.widget.TextView;
     
    import java.util.ArrayList;
    import java.util.List;
     
     
    public class UpdateOtherGridAdapter extends BaseAdapter {
        private LayoutInflater inflater;
        private Context mContext;
        private List<String> contentList = new ArrayList<>();
     
     
        public UpdateOtherGridAdapter(Context context, ArrayList<String> list) {
            this.mContext = context;
            inflater = LayoutInflater.from(context);
            this.contentList = list;
        }
     
        public void setContentList(List<String> contentList) {
            this.contentList = contentList;
        }
     
        public void update() {
            this.notifyDataSetChanged();
        }
     
        @Override
        public int getCount() {
            return contentList.size();
        }
     
        @Override
        public Object getItem(int arg0) {
            return null;
        }
     
        @Override
        public long getItemId(int arg0) {
            return 0;
        }
     
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            System.out.println("xcqw getView  ***position"+position);
            ViewHolder holder = null;
            if (convertView == null) {
                convertView = inflater.inflate(R.layout.item,
                        parent, false);
                holder = new ViewHolder();
                holder.tvContent = (TextView) convertView.findViewById(R.id.tv_content);
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }
     
            String content = contentList.get(position);
            holder.tvContent.setText(content);
            return convertView;
        }
     
        public class ViewHolder {
            public TextView tvContent;
        }
     
     
    }

 

<1>会出现多次调用getView的写法

activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        >
     
        <Button
            android:id="@+id/bt_refresh"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="点我更新listView"/>
     
        <ListView
            android:id="@+id/gv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
        </ListView>
    </LinearLayout>

注意看到 ListView的Layout_height中写的是wrap_content


实际打印如下:
08-07 16:39:18.604 25086-25086/com.dx.text0808 I/System.out: xcqw getView  ***position0
08-07 16:39:18.609 25086-25086/com.dx.text0808 I/System.out: xcqw getView  ***position1
08-07 16:39:18.609 25086-25086/com.dx.text0808 I/System.out: xcqw getView  ***position2
08-07 16:39:18.668 25086-25086/com.dx.text0808 I/System.out: xcqw getView  ***position0
08-07 16:39:18.669 25086-25086/com.dx.text0808 I/System.out: xcqw getView  ***position1
08-07 16:39:18.679 25086-25086/com.dx.text0808 I/System.out: xcqw getView  ***position2
08-07 16:39:18.691 25086-25086/com.dx.text0808 I/System.out: xcqw getView  ***position0
08-07 16:39:18.693 25086-25086/com.dx.text0808 I/System.out: xcqw getView  ***position1
08-07 16:39:18.707 25086-25086/com.dx.text0808 I/System.out: xcqw getView  ***position2
08-07 16:39:18.784 25086-25086/com.dx.text0808 I/System.out: xcqw getView  ***position0
08-07 16:39:18.785 25086-25086/com.dx.text0808 I/System.out: xcqw getView  ***position1
08-07 16:39:18.786 25086-25086/com.dx.text0808 I/System.out: xcqw getView  ***position2

 

<2>不会出现多次调用getView的写法

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        >
     
        <Button
            android:id="@+id/bt_refresh"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="点我更新listView"/>
     
        <ListView
            android:id="@+id/gv"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
        </ListView>
    </LinearLayout>


注意看到现在ListView中的Layout_height写的是Match_parent


实际打印如下:

    08-07 16:42:48.892 28432-28432/com.dx.text0808 I/System.out: xcqw getView  ***position0
    08-07 16:42:48.905 28432-28432/com.dx.text0808 I/System.out: xcqw getView  ***position1
    08-07 16:42:48.910 28432-28432/com.dx.text0808 I/System.out: xcqw getView  ***position2

 


二.GridView

(1)出现原因

貌似不管长宽写不写死都是会多次调用getView,不知道为啥,日了狗了。。。原因待补充


(2)解决方法

<1>出现的情形

adapter.xml

    package com.dx.text0807;
     
    import android.content.Context;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    import android.widget.TextView;
     
    import java.util.ArrayList;
    import java.util.List;
     
     
    public class UpdateOtherGridAdapter extends BaseAdapter {
        private LayoutInflater inflater;
        private Context mContext;
        private List<String> contentList = new ArrayList<>();
     
     
        public UpdateOtherGridAdapter(Context context, ArrayList<String> list) {
            this.mContext = context;
            inflater = LayoutInflater.from(context);
            this.contentList = list;
        }
     
        public void update() {
            this.notifyDataSetChanged();
        }
     
        @Override
        public int getCount() {
            return contentList.size();
        }
     
        @Override
        public Object getItem(int arg0) {
            return null;
        }
     
        @Override
        public long getItemId(int arg0) {
            return 0;
        }
     
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            System.out.println("xcqw getView  1***position"+position);
     
            ViewHolder holder = null;
            if (convertView == null) {
                convertView = inflater.inflate(R.layout.item,
                        parent, false);
                holder = new ViewHolder();
                holder.tvContent = (TextView) convertView.findViewById(R.id.tv_content);
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }
     
     
            if(((MyGridView) parent).isOnMeasure){
                //如果是onMeasure调用的就立即返回
                return convertView;
            }
            System.out.println("xcqw getView  2***position"+position);
     
            String content = contentList.get(position);
            holder.tvContent.setText(content);
     
     
        //如果不是onMeasure调用的就可以正常操作了
        //赋值操作
            return convertView;
        }
     
        public class ViewHolder {
            public TextView tvContent;
        }
     
     
    }

 


activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.dx.text0807.MainActivity">
     
        <com.dx.text0807.MyGridView
            android:id="@+id/gv"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            >
        </com.dx.text0807.MyGridView>
        <!--android:layout_height="wrap_content"-->
        <!--android:layout_height="50dp"-->
    </RelativeLayout>

 

注意了!!!,不管你长宽怎么写都是会多次调用getView,不知道网上说写死就可以的人是怎么整的。。。


<2>解决方法

不让他多次调用getView是不可能了,所以只能说在他onMeasure调用getView的时候我们不要去对convertView做任务赋值的操作,只有当onLayout的时候我们再对ConvertView操作

首先我们要重写一个gridView

MyGridView.java

    public class MyGridView extends GridView {
        public boolean isOnMeasure;
        public MyGridView(Context context) {
            super(context);
        }
     
        public MyGridView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
     
     
        public MyGridView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }
     
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            isOnMeasure = true;
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
     
        @Override
        protected void onLayout(boolean changed, int l, int t, int r, int b) {
            isOnMeasure = false;
            super.onLayout(changed, l, t, r, b);
        }
    }


getView中对ConvertView的处理

    @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            System.out.println("xcqw getView  1***position"+position);
     
            ViewHolder holder = null;
            if (convertView == null) {
                convertView = inflater.inflate(R.layout.item,
                        parent, false);
                holder = new ViewHolder();
                holder.tvContent = (TextView) convertView.findViewById(R.id.tv_content);
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }
     
     
            if(((MyGridView) parent).isOnMeasure){
                //如果是onMeasure调用的就立即返回
                return convertView;
            }
            System.out.println("xcqw getView  2***position"+position);
     
            String content = contentList.get(position);
            holder.tvContent.setText(content);
     
     
        //如果不是onMeasure调用的就可以正常操作了
        //赋值操作
            return convertView;
        }

 

实际打印

08-07 17:11:37.119 17294-17294/com.dx.text0807 I/System.out: xcqw getView  1***position0
08-07 17:11:37.178 17294-17294/com.dx.text0807 I/System.out: xcqw getView  1***position0
08-07 17:11:37.268 17294-17294/com.dx.text0807 I/System.out: xcqw getView  1***position0
08-07 17:11:37.268 17294-17294/com.dx.text0807 I/System.out: xcqw getView  2***position0
08-07 17:11:37.269 17294-17294/com.dx.text0807 I/System.out: xcqw getView  1***position1
08-07 17:11:37.271 17294-17294/com.dx.text0807 I/System.out: xcqw getView  2***position1
08-07 17:11:37.272 17294-17294/com.dx.text0807 I/System.out: xcqw getView  1***position2
08-07 17:11:37.273 17294-17294/com.dx.text0807 I/System.out: xcqw getView  2***position2
08-07 17:11:37.274 17294-17294/com.dx.text0807 I/System.out: xcqw getView  1***position3
08-07 17:11:37.276 17294-17294/com.dx.text0807 I/System.out: xcqw getView  2***position3
08-07 17:11:37.279 17294-17294/com.dx.text0807 I/System.out: xcqw getView  1***position0
08-07 17:11:37.281 17294-17294/com.dx.text0807 I/System.out: xcqw getView  1***position0
08-07 17:11:37.373 17294-17294/com.dx.text0807 I/System.out: xcqw getView  1***position0
08-07 17:11:37.376 17294-17294/com.dx.text0807 I/System.out: xcqw getView  1***position0


可以看到  getView2***  打印只有四次  ,效果达到了,哈哈
---------------------
转自原文:https://blog.csdn.net/u011889786/article/details/52143268

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值