中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

解決ListView中包含EditText數據混亂原理

發布時間:2020-08-10 11:25:28 來源:網絡 閱讀:5244 作者:IT學無止境 欄目:移動開發

要求:屏幕中顯示一個listview,其中每一個item都有一個editText,在任一editText上輸入內容,快速上下滑動,保證數據不混亂。

這是一道面試題,初看沒什么,應該會很簡單,但實際解決起來沒那么簡單,先上解決代碼。

package com.zhiren.mytestok;

import android.content.Context;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.EditText;

import java.util.List;

/**
 * Created by Administrator on 2017/2/20.
 */

public class MyAdapters extends BaseAdapter {
    private Context context;
    //    private String[] str;
    private List list;

    public MyAdapters(Context context, List list) {
        this.context = context;
        this.list = list;
    }

    @Override
    public int getCount() {
        return list.size();
    }

    @Override
    public Object getItem(int position) {
        return null;
    }

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

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        final ViewHolder viewHolder;
        if (convertView == null) {
            convertView = View.inflate(context, R.layout.item_mian, null);
            viewHolder = new ViewHolder(convertView);


            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }

        Bean bean = (Bean) list.get(position);
        Log.e("TAG", viewHolder.text + ":" + position);
        viewHolder.text.setTag(position);
        viewHolder.text.clearFocus();


        viewHolder.text.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                int pos = (int) viewHolder.text.getTag();
                Bean b  = (Bean) list.get(pos);
                b.setName(s + "");
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });

        if (!TextUtils.isEmpty(bean.getName())) {
            viewHolder.text.setText(bean.getName());
        } else {
            viewHolder.text.setText("");
        }

        return convertView;
    }

    public class ViewHolder {
        private EditText text;

        public ViewHolder(View v) {
            text = (EditText) v.findViewById(R.id.et_item);
        }
    }
}

解釋:解決ListView中包含EditText數據混亂原理

通過打印log可以看到,屏幕中最多可以顯示7行item,下標依次為:0、1、2、3、4、5、6.

其中下標為0的item的地址值是3098e6e5

通過向上滑動,當出現第8行item(下標為7)的時候,下標為0的item已經完全看不到了,根據谷歌設計原理,下標為0的item復用到了剛剛出現的下標為7的item上,其中可以看到下標為7的item的地址值也是3098e6e5,以上可以證明。這些都是大家知道的,重點看下面:

為什么要寫

viewHolder.text.setTag(position);

這一行意義重大,在滑動的過程中,動態的將item與position進行綁定,如圖:

解決ListView中包含EditText數據混亂原理

那么這么做的意義是什么呢,可以看到item中的editText有一個監聽事件:每當editText內容變化的時候都會將editText上的內容保存至集合中,那么保存到集合的哪一個下標中呢?看這行

int pos = (int) viewHolder.text.getTag();

被點擊的那行item根據getTag()獲取了最近與它綁定的那個position,還以地址為3098e6e5的item為例,那么pos的值此時應該是0還是7呢?這與當前listview滑動的位置有關,如果當前屏幕能看到下標為7的item,那么此時pos就必定為7,不可能為0,第一:item只能動態與一個position相綁定,第二,綁定是動態變化的,當前屏幕能看到的是下標為7的item,自然item與下標7綁定就不能再與下標0綁定了。那么就得到pos為7,集合就會將當前editText的內容保存到下標為7的對象中。那么無論再怎么上下滑動,只有當positon為7的時候才能從集合中獲取那條保存的數據,其他position都不可以,其他item也同理。



如果正常寫會出現什么呢?

例如:監聽器里不getTag()

viewHolder.text.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
//                int pos = (int) viewHolder.text.getTag();
//                Bean b  = (Bean) list.get(pos);
//                b.setName(s + "");
                Bean b = (Bean) list.get(position);
                b.setName(s + "");
                Log.e("TAG", "" + position);
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });


運行app后,首先上下滑動listView到最后再滑動到開頭(我設置了長度為51),讓每一個item充分復用,此時再次在下標為0的item中輸入內容,打印數據如下:

解決ListView中包含EditText數據混亂原理

可以看到,我只在一個item的editText中輸入了1個字,按道理來說應該只觸發下標為0的那個item,并將下標為0的item上的數據保存到集合,但事實上卻觸發了這么多item中的editText的監聽,這是為什么呢?

原因是在上下快速滑動的過程中,下標為0的item出現了大量的復用情況,例如第0、7、14、21行的item都復用了這一個item,而適配器中的getView()方法經過了多次的執行,每次執行完畢后一些無用的資源就被回收了,但是item的editText是保存在viewHolder中的,并沒有被回收,但是多次的執行getView()方法,每一次都讓Item中的這個editText在對應的positon下設置了一次監聽,那么多次設置監聽,對應的是不同的位置(position),當觸發監聽的時候,自然會多處響應,導致了數據顯示的混亂。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

疏附县| 平舆县| 屏东县| 上思县| 理塘县| 和静县| 广水市| 绥化市| 左贡县| 芒康县| 宜春市| 吉木萨尔县| 阳谷县| 商城县| 凯里市| 罗甸县| 英超| 蛟河市| 南靖县| 绵竹市| 澄迈县| 渝北区| 临颍县| 武安市| 东乌珠穆沁旗| 安远县| 平谷区| 泽普县| 肇庆市| 天台县| 黎平县| 崇仁县| 图木舒克市| 阿尔山市| 德庆县| 东丽区| 隆林| 锡林浩特市| 广州市| 玛曲县| 陈巴尔虎旗|