包含在Android ListView中的EditText的内容不会保存

P. *_*ohm 2 java android android-listview

在我的项目中,我必须向用户显示一个基本上包含EditText的ListView.

这就像一份调查问卷,当他回答问题时,他可以下来回答下一个问题.(并回去)

public class onAdapter extends BaseAdapter {
    List<PointVerification> mObjects;
    Context mContext;
    LayoutInflater mInflater;

    HashMap<Integer, List<ChoixPointVerification>> mChoix;
    HashMap<Integer, ReponsePointVerification> mReponses;
    HashMap<Integer, String> mReponsesActuel;
    Integer mPositionSelectionne;
    Integer mIdIntervention;


    /**
     * Constructeur
     * @param context

     * @param listePointsVerification Liste des points de vérification à afficher.
     * @param listeChoixPointsVerification liste des choix de points de vérification pour chaque point de vérification.
     * @param listeReponsesPointsVerification réponses déjà fournies pour chaque point de vérification
     * @param idIntervention Identifiant de l'intervention
     */
    public onAdapter(
            Context context,

            Integer idIntervention, 
            List<PointVerification> listePointsVerification,
            List<ChoixPointVerification>> listeChoixPointsVerification,
            ReponsePointVerification> listeReponsesPointsVerification) {

        this.mInflater = LayoutInflater.from(context);
        this.mContext = context;
        this.mObjects = listePointsVerification;

        this.mChoix = listeChoixPointsVerification;
        this.mReponses = listeReponsesPointsVerification;
        this.mIdIntervention = idIntervention;


        // préparation des réponses par position
        this.mReponsesActuel = new HashMap<Integer, String>();
    }


    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View row;

        final Integer idPointVerification = getItem(position).id;

        if (convertView == null)
        {
            row = mInflater.inflate(R.layout.intervention_reponses_controle_nombre, null);

            EditText edValeur = (EditText) row.findViewById(R.id.edValeur);
            // Ajout de l'évènement lorsque l'on change la valeur
            // evènement d'enregistrement
            edValeur.addTextChangedListener(new TextWatcher() 

                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {
                }

                @Override
                public void beforeTextChanged(CharSequence s, int start, int count,
                        int after) {
                }

                @Override
                public void afterTextChanged(Editable s) {
                    // This hashmap is a try workaround to the bug
                    // i register all modifications into this hashmap
                    mReponsesActuel.put(
                            idPointVerification,
                            s.toString());

                    // SAVE PROCEDURE
                    // REMOVED FOR THE EXAMPLE
                    // BUT I UPDATE MY DATABASE
                }
            });
        }
        else
        {
            row = convertView;
        }

        EditText edValeur = (EditText) row.findViewById(R.id.edValeur);

        // update of the text
        // it is the contained in the hashmap
        if (mReponsesActuel.containsKey(idPointVerification)) {
            String valeur = mReponsesActuel.get(idPointVerification);
            edValeur.setText(valeur);
        // otherwhise i will look into the database
        } else if (mReponses != null && mReponses.containsKey(idPointVerification)
                && mReponses.get(idPointVerification).valeur != null) {
            edValeur.setText(mReponses.get(idPointVerification).valeur);
        }
        else
        {
            edValeur.setText("");
        }

        return row;
    }
}
Run Code Online (Sandbox Code Playgroud)

我不知道为什么但是用户在ListView中进入,内容未保存并显示一些特殊值,如其他EditText.我没有找到如何纠正这种行为,而且它真的很匆忙.

基本上我创建了一个TextWatcher,它将数据注册到数据库中,并且还包含一个包含所有值的临时HashMap.调用GetView时会调用该数据.如果我删除了初始化,EditText将被删除.

注意:我在我的代码中进行了一些测试,因此可能存在不同的问题.

编辑

我上传了一个带有问题的项目:http://dl.free.fr/rbqOhUfJF

这里重现问题的步骤:

  1. 以调试模式启动项目

  2. 写入第一行A,第二行B,第三行

  3. 向下滚动,直到隐藏C.

  4. 向上滚动到顶部.结果:没有更多文字.

如果仔细查看调试日志,可以看到使用afterText的行.每次我们在第2部分中编写一些文本时,都会有一个调试行来注册事件.

但是在第3阶段,当你隐藏一个项目.该活动将以""启动

结果:在第4阶段,它加载""字符串

HpT*_*erm 5

为了加快大多数移动应用程序(Android iOS ...)的速度,通常会回收列表单元格.这节省了内存,特别是对于长列表.因此,您必须获取新显示的单元格的数据.当单元格移出屏幕时,其布局/视图将被破坏.在您的情况下,您必须在某处保存编辑文本的文本.这就是你想要用hashmap做的事情.

我没有在您的代码中看到任何特殊错误.

如果问题是关于使用hashmap的"解决方法",我确认对我来说,由你来保存编辑文本的状态.使用hashmap是一种方法.

顺便说一句,getItem(position).id可以替换getItemId(position)为此目的.

不确定这一切是否都能回答你的问题.

编辑

现在我正确地理解了你的问题,我可以提供一些代码.我必须说,我对找到的解决方案并不满意,但至少它是有效的.

TextWatcher的问题是您无法访问上下文和相应的视图.

使用setOnFocusChangeListener解决了这个问题.所以这是我终于开始工作的代码.

public final class PointVerificationAdapter extends BaseAdapter {
    List<BasicNameValuePair> mObjects;
    Context mContext;
    LayoutInflater mInflater;
    HashMap<Integer, String> mReponsesActuel;
    ArrayList<String> myItems = new ArrayList<String>();

    public PointVerificationAdapter(
            Context context,
            List<BasicNameValuePair> listObjets
            ) {

        this.mInflater = LayoutInflater.from(context);
        this.mContext = context;
        this.mObjects = listObjets;

        for (int i = 0; i < 30; i++) {
            myItems.add(Integer.toString(i));
        }
    }

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

    @Override
    public BasicNameValuePair getItem(int position) {
        return mObjects.get(position);
    }

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

    static class ViewHolder {
        EditText yourEditText;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        ViewHolder holder = null;

        if (convertView == null)
        {
            holder = new ViewHolder();
            convertView = mInflater.inflate(R.layout.intervention_reponses_controle_nombre, parent, false);
            convertView.setId(position);
            holder.yourEditText = (EditText) convertView.findViewById(R.id.edValeur);

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

        ((TextView) convertView.findViewById(R.id.tvNom)).setText(Integer.toString(position));

        holder.yourEditText.setText(myItems.get(position));
        holder.yourEditText.setId(position);
        holder.yourEditText.setOnFocusChangeListener(new OnFocusChangeListener() {
            public void onFocusChange(View view, boolean hasFocus) {
                if (!hasFocus){
                    final int position = view.getId();
                    final EditText editText = (EditText) view;
                    myItems.set(position, editText.getText().toString());
                }
            }
        });

        return convertView;
    }

}
Run Code Online (Sandbox Code Playgroud)

最终编辑

之前的代码正在运行,但我对它不满意,因为你要求addTextChangedListener而不是onFocusChange.

所以这是解决方案:

public final class PointVerificationAdapter extends BaseAdapter {
    List<BasicNameValuePair> mObjects;
    Context mContext;
    LayoutInflater mInflater;
    HashMap<Integer, String> mReponsesActuel;
    ArrayList<String> myItems = new ArrayList<String>();

    public PointVerificationAdapter(
            Context context,
            List<BasicNameValuePair> listObjets
            ) {

        this.mInflater = LayoutInflater.from(context);
        this.mContext = context;
        this.mObjects = listObjets;

        for (int i = 0; i < 30; i++) {
            myItems.add(Integer.toString(i));
        }
    }

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

    @Override
    public BasicNameValuePair getItem(int position) {
        return mObjects.get(position);
    }

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

    static class ViewHolder {
        EditText yourEditText;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        ViewHolder holder = null;

        if (convertView == null)
        {
            holder = new ViewHolder();
            convertView = mInflater.inflate(R.layout.intervention_reponses_controle_nombre, parent, false);
            convertView.setId(position);
            holder.yourEditText = (EditText) convertView.findViewById(R.id.edValeur);
            holder.yourEditText.setId(position);
            holder.yourEditText.addTextChangedListener(new GenericTextWatcher(holder.yourEditText));
            convertView.setTag(holder);
        }
        else
        {
            holder = (ViewHolder) convertView.getTag();
            holder.yourEditText.setId(position);
        }

        ((TextView) convertView.findViewById(R.id.tvNom)).setText(Integer.toString(position));

        holder.yourEditText.setText(myItems.get(position));

        return convertView;
    }

    private class GenericTextWatcher implements TextWatcher{

        private View view;
        private GenericTextWatcher(View view) {
            this.view = view;
        }

        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}

        public void afterTextChanged(Editable editable) {
            final int position = view.getId();
            final EditText editText = (EditText) view;
            myItems.set(position, editText.getText().toString());
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 是的,关键是要正确访问正确的editText视图.在您的情况下,addTextChangedListener并不总是引用正确的editText.在这种情况下,您需要正确的上下文.通过将TextWatcher与'view'一起使用,我确信我链接到正确的视图,这是您正在编辑的editText之一.我必须承认,我在寻找解决方案方面有点挣扎,但现在一切都清楚了.照顾自己.再见 (3认同)