Не удается получить значения из Listview EditText?

Я пытаюсь получить данные из EditText, который находится в моем Listview. Я видел много похожих вопросов и получил решение. Но он бросает NPE в моей реализации.

Итак, пожалуйста, помогите мне решить эту проблему.

Адаптер

public class Coscho_adapter extends BaseAdapter {

    Context con;
    ArrayList<HashMap<String, String>> list;
    LayoutInflater mInflater;
    EditText marks;
    TextView studname, acname;

    public Coscho_adapter(Context co, ArrayList<HashMap<String, String>> list1) {
        list = list1;
        con = co;
        mInflater = (LayoutInflater) con.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

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

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

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

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if(convertView==null){
            holder = new ViewHolder();
            convertView = mInflater.inflate(R.layout.sc_item,null,false);
            holder.marks = (EditText) convertView.findViewById(R.id.marks);
            holder.studname = (TextView) convertView.findViewById(R.id.stu_name);
            holder.acname = (TextView) convertView.findViewById(R.id.act_name);
            convertView.setTag(holder);
        }else{
            holder = (ViewHolder) convertView.getTag();
        }

        int sno = position + 1;
        holder.studname.setText(sno + ". " + list.get(position).get("DESCRIPTOR"));
        holder.acname.setVisibility(View.GONE);
        holder.marks.setText(list.get(position).get("STUDENT_MARK"), TextView.BufferType.EDITABLE);
        int maxLength = 1;
        holder.marks.setFilters(new InputFilter[] {new InputFilter.LengthFilter(maxLength), new InputFilterMinMax("0", "5")});
        desc_ids.add(list.get(position).get("DESCRIPTOR_ID"));

        return convertView;
    }

    class ViewHolder {
        EditText marks;
        TextView studname, acname;
    }
}

OnClick

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if(item.getItemId()==R.id.add)
    {
       View v;
        ArrayList<String> scho = new ArrayList<String>();
        EditText et;
        if (co_adapter.getCount() != 0) {
        for (int i = 0; i < co_adapter.getCount(); i++) {
            v = mListView.getChildAt(i);
            et = (EditText) v.findViewById(R.id.marks);
            if (et != null) {
                scho.add(et.getText().toString());
                Log.e("SCH", et.getText().toString());
            }
        }
    }
   }
    return super.onOptionsItemSelected(item);
}

Экран

ОБНОВЛЕНИЕ с помощью TextWatcher

Теперь я могу сохранить значение edittext в массиве. Но когда прокручивается список. Значения изменяются на значения intial.

 public class Coscho_adapter extends BaseAdapter {

            Context con;
            LayoutInflater mInflater;

            public Scholastic_adapter(Context context, ArrayList<HashMap<String, String>> list1) {
                sadap_list = list1;
                con = context;
                mInflater = LayoutInflater.from(context);
            }

            @Override
            public int getCount() {
                return sadap_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) {
                ViewHolder holder;
                if(convertView==null){
                    holder = new ViewHolder();
                    convertView = mInflater.inflate(R.layout.sc_item,null,false);
                    holder.marks = (EditText) convertView.findViewById(R.id.marks);
                    holder.studname = (TextView) convertView.findViewById(R.id.stu_name);
                    holder.acname = (TextView) convertView.findViewById(R.id.act_name);
                    convertView.setTag(holder);
                }else{
                    holder = (ViewHolder) convertView.getTag();
                }

                for (int i = 0; i < arrScMarks.length; i++) {
                    Log.e("Array > ", i +"> "+ arrScMarks[i]);
                }

                int sno = position + 1;
                holder.ref = position;
                holder.studname.setText(sno + ". " + sadap_list.get(holder.ref).get("FIRST_NAME"));
                holder.acname.setText(sadap_list.get(holder.ref).get("ACTIVITY_NAME"));
                holder.marks.setText(arrScMarks[holder.ref]);
                holder.marks.addTextChangedListener(new GenericTextWatcher(holder.ref));


                return convertView;
            }

            class ViewHolder {
                EditText marks;
                TextView studname, acname;
                int ref;
            }
        }

TextWatcher

private class GenericTextWatcher implements TextWatcher{

        int position;

        private GenericTextWatcher(int pos) {
              this.position = pos;
        }

        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) {
            String text = editable.toString();
            arrScMarks[position] = text;
            Log.e("Watcher > ", position +"> "+ arrScMarks[position] );
            }
        }

LogCat

Ввод данных

09-01 05:37:59.658 2466-2466/app E/Watcher >: 1> 
09-01 05:38:00.638 2466-2466/app E/Watcher >: 1> 1
09-01 05:38:02.518 2466-2466/app E/Watcher >: 2> 
09-01 05:38:02.798 2466-2466/app E/Watcher >: 2> 2
09-01 05:38:04.478 2466-2466/app E/Watcher >: 3> 
09-01 05:38:05.318 2466-2466/app E/Watcher >: 3> 3
09-01 05:38:06.878 2466-2466/app E/Watcher >: 4> 
09-01 05:38:07.758 2466-2466/app E/Watcher >: 4> 4
09-01 05:38:09.928 2466-2466/app E/Watcher >: 5> 
09-01 05:38:10.278 2466-2466/app E/Watcher >: 5> 5

Пока прокрутка

09-01 05:48:49.188 16362-16362/app E/Watcher >: 0> 0
09-01 05:48:49.538 16362-16362/app E/Watcher >: 1> 0
09-01 05:48:49.708 16362-16362/app E/Watcher >: 2> 0
09-01 05:48:49.888 16362-16362/app E/Watcher >: 3> 0
09-01 05:48:50.268 16362-16362/app E/Watcher >: 4> 0
09-01 05:48:50.538 16362-16362/app E/Watcher >: 5> 0
09-01 05:48:50.558 16362-16362/app E/Watcher >: 6> 0
09-01 05:48:50.868 16362-16362/app E/Watcher >: 8> 0
09-01 05:48:52.708 16362-16362/app E/Watcher >: 9> 0
09-01 05:48:52.768 16362-16362/app E/Watcher >: 0> 0
09-01 05:48:52.768 16362-16362/app E/Watcher >: 10> 0
09-01 05:49:20.648 16362-16362/app E/Watcher >: 9> 0
09-01 05:49:20.648 16362-16362/app E/Watcher >: 18> 0
09-01 05:49:20.738 16362-16362/app E/Watcher >: 8> 0
09-01 05:49:20.738 16362-16362/app E/Watcher >: 17> 0
09-01 05:49:20.818 16362-16362/app E/Watcher >: 7> 0
09-01 05:49:20.888 16362-16362/app E/Watcher >: 5> 0
09-01 05:49:20.888 16362-16362/app E/Watcher >: 15> 0
09-01 05:49:20.898 16362-16362/app E/Watcher >: 4> 0
09-01 05:49:20.898 16362-16362/app E/Watcher >: 14> 0
09-01 05:49:20.968 16362-16362/app E/Watcher >: 3> 0
09-01 05:49:20.968 16362-16362/app E/Watcher >: 13> 0
09-01 05:49:21.068 16362-16362/app E/Watcher >: 6> 0
09-01 05:49:21.068 16362-16362/app E/Watcher >: 16> 0
09-01 05:49:22.008 16362-16362/app E/Watcher >: 1> 0
09-01 05:49:22.008 16362-16362/app E/Watcher >: 11> 0
09-01 05:49:22.058 16362-16362/app E/Watcher >: 0> 0
09-01 05:49:22.058 16362-16362/app E/Watcher >: 10> 0
09-01 05:49:22.058 16362-16362/app E/Watcher >: 10> 0
09-01 05:49:22.098 16362-16362/app E/Watcher >: 9> 0
09-01 05:49:22.098 16362-16362/app E/Watcher >: 18> 0
09-01 05:49:22.108 16362-16362/app E/Watcher >: 9> 0

Пока значение повторного ввода после прокрутки

09-01 05:56:32.288 16362-16362/app E/Watcher >: 1> 
09-01 05:56:32.288 16362-16362/app E/Watcher >: 10> 
09-01 05:56:32.288 16362-16362/app E/Watcher >: 10> 
09-01 05:56:32.288 16362-16362/app E/Watcher >: 1> 
09-01 05:56:33.438 16362-16362/app E/Watcher >: 1> 1
09-01 05:56:33.438 16362-16362/app E/Watcher >: 10> 1
09-01 05:56:33.438 16362-16362/app E/Watcher >: 10> 1
09-01 05:56:33.438 16362-16362/app E/Watcher >: 1> 1
09-01 05:56:34.918 16362-16362/app E/Watcher >: 11> 
09-01 05:56:34.918 16362-16362/app E/Watcher >: 2> 
09-01 05:56:36.248 16362-16362/app E/Watcher >: 11> 2
09-01 05:56:36.248 16362-16362/app E/Watcher >: 2> 2
09-01 05:56:37.918 16362-16362/app E/Watcher >: 3> 
09-01 05:56:37.918 16362-16362/app E/Watcher >: 12> 
09-01 05:56:37.918 16362-16362/app E/Watcher >: 3> 
09-01 05:56:39.008 16362-16362/app E/Watcher >: 3> 3
09-01 05:56:39.008 16362-16362/app E/Watcher >: 12> 3
09-01 05:56:39.008 16362-16362/app E/Watcher >: 3> 3

Ответ 1

Сначала я попытался бы добавить TextChangedListener в файл holder.marks, или вы могли бы добавить кнопку, чтобы сохранить новое значение, введенное в EditText.

Когда текст изменится, я изменил бы значения в списке. Без этого вы потеряете пользователя данных, когда список прокручивается по этой строке:

        holder.marks.setText(list.get(position).get("STUDENT_MARK"), TextView.BufferType.EDITABLE);

будет перезаписывать отмеченную ранее запись в списке.

Изменить: я помещаю код адаптера, который я нашел в ссылке, в случае, если он станет недоступным в будущем.

private class MyListAdapter extends BaseAdapter{

    @Override
    public int getCount() {
        // TODO Auto-generated method stub
        if(arrText != null && arrText.length != 0){
            return arrText.length;    
        }
        return 0;
    }

    @Override
    public Object getItem(int position) {
        // TODO Auto-generated method stub
        return arrText[position];
    }

    @Override
    public long getItemId(int position) {
        // TODO Auto-generated method stub
        return position;
    }

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

        //ViewHolder holder = null;
        final ViewHolder holder;
        if (convertView == null) {

            holder = new ViewHolder();
            LayoutInflater inflater = ListviewActivity.this.getLayoutInflater();
            convertView = inflater.inflate(R.layout.lyt_listview_list, null);
            holder.textView1 = (TextView) convertView.findViewById(R.id.textView1);
            holder.editText1 = (EditText) convertView.findViewById(R.id.editText1);    

            convertView.setTag(holder);

        } else {

            holder = (ViewHolder) convertView.getTag();
        }

        holder.ref = position;

        holder.textView1.setText(arrText[position]);
        holder.editText1.setText(arrTemp[position]);
        holder.editText1.addTextChangedListener(new TextWatcher() {

            @Override
            public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
                // TODO Auto-generated method stub

            }

            @Override
            public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
                    int arg3) {
                // TODO Auto-generated method stub

            }

            @Override
            public void afterTextChanged(Editable arg0) {
                // TODO Auto-generated method stub
                arrTemp[holder.ref] = arg0.toString();
            }
        });

        return convertView;
    }

    private class ViewHolder {
        TextView textView1;
        EditText editText1;
        int ref;
    }


}

Новое редактирование:

Удалите свой GenericTextWatcher и используйте его вместо этого. Когда я использовал вашу реализацию TextWatcher, она не сработала, я изменил ее так, и это работает для меня.

holder.getEditText().addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

        }

        @Override
        public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {

        }

        @Override
        public void afterTextChanged(Editable editable) {
            String text = editable.toString();
            ARR[holder.getPosition()] = text;
            Log.e("Watcher > ", holder.getPosition()+"> "+ ARR[holder.getPosition()] );
        }
    });

Ответ 2

Вам нужно удалить TextWatcher из edittext, прежде чем вы установите в нем текст

if (holder.marks.getTag() != null) {
   GenericTextWatcher oldWatcher = (GenericTextWatcher) holder.marks.getTag();
   holder.marks.removeTextChangedListener(oldWatcher);
   holder.marks.setText(arrScMarks[holder.ref]);
}
//then set new textwatcher to edittext with current position 
GenericTextWatcher watcher;
watcher = new GenericTextWatcher(position);
holder.marks.addTextChangedListener(watcher);
holder.marks.setTag(watcher);

Ответ 3

Причина, по которой вы получаете NPE, вероятно, потому, что ваш getItem возвращает null.

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

Вам нужно вернуть конкретную позицию в своей коллекции (Arraylist)

 @Override
public Object getItem(int arg0) {
    return list.get(arg0);
}

Ответ 4

Замените это:

    if (et != null) { // here you check if et,which is a textview if its null
        scho.add(et.getText().toString());
        Log.e("SCH", et.getText().toString());
    }

При этом:

    if (et.getText().toString()) { // check if the text is null
        scho.add(et.getText().toString());
        Log.e("SCH", et.getText().toString());
    }

Ответ 5

Метод, который вы используете:

v = mListView.getChildAt(i);

относится к суперклассу ViewGroup и собирается возвращать только видимые в данный момент элементы в ListView (потому что они переработаны и нет причины хранить их все в памяти). Попробуйте установить OnClickListener внутри метода getView() адаптера:

public View getView(final int position, View convertView, ViewGroup parent) {
    ...

    convertView.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            ...
            et = (EditText) v.findViewById(R.id.marks);
        }
    };
}

Обратите внимание, что создание нового экземпляра OnClickListener для каждого элемента обычно не является необходимым и вызовет некоторые накладные расходы. Вы можете использовать один OnClickListener и теги, чтобы различать элементы.

В качестве альтернативы вы можете использовать сборку ListView в слушателе:

https://developer.android.com/reference/android/widget/AdapterView.OnItemClickListener.html

Ответ 6

Listview getChildAt(i) возвращает значение для видимых элементов на устройстве не для всех элементов, раздутых в адаптере, поэтому вы получите все представление для элементов, видимых на экране устройства, в противном случае - null. поэтому попробуйте просмотреть только видимые элементы и обработать NullPointerException, вы можете сделать чек:

     View v = mListView.getChildAt(i);
     if(v!=null){
       // your code
     }

Ответ 7

попробуйте этот

@Override
public boolean onOptionsItemSelected(MenuItem item) {
if(item.getItemId()==R.id.add)
{
ArrayList<String> scho = new ArrayList<String>();
    EditText et;
    if (mListView.getChildCount() > 0) {
    for (int i = 0; i < mListView.getChildCount(); i++) {
       // if your view statrts with relative layout then 
         RelativeLayout rl=(RelativeLayout)mListView.getChildAt(i);
   // else 
         yourlayout lay =(yourlayout)mListView.getChildAt(i);

         EditText et=(EditText)lay.getChildAt(your edit text positin in lay)

        //  main thing is we have to follow chain logic to find out the EditText position

        System.out.println(et.getText().toString());
    }
    }
 }
return super.onOptionsItemSelected(item);

}