问题
I'm trying to get data from EditText which is in my Listview. I saw a lot of similar questions & got a solution. But it throws an NPE in my Implementation.
So please guide me to fix this issue.
Adapter
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);
}
UPDATE using TextWatcher
Now i can store the value of the edittext in a Array. But when the listview is scrolled. The values are changed to the intial values.
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
Entering Data
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
While Scrolling
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
While Reentering value after Scrolling
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:
The way I would try first would be to add a TextChangedListener to the holder.marks, or you could add a button to save new value entered into the EditText.
When the text changes, I'd change the values in the list. Without this you will lose the data user when the list is scrolled as this line:
holder.marks.setText(list.get(position).get("STUDENT_MARK"), TextView.BufferType.EDITABLE);
will re-write the studend mark that was originally in the list.
Edit: I'm putting the Adapter code I found in the link in case it becomes unavailable in the future.
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;
}
}
New Edit:
Remove your GenericTextWatcher and use this instead. When I used your TextWatcher implementation it didn't work, I changed it like this and this works for me.
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:
You need to remove TextWatcher from edittext before you set text in it
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:
The reason you're getting a NPE is probably because your getItem is returning null.
@Override
public Object getItem(int arg0) {
return null;
}
You need to return the particular position in your Collection(Arraylist)
@Override
public Object getItem(int arg0) {
return list.get(arg0);
}
回答4:
Replace this :
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());
}
With this :
if (et.getText().toString()) { // check if the text is null
scho.add(et.getText().toString());
Log.e("SCH", et.getText().toString());
}
回答5:
Method you are using:
v = mListView.getChildAt(i);
belongs to ViewGroup superclass and is going to return only currently visible items in your ListView (because they are recycled and there is no reason to keep all of them in memory). Try to set OnClickListener inside getView() method of adapter:
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);
}
};
}
Please note, that creating new instance of OnClickListener for each item is usually not necessary and will cause some overhead. You can use single OnClickListener and tags to distinguish items.
Alternatively, you can use ListView's build in listener:
https://developer.android.com/reference/android/widget/AdapterView.OnItemClickListener.html
回答6:
Listview's getChildAt(i) only returns value for Visible Items on Device not for all items inflated in Adapter so you will get all the view for items visible on screen of a device otherwise null. so try to fetch only visible items view's and to handle NullPointerException you can make a check :
View v = mListView.getChildAt(i);
if(v!=null){
// your code
}
回答7:
try this one
@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);
}
来源:https://stackoverflow.com/questions/39166669/cant-get-values-from-listviews-edittext