空指针异常 - BaseAdapter notifyDataSetChanged
Null Pointer Exception - BaseAdapter notifyDataSetChanged
我正在尝试实施 Filterable ListView
但得到 NPE
:
08-13 11:34:20.980: E/AndroidRuntime(31796): FATAL EXCEPTION: main
08-13 11:34:20.980: E/AndroidRuntime(31796): java.lang.NullPointerException
08-13 11:34:20.980: E/AndroidRuntime(31796): at com.wingnity.jsonparsingtutorial.ActorsActivity$ActorAdapter.getCount(ActorsActivity.java:252)
08-13 11:34:20.980: E/AndroidRuntime(31796): at android.widget.AdapterView$AdapterDataSetObserver.onChanged(AdapterView.java:804)
08-13 11:34:20.980: E/AndroidRuntime(31796): at android.widget.AbsListView$AdapterDataSetObserver.onChanged(AbsListView.java:6545)
08-13 11:34:20.980: E/AndroidRuntime(31796): at android.database.DataSetObservable.notifyChanged(DataSetObservable.java:37)
08-13 11:34:20.980: E/AndroidRuntime(31796): at android.widget.BaseAdapter.notifyDataSetChanged(BaseAdapter.java:50)
08-13 11:34:20.980: E/AndroidRuntime(31796): at com.wingnity.jsonparsingtutorial.ActorsActivity$ActorAdapter$ItemFilter.publishResults(ActorsActivity.java:237)
08-13 11:34:20.980: E/AndroidRuntime(31796): at android.widget.Filter$ResultsHandler.handleMessage(Filter.java:282)
08-13 11:34:20.980: E/AndroidRuntime(31796): at android.os.Handler.dispatchMessage(Handler.java:99)
08-13 11:34:20.980: E/AndroidRuntime(31796): at android.os.Looper.loop(Looper.java:137)
08-13 11:34:20.980: E/AndroidRuntime(31796): at android.app.ActivityThread.main(ActivityThread.java:4921)
08-13 11:34:20.980: E/AndroidRuntime(31796): at java.lang.reflect.Method.invokeNative(Native Method)
08-13 11:34:20.980: E/AndroidRuntime(31796): at java.lang.reflect.Method.invoke(Method.java:511)
08-13 11:34:20.980: E/AndroidRuntime(31796): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1036)
08-13 11:34:20.980: E/AndroidRuntime(31796): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:803)
08-13 11:34:20.980: E/AndroidRuntime(31796): at dalvik.system.NativeStart.main(Native Method)
这是我面临的问题:
@Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
actorsList = (ArrayList<Actors>) results.values; // Type safety: Unchecked cast from Object to ArrayList<Actors>
notifyDataSetChanged();
}
我正在向 ListView 中获取数据,但在向 EditText 中输入文本时遇到此错误...
Activity代码:
public class ActorsActivity extends Activity {
ArrayList<Actors> actorsList;
ActorAdapter adapter;
ListView listView;
EditText editSearch;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editSearch = (EditText) findViewById(R.id.editSearch);
listView = (ListView)findViewById(R.id.list);
actorsList = new ArrayList<Actors>();
new JSONAsyncTask().execute("http://microblogging.wingnity.com/JSONParsingTutorial/jsonActors");
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position,
long id) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), actorsList.get(position).getName(), Toast.LENGTH_LONG).show();
}
});
editSearch.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// TODO Auto-generated method stub
adapter.getFilter().filter(s);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
@Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
}
});
}
class JSONAsyncTask extends AsyncTask<String, Void, Boolean> {
ProgressDialog dialog;
@Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new ProgressDialog(ActorsActivity.this);
dialog.setMessage("Loading, please wait");
dialog.setTitle("Connecting server");
dialog.show();
dialog.setCancelable(false);
}
@Override
protected Boolean doInBackground(String... urls) {
try {
//------------------>>
HttpGet httppost = new HttpGet(urls[0]);
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = httpclient.execute(httppost);
// StatusLine stat = response.getStatusLine();
int status = response.getStatusLine().getStatusCode();
if (status == 200) {
HttpEntity entity = response.getEntity();
String data = EntityUtils.toString(entity);
JSONObject jsono = new JSONObject(data);
JSONArray jarray = jsono.getJSONArray("actors");
for (int i = 0; i < jarray.length(); i++) {
JSONObject object = jarray.getJSONObject(i);
Actors actor = new Actors();
actor.setName(object.getString("name"));
actor.setCountry(object.getString("country"));
actorsList.add(actor);
}
return true;
}
//------------------>>
} catch (ParseException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return false;
}
protected void onPostExecute(Boolean result) {
dialog.cancel();
adapter = new ActorAdapter(getApplicationContext(), R.layout.row, actorsList);
listView.setAdapter(adapter);
adapter.notifyDataSetChanged();
if(result == false)
Toast.makeText(getApplicationContext(), "Unable to fetch data from server", Toast.LENGTH_LONG).show();
}
}
public class ActorAdapter extends BaseAdapter {
LayoutInflater inflater;
int Resource;
ViewHolder holder;
private ItemFilter itemFilter;
ArrayList<Actors> filteredItems;
public ActorAdapter(Context context, int resource, ArrayList<Actors> arrayList) {
inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
Resource = resource;
actorsList = arrayList;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (view == null) {
holder = new ViewHolder();
view = inflater.inflate(Resource, null);
holder.tvName = (TextView) view.findViewById(R.id.tvName);
holder.tvCountry = (TextView) view.findViewById(R.id.tvCountry);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
holder.tvName.setText(actorsList.get(position).getName());
holder.tvCountry.setText(actorsList.get(position).getCountry());
return view;
}
class ViewHolder {
public TextView tvName;
public TextView tvCountry;
}
private class ItemFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (constraint != null && constraint.length() > 0) {
ArrayList<Actors> filterList = new ArrayList<Actors>();
for (int i = 0; i < filteredItems.size(); i++) {
Actors actors = filteredItems.get(i);
String name = actors.getName().toUpperCase();
String country = actors.getCountry().toUpperCase();
if (name.contains(constraint.toString().toUpperCase()) || country.contains(constraint.toString().toUpperCase())) {
filterList.add(actors);
}
}
results.count = filterList.size();
results.values = filterList;
} else {
results.count = filteredItems.size();
results.values = filteredItems;
}
return results;
}
@Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
actorsList = (ArrayList<Actors>) results.values; // Type safety: Unchecked cast from Object to ArrayList<Actors>
notifyDataSetChanged();
}
}
public Filter getFilter() {
if (itemFilter == null) {
itemFilter = new ItemFilter();
}
return itemFilter;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return actorsList.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return actorsList.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
}
}
那么我该如何解决这个问题?我不明白我为什么会遇到这个问题。
异常是因为您试图从适配器内部更改显示值的列表。构建视图时,适配器找不到要通知的某些值并导致 NullPointerException。尝试在适配器外过滤您的列表。您可以以面向对象的方式在他自己的 class 中独立于适配器实现过滤器。因此,在文本侦听器中,您可以在单独的步骤中执行过滤器,第二步应该是将值分配给您的 actorList,第三步是通知适配器。应该是这样的
editSearch.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
//change the values, DO NOT create new because the reference will change
actorsList = myFilter.filter(s); //assign the filtered values, myFilter could be static function also
adapter.notifyDataSetChanged();
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
@Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
}
});
你还没有初始化 filteredItems
这就是你在 publishResults()
函数中得到 NPE
的原因。您必须先在构造函数中初始化
public ActorAdapter(Context context, int resource, ArrayList<Actors> arrayList) {
// your code
actorsList = arrayList;
filteredItems=arrayList; //initially show all items
}
现在您必须在所有其他功能(如 getCount(), getView()
...等)中使用 filteredItems
代替 actorsList
,以便您的列表视图仅显示过滤后的项目并在 performFiltering()
改变
for (int i = 0; i < filteredItems.size(); i++)
到
for (int i = 0; i < actorsList .size(); i++)
同时删除 adapter.notifyDataSetChanged();
,因为在将 Arraylist 分配给适配器后您没有对其进行任何更改。
我正在尝试实施 Filterable ListView
但得到 NPE
:
08-13 11:34:20.980: E/AndroidRuntime(31796): FATAL EXCEPTION: main
08-13 11:34:20.980: E/AndroidRuntime(31796): java.lang.NullPointerException
08-13 11:34:20.980: E/AndroidRuntime(31796): at com.wingnity.jsonparsingtutorial.ActorsActivity$ActorAdapter.getCount(ActorsActivity.java:252)
08-13 11:34:20.980: E/AndroidRuntime(31796): at android.widget.AdapterView$AdapterDataSetObserver.onChanged(AdapterView.java:804)
08-13 11:34:20.980: E/AndroidRuntime(31796): at android.widget.AbsListView$AdapterDataSetObserver.onChanged(AbsListView.java:6545)
08-13 11:34:20.980: E/AndroidRuntime(31796): at android.database.DataSetObservable.notifyChanged(DataSetObservable.java:37)
08-13 11:34:20.980: E/AndroidRuntime(31796): at android.widget.BaseAdapter.notifyDataSetChanged(BaseAdapter.java:50)
08-13 11:34:20.980: E/AndroidRuntime(31796): at com.wingnity.jsonparsingtutorial.ActorsActivity$ActorAdapter$ItemFilter.publishResults(ActorsActivity.java:237)
08-13 11:34:20.980: E/AndroidRuntime(31796): at android.widget.Filter$ResultsHandler.handleMessage(Filter.java:282)
08-13 11:34:20.980: E/AndroidRuntime(31796): at android.os.Handler.dispatchMessage(Handler.java:99)
08-13 11:34:20.980: E/AndroidRuntime(31796): at android.os.Looper.loop(Looper.java:137)
08-13 11:34:20.980: E/AndroidRuntime(31796): at android.app.ActivityThread.main(ActivityThread.java:4921)
08-13 11:34:20.980: E/AndroidRuntime(31796): at java.lang.reflect.Method.invokeNative(Native Method)
08-13 11:34:20.980: E/AndroidRuntime(31796): at java.lang.reflect.Method.invoke(Method.java:511)
08-13 11:34:20.980: E/AndroidRuntime(31796): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1036)
08-13 11:34:20.980: E/AndroidRuntime(31796): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:803)
08-13 11:34:20.980: E/AndroidRuntime(31796): at dalvik.system.NativeStart.main(Native Method)
这是我面临的问题:
@Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
actorsList = (ArrayList<Actors>) results.values; // Type safety: Unchecked cast from Object to ArrayList<Actors>
notifyDataSetChanged();
}
我正在向 ListView 中获取数据,但在向 EditText 中输入文本时遇到此错误...
Activity代码:
public class ActorsActivity extends Activity {
ArrayList<Actors> actorsList;
ActorAdapter adapter;
ListView listView;
EditText editSearch;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editSearch = (EditText) findViewById(R.id.editSearch);
listView = (ListView)findViewById(R.id.list);
actorsList = new ArrayList<Actors>();
new JSONAsyncTask().execute("http://microblogging.wingnity.com/JSONParsingTutorial/jsonActors");
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position,
long id) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), actorsList.get(position).getName(), Toast.LENGTH_LONG).show();
}
});
editSearch.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// TODO Auto-generated method stub
adapter.getFilter().filter(s);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
@Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
}
});
}
class JSONAsyncTask extends AsyncTask<String, Void, Boolean> {
ProgressDialog dialog;
@Override
protected void onPreExecute() {
super.onPreExecute();
dialog = new ProgressDialog(ActorsActivity.this);
dialog.setMessage("Loading, please wait");
dialog.setTitle("Connecting server");
dialog.show();
dialog.setCancelable(false);
}
@Override
protected Boolean doInBackground(String... urls) {
try {
//------------------>>
HttpGet httppost = new HttpGet(urls[0]);
HttpClient httpclient = new DefaultHttpClient();
HttpResponse response = httpclient.execute(httppost);
// StatusLine stat = response.getStatusLine();
int status = response.getStatusLine().getStatusCode();
if (status == 200) {
HttpEntity entity = response.getEntity();
String data = EntityUtils.toString(entity);
JSONObject jsono = new JSONObject(data);
JSONArray jarray = jsono.getJSONArray("actors");
for (int i = 0; i < jarray.length(); i++) {
JSONObject object = jarray.getJSONObject(i);
Actors actor = new Actors();
actor.setName(object.getString("name"));
actor.setCountry(object.getString("country"));
actorsList.add(actor);
}
return true;
}
//------------------>>
} catch (ParseException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return false;
}
protected void onPostExecute(Boolean result) {
dialog.cancel();
adapter = new ActorAdapter(getApplicationContext(), R.layout.row, actorsList);
listView.setAdapter(adapter);
adapter.notifyDataSetChanged();
if(result == false)
Toast.makeText(getApplicationContext(), "Unable to fetch data from server", Toast.LENGTH_LONG).show();
}
}
public class ActorAdapter extends BaseAdapter {
LayoutInflater inflater;
int Resource;
ViewHolder holder;
private ItemFilter itemFilter;
ArrayList<Actors> filteredItems;
public ActorAdapter(Context context, int resource, ArrayList<Actors> arrayList) {
inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
Resource = resource;
actorsList = arrayList;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (view == null) {
holder = new ViewHolder();
view = inflater.inflate(Resource, null);
holder.tvName = (TextView) view.findViewById(R.id.tvName);
holder.tvCountry = (TextView) view.findViewById(R.id.tvCountry);
view.setTag(holder);
} else {
holder = (ViewHolder) view.getTag();
}
holder.tvName.setText(actorsList.get(position).getName());
holder.tvCountry.setText(actorsList.get(position).getCountry());
return view;
}
class ViewHolder {
public TextView tvName;
public TextView tvCountry;
}
private class ItemFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults results = new FilterResults();
if (constraint != null && constraint.length() > 0) {
ArrayList<Actors> filterList = new ArrayList<Actors>();
for (int i = 0; i < filteredItems.size(); i++) {
Actors actors = filteredItems.get(i);
String name = actors.getName().toUpperCase();
String country = actors.getCountry().toUpperCase();
if (name.contains(constraint.toString().toUpperCase()) || country.contains(constraint.toString().toUpperCase())) {
filterList.add(actors);
}
}
results.count = filterList.size();
results.values = filterList;
} else {
results.count = filteredItems.size();
results.values = filteredItems;
}
return results;
}
@Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
actorsList = (ArrayList<Actors>) results.values; // Type safety: Unchecked cast from Object to ArrayList<Actors>
notifyDataSetChanged();
}
}
public Filter getFilter() {
if (itemFilter == null) {
itemFilter = new ItemFilter();
}
return itemFilter;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return actorsList.size();
}
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return actorsList.get(position);
}
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
}
}
那么我该如何解决这个问题?我不明白我为什么会遇到这个问题。
异常是因为您试图从适配器内部更改显示值的列表。构建视图时,适配器找不到要通知的某些值并导致 NullPointerException。尝试在适配器外过滤您的列表。您可以以面向对象的方式在他自己的 class 中独立于适配器实现过滤器。因此,在文本侦听器中,您可以在单独的步骤中执行过滤器,第二步应该是将值分配给您的 actorList,第三步是通知适配器。应该是这样的
editSearch.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
//change the values, DO NOT create new because the reference will change
actorsList = myFilter.filter(s); //assign the filtered values, myFilter could be static function also
adapter.notifyDataSetChanged();
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
@Override
public void afterTextChanged(Editable s) {
// TODO Auto-generated method stub
}
});
你还没有初始化 filteredItems
这就是你在 publishResults()
函数中得到 NPE
的原因。您必须先在构造函数中初始化
public ActorAdapter(Context context, int resource, ArrayList<Actors> arrayList) {
// your code
actorsList = arrayList;
filteredItems=arrayList; //initially show all items
}
现在您必须在所有其他功能(如 getCount(), getView()
...等)中使用 filteredItems
代替 actorsList
,以便您的列表视图仅显示过滤后的项目并在 performFiltering()
改变
for (int i = 0; i < filteredItems.size(); i++)
到
for (int i = 0; i < actorsList .size(); i++)
同时删除 adapter.notifyDataSetChanged();
,因为在将 Arraylist 分配给适配器后您没有对其进行任何更改。