【问题标题】:Null Pointer Exception - BaseAdapter notifyDataSetChanged空指针异常 - BaseAdapter notifyDataSetChanged
【发布时间】:2015-11-05 23:28:15
【问题描述】:

我正在尝试实现 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 时遇到此错误...

活动代码:

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;
    }
  }

}

那么我该如何解决这个问题?我不明白我为什么要面对这个问题。

【问题讨论】:

  • 检查actorsList size > 0 or != null 一些东西,因为你在那里没有得到任何价值
  • 我正在将数据输入列表视图.. 但在搜索字段上写入文本时遇到此错误
  • filteredItems 为空,因为我没有看到任何 filteredItems = ...
  • 那么我该怎么做才能解决这个问题? @pskink
  • 我不知道您想要什么:根据您输入的内容或其他任何内容过滤现有列表或显示来自某些 Web api 的项目?

标签: android listview arraylist filter baseadapter


【解决方案1】:

异常是因为您试图从适配器内部更改显示值的列表。构建视图时,适配器找不到一些要通知的值并导致 NullPointerException。尝试在适配器之外过滤您的列表。您可以以面向对象的方式在他自己的类中独立于适配器实现过滤器。因此,在文本侦听器中,您可以在单独的步骤中进行过滤,第二步应该是将值分配给您的 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

    }
});

【讨论】:

    【解决方案2】:

    你还没有初始化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 分配给适配器后,您没有对其进行任何更改。

    【讨论】:

    • 感谢filteredItems = arrayList; //最初显示所有对我有用的项目。
    • 我必须在列表视图中显示 youtube 播放列表。你能帮我吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-12
    相关资源
    最近更新 更多