Android 自定义Listadapter可筛选无结果

Android 自定义Listadapter可筛选无结果,android,filter,arraylist,hashmap,custom-adapter,Android,Filter,Arraylist,Hashmap,Custom Adapter,我正在为这个问题挣扎一段时间。我正在用edittext建立一个可过滤列表。列表最初填充得很好,但一旦我在edittext字段中键入了一些内容。整个列表将消失,并且不会返回任何结果。以下是我的代码 注意:我的代码主要基于sacoskun的 ThreedListViewActivity.java public class ThreedListViewActivity extends ActionBarActivity { // All static variables static final St

我正在为这个问题挣扎一段时间。我正在用edittext建立一个可过滤列表。列表最初填充得很好,但一旦我在edittext字段中键入了一些内容。整个列表将消失,并且不会返回任何结果。以下是我的代码

注意:我的代码主要基于sacoskun的

ThreedListViewActivity.java

public class ThreedListViewActivity extends ActionBarActivity
{
// All static variables
static final String URL = "http://api.androidhive.info/music/music.xml";
// XML node keys
static final String KEY_SONG = "song"; // parent node
static final String KEY_ID = "id";
static final String KEY_TITLE = "title";
static final String KEY_ARTIST = "artist";
static final String KEY_DURATION = "duration";
static final String KEY_THUMB_URL = "thumb_url";

ListView list;
ThreedListAdapterFilterable adapter;
ArrayList<HashMap<String, String>> songsList = new ArrayList<HashMap<String, String>>();
EditText filterText = null;

@Override
public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.threed_listview);
    setTitle(R.string.view_3d);
    list=(ListView)findViewById(R.id.list);
    adapter = new ThreedListAdapterFilterable(this, songsList);

    new MyAsyncTask().execute();

    filterText = (EditText) findViewById(R.id.search_box);
    filterText.addTextChangedListener(filterTextWatcher);

    // Click event for single list row
    list.setOnItemClickListener(new OnItemClickListener() {

        public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {

        }
    });
}

private TextWatcher filterTextWatcher = new TextWatcher() {

    public void afterTextChanged(Editable s) {
    }

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

    public void onTextChanged(CharSequence s, int start, int before,
            int count) {
        adapter.getFilter().filter(s.toString());
    }

};

public class MyAsyncTask extends AsyncTask<Void,Void,Void>{

    private final ProgressDialog dialog=new ProgressDialog(ThreedListViewActivity.this);

    @Override
    protected Void doInBackground(Void... params) {

        XMLParser parser = new XMLParser();
        String xml = parser.getXmlFromUrl(URL); // getting XML from URL
        Document doc = parser.getDomElement(xml); // getting DOM element

        NodeList nl = doc.getElementsByTagName(KEY_SONG);
        // looping through all song nodes <song>
        for (int i = 0; i < nl.getLength(); i++) {
            // creating new HashMap
            HashMap<String, String> map = new HashMap<String, String>();
            Element e = (Element) nl.item(i);
            // adding each child node to HashMap key => value
            map.put(KEY_ID, parser.getValue(e, KEY_ID));
            map.put(KEY_TITLE, parser.getValue(e, KEY_TITLE));
            map.put(KEY_ARTIST, parser.getValue(e, KEY_ARTIST));
            map.put(KEY_DURATION, parser.getValue(e, KEY_DURATION));
            map.put(KEY_THUMB_URL, parser.getValue(e, KEY_THUMB_URL));

            // adding HashList to ArrayList
            songsList.add(map);
        }
        return null;
    }

    @Override
    protected void onPreExecute()
    {
        dialog.setMessage("Loading ...");
        dialog.show();
        dialog.setCancelable(false);
    }

    @Override
    protected void onPostExecute(Void result)
    {
        if(dialog.isShowing() == true)
        {
            dialog.dismiss();
        }
         // Getting adapter by passing xml data ArrayList

        list.setAdapter(adapter);

    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {

    MenuInflater inflater = getMenuInflater();

    inflater.inflate(R.menu.action_items, menu);

    return true;
}

}
ThreedListAdapterFilterable.java

public class ThreedListAdapterFilterable extends BaseAdapter implements Filterable {

private Activity activity;
ArrayList<HashMap<String, String>> mDataShown;
ArrayList<HashMap<String, String>> mAllData;
private static LayoutInflater inflater=null;
public ImageLoader imageLoader; 

public ThreedListAdapterFilterable(Activity a, ArrayList<HashMap<String, String>> d) {
    activity = a;
    mDataShown= (ArrayList<HashMap<String, String>>) d;
    mAllData = (ArrayList<HashMap<String, String>>) mDataShown.clone();
    inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    imageLoader=new ImageLoader(activity.getApplicationContext());
}

public int getCount() {
    return mDataShown.size();
}

public Object getItem(int position) {
    return position;
}

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

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

        View vi=convertView;
        if(convertView==null)
            vi = inflater.inflate(R.layout.threed_listrow, null);

        TextView title = (TextView)vi.findViewById(R.id.title); // title
        TextView artist = (TextView)vi.findViewById(R.id.artist); // artist name
        TextView duration = (TextView)vi.findViewById(R.id.duration); // duration
        ImageView thumb_image=(ImageView)vi.findViewById(R.id.list_image); // thumb image

        HashMap<String, String> song = new HashMap<String, String>();
        song = mDataShown.get(position);

        // Setting all values in listview
        title.setText(song.get(ThreedListViewActivity.KEY_TITLE));
        artist.setText(song.get(ThreedListViewActivity.KEY_ARTIST));
        duration.setText(song.get(ThreedListViewActivity.KEY_DURATION));
        imageLoader.DisplayImage(song.get(ThreedListViewActivity.KEY_THUMB_URL), thumb_image);
        return vi;
}

public Filter getFilter() {
     Filter nameFilter = new Filter() {

            @SuppressWarnings("unchecked")
            @Override
           public String convertResultToString(Object resultValue) {
                return ((HashMap<String, String>)(resultValue)).get(ThreedListViewActivity.KEY_TITLE);
           }

            @Override
            protected FilterResults performFiltering(CharSequence s) {

                 if(s != null)
                    {
                     ArrayList<HashMap<String, String>> tmpAllData = mAllData;
                     ArrayList<HashMap<String, String>> tmpDataShown = mDataShown;
                     tmpDataShown.clear();  
                     for(int i = 0; i < tmpAllData.size(); i++)
                     {
                      if(tmpAllData.get(i).get(ThreedListViewActivity.KEY_TITLE).toLowerCase().startsWith(s.toString().toLowerCase()))
                      {
                       tmpDataShown.add(tmpAllData.get(i));
                      }
                     }

                     FilterResults filterResults = new FilterResults();
                     filterResults.values = tmpDataShown;
                     filterResults.count = tmpDataShown.size();
                     return filterResults;
                    }
                    else
                    {
                     return new FilterResults();
                    }
            }

            @Override
               protected void publishResults(CharSequence s,
                 FilterResults results) {
                if(results != null && results.count > 0)
                {
                 notifyDataSetChanged();
                }
               }};
               return nameFilter;
    }
}
编辑: 这是一个更新的适配器,将筛选我的列表。但是,当我将输入文本中的文本退格时,它不会更新我的列表

public class ProjectListAdapter extends BaseAdapter implements Filterable{

private Activity activity;
ArrayList<HashMap<String, String>> mDataShown;
ArrayList<HashMap<String, String>> mAllData;
private static LayoutInflater inflater=null;
public ImageLoader imageLoader; 
HashMap<String, String> song = new HashMap<String, String>();
ArrayList<HashMap<String, String>> filteredItems;

public ProjectListAdapter(Activity a, ArrayList<HashMap<String, String>> d) {

    activity = a;
    mDataShown= (ArrayList<HashMap<String, String>>) d;
    mAllData = (ArrayList<HashMap<String, String>>) mDataShown.clone();
    filteredItems = mDataShown;
    inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    imageLoader=new ImageLoader(activity.getApplicationContext());
}

@Override
public int getCount() {
    // TODO Auto-generated method stub
    return mDataShown.size();
}

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

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

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

    View vi;

    if(convertView==null){
        vi=new View(activity);
        vi = inflater.inflate(R.layout.recents_listrow, null);
    }else{
        vi = (View)convertView;
    }
    TextView title = (TextView)vi.findViewById(R.id.title); // title
    TextView artist = (TextView)vi.findViewById(R.id.company); // artist name
    ImageView thumb_image=(ImageView)vi.findViewById(R.id.list_image); // thumb image
    title.setText(filteredItems.get(position).get(RecentsFragment.KEY_TITLE));
    artist.setText(filteredItems.get(position).get(RecentsFragment.KEY_COMPANY));
    imageLoader.DisplayImage(filteredItems.get(position).get(RecentsFragment.KEY_THUMB_URL), thumb_image);

    return vi;

}

public Filter getFilter() {
     Filter nameFilter = new Filter() {

            @Override
            protected FilterResults performFiltering(CharSequence constraint) {


                if(constraint != null && constraint.toString().length() > 0) {
                    constraint = constraint.toString().toUpperCase();
                    ArrayList<HashMap<String, String>> filt = mDataShown;
                    ArrayList<HashMap<String, String>> tmpItems = mAllData;
                    filt.clear();
                                    for(int i = 0; i < tmpItems.size(); i++) {

                                      if(tmpItems.get(i).get(RecentsFragment.KEY_TITLE).toLowerCase().startsWith(constraint.toString().toLowerCase()))
                                      {
                                          filt.add(tmpItems.get(i));
                                      }
                                    }
                                    FilterResults filterResults = new FilterResults();
                                    filterResults.count = filt.size();
                                    filterResults.values = filt;
                                    return filterResults;
                               }else{
                                   return new FilterResults();
                                  }

            }

            @Override
               protected void publishResults(CharSequence constraint,
                 FilterResults results) {

                mDataShown = (ArrayList<HashMap<String, String>>)results.values;

                if (results.count > 0) {
                    notifyDataSetChanged();
                } else {
                    notifyDataSetInvalidated();
                }

               }
            };

               return nameFilter;
 }

}
我正在尝试实现的列表片段:RecentsFragment

public class RecentsFragment extends ListFragment {

// All static variables
static final String URL = "http://www.sundancepost.com/ivue/projects.xml";
// XML node keys
static final String KEY_PROJECT = "project"; // parent node
static final String KEY_TITLE = "title";
static final String KEY_COMPANY = "company";
static final String KEY_THUMB_URL = "thumb_url";
int mCurCheckPosition = 0;

ListView list;
ProjectListAdapter adapter;
ArrayList<HashMap<String, String>> projectsList = new ArrayList<HashMap<String, String>>();
EditText filterText = null;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setRetainInstance(true);

}

 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     View view = inflater.inflate(R.layout.recents_list, container, false);
     list = (ListView)view.findViewById(android.R.id.list);
     filterText = (EditText)view.findViewById(R.id.filter_box);

     return view;
 }

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    if(null == savedInstanceState){

        ConnectivityManager cMgr = (ConnectivityManager)getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
        if (cMgr.getActiveNetworkInfo() != null && cMgr.getActiveNetworkInfo().isConnectedOrConnecting()) {

            new MyAsyncTask().execute();

        } else {
             AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
             builder.setMessage("Please check your internet connection");
             builder.setTitle("Failed to download resources");
             builder.setCancelable(false);
             builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                       public void onClick(DialogInterface dialog, int id) {
                           return;
                       }
                   });
            AlertDialog alert = builder.create();
            alert.show();
        }
    }

    adapter = new ProjectListAdapter(getActivity(), projectsList);
    list.requestFocus();
    list.setTextFilterEnabled(true);
    filterText.addTextChangedListener(filterTextWatcher);

    list.setOnItemClickListener(new OnItemClickListener() {

        public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {

            Intent intent = new Intent(getActivity(), DetailsActivity.class);
            intent.putExtra("title",projectsList.get(position).get(KEY_TITLE));
            intent.putExtra("company", projectsList.get(position).get(KEY_COMPANY));

            startActivity(intent);

        }
    });

}

@Override
public void onSaveInstanceState(Bundle outState){
    super.onSaveInstanceState(outState);
    outState.putInt("workaround", mCurCheckPosition);
}

private TextWatcher filterTextWatcher = new TextWatcher() {

    public void afterTextChanged(Editable s) {
    }

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

    public void onTextChanged(CharSequence s, int start, int before,
            int count) {
        adapter.getFilter().filter(s);
    }

};

@Override
public void onDestroy() {
    super.onDestroy();
    filterText.removeTextChangedListener(filterTextWatcher);
}

public class MyAsyncTask extends AsyncTask<Void,Void,Void>{

    private final ProgressDialog recents_dialog = new ProgressDialog(getActivity());

    @Override
    protected Void doInBackground(Void... params) {

        XMLParser parser = new XMLParser();
        String xml = parser.getXmlFromUrl(URL); // getting XML from URL
        Document doc = parser.getDomElement(xml); // getting DOM element

        NodeList nl = doc.getElementsByTagName(KEY_PROJECT);
        // looping through all song nodes <song>
        for (int i = 0; i < nl.getLength(); i++) {
            // creating new HashMap
            HashMap<String, String> map = new HashMap<String, String>();
            Element e = (Element) nl.item(i);
            // adding each child node to HashMap key => value
            map.put(KEY_TITLE, parser.getValue(e, KEY_TITLE));
            map.put(KEY_COMPANY, parser.getValue(e, KEY_COMPANY));
            map.put(KEY_THUMB_URL, parser.getValue(e, KEY_THUMB_URL));

            // adding HashList to ArrayList
            projectsList.add(map);
        }
        return null;
    }

    @Override
    protected void onPreExecute()
    {
        projectsList.clear();
        recents_dialog.setMessage("Loading ...");
        recents_dialog.show();
        recents_dialog.setCancelable(false);
    }

    @Override
    protected void onPostExecute(Void result)
    {
        if(recents_dialog.isShowing() == true)
        {
            recents_dialog.dismiss();
        }
         // Getting adapter by passing xml data ArrayList

        list.setAdapter(adapter);

    }
}


}

公共类FriendsStactivity扩展了活动实现OnClickListener{ 私人经理人; 静态最终字符串键\u ID=ID; 静态最终字符串键\u NAME=NAME; 静态最终串键\u已安装=已安装; 静态最终字符串KEY\u THUMB\u URL=picture; 受保护的列表视图好友列表; 受保护的静态JSONArray JSONArray; Friendslistatadapter适配器; ArrayList>friendslist; 编辑文本过滤器文本; 字符串响应; 按钮播放,邀请

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.friends_list);
    friendslist = new ArrayList<HashMap<String, String>>();
    mHandler = new Handler();
    ActionBar actionBar = (ActionBar) findViewById(R.id.actionbar);
    actionBar.setTitle("Facebook Friends");
    actionBar.setHomeAction(new IntentAction(this, TruthorDareActivity
            .createIntent(this), R.drawable.ic_home));
    friendsList = (ListView) findViewById(R.id.friendsList);
    filterText = (EditText) findViewById(R.id.searchBox);
    filterText.addTextChangedListener(filterTextWatcher);
    friendsList.setTextFilterEnabled(true);
    friendsList.requestFocus();
    play = (Button) findViewById(R.id.play);
    invite = (Button) findViewById(R.id.invite);
    play.setOnClickListener(this);
    invite.setOnClickListener(this);
    Bundle extras = getIntent().getExtras();
    apiResponse = extras.getString("API_RESPONSE");
    callPlayList();
}

@Override
public void onBackPressed() {
    super.onBackPressed();
    this.finish();
}

@Override
protected void onResume() {
    super.onResume();
    friendsList.requestFocus();
}

public void callPlayList() {
    try {
        jsonArray = new JSONObject(apiResponse).getJSONArray("data");
        for (int i = 0; i < jsonArray.length(); i++) {
            JSONObject json_data = jsonArray.getJSONObject(i);
            if (json_data.has("installed")
                    && json_data.getBoolean("installed") == true) {
                HashMap<String, String> map = new HashMap<String, String>();
                map.put(KEY_ID, json_data.getString("id"));
                map.put(KEY_NAME, json_data.getString("name"));
                map.put(KEY_THUMB_URL, json_data.getString("picture"));
                map.put(KEY_INSTALLED, json_data.getString("installed"));
                friendslist.add(map);
            }
        }

    } catch (JSONException e) {
        showToast("Error: " + e.getMessage());
        return;
    }
    adapter = new FriendsListAdapter(FriendsListActivity.this, friendslist);
    friendsList.setAdapter(adapter);

}

public void callInviteList() {
    try {
        jsonArray = new JSONObject(apiResponse).getJSONArray("data");
        for (int i = 0; i < jsonArray.length(); i++) {
            JSONObject json_data = jsonArray.getJSONObject(i);
            if (!json_data.has("installed")) {
                HashMap<String, String> map = new HashMap<String, String>();
                map.put(KEY_ID, json_data.getString("id"));
                map.put(KEY_NAME, json_data.getString("name"));
                map.put(KEY_THUMB_URL, json_data.getString("picture"));
                map.put(KEY_INSTALLED, "false");
                friendslist.add(map);
            }
        }

    } catch (JSONException e) {
        showToast("Error: " + e.getMessage());
        return;
    }
    adapter = new FriendsListAdapter(FriendsListActivity.this, friendslist);
    friendsList.setAdapter(adapter);
}

public void clearAdapter(String params) {
    friendslist.clear();
    adapter.notifyDataSetChanged();
    adapter.notifyDataSetInvalidated();
    if (params.equals("invite")) {
        callInviteList();
    } else {
        callPlayList();
    }

}

public class PostDialogListener extends BaseDialogListener {
    @Override
    public void onComplete(Bundle values) {
        final String postId = values.getString("post_id");
        if (postId != null) {
            showToast("Message posted on the wall.");
        } else {
            showToast("No message posted on the wall.");
        }
    }
}

public void showToast(final String msg) {
    mHandler.post(new Runnable() {
        @Override
        public void run() {
            Toast toast = Toast.makeText(FriendsListActivity.this, msg,
                    Toast.LENGTH_LONG);
            toast.show();
        }
    });
}

private TextWatcher filterTextWatcher = new TextWatcher() {

    public void afterTextChanged(Editable s) {
    }

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

    public void onTextChanged(CharSequence s, int start, int before,
            int count) {
        adapter.getFilter().filter(s);
    }

};

@Override
protected void onDestroy() {
    super.onDestroy();
    filterText.removeTextChangedListener(filterTextWatcher);
}

@Override
public void onClick(View v) {
    switch (v.getId()) {
    case R.id.play:
        clearAdapter("play");
        break;
    case R.id.invite:
        clearAdapter("invite");
        break;
    default:
        break;
    }

}
}

下一部分是我在单独的类文件中使用的适配器类


}

在getFilter方法中,尝试以下操作

@凌驾 受保护的void publishResultCharsSequence约束, FilterResults结果{

            mDataShown = (ArrayList<HashMap<String, String>>)results.values;
            ProjectListAdapter.this.setListData(mDataShown);
            ProjectListAdapter.this.notifyDataSetChanged();
        };

})

使用调试器。在适配器中放置一些断点。过滤器是否实际返回任何结果?是否调用过publishResults?我认为发布的结果不会传递到getView函数中。因此,该列表不会更新。谢谢你的提醒,@Christopherryi肯定会测试这个。谢谢你的作品@ParkerHi,@Parker..我想知道你在publishResults方法中把'data'变量应用在哪里?您是否也修改了getView方法?@Victor Yew。我在这里编辑了代码,因为我试图放回您的原始代码,但忘记了我使用的是数据而不是MDataShowed。如果你需要我发布更多,我会的。我修改了lazylist适配器类的模型,使这段代码可以工作。你现在应该使用MDataShowed而不是数据。嗯……我用MDataShowed替换了数据,就像你一样。最初,列表填充得很好,但当我开始在文本输入中键入内容时,它崩溃了。如果你能给我看更多的代码就太好了。谢谢。我更新了更多代码供您尝试。相信你的过滤代码中的s.toString是它崩溃的原因。嗨,谢谢你的回答。但是,setListData函数是继承的吗?不,它不是继承的,我已经创建了在自定义适配器中设置列表的方法。
            mDataShown = (ArrayList<HashMap<String, String>>)results.values;
            ProjectListAdapter.this.setListData(mDataShown);
            ProjectListAdapter.this.notifyDataSetChanged();
        };
public void afterTextChanged(Editable s) {
}

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

public void onTextChanged(CharSequence s, int start, int before,
        int count) {
    if(s.toString().equalsIgnoreCase(""))
    {
     adapter.setListData(projectListdata)
     adapter.notifyDataSetChanged();
    }
    else
     adapter.getFilter().filter(s);
}