2

I am having trouble with the SearchView in my app displaying incorrect ListView items.

If I type Name: ListView is displayed as expected

If I type Name1: I get entries 1-2

If I type Name 2-11: I get the entry for Name1


Here is a visual: Visual


As far as I cant tell, the code is fine but the application is not working as expected. Could somebody please point me in the right direction to fixing this?


The ListView is displayed with a custom array adapter from the following data:

[{"society_id":1,"name":"Name1","email":"Test@email1","description":"TestDes1"},
{"society_id":2,"name":"Name2","email":"Test@email2","description":"TestDes2"},
{"society_id":3,"name":"Name3","email":"Test@email3","description":"TestDes3"},...]

SocietySearch.java:

public class SocietySearch extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) { //TODO remember notifyDataSetChanged
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_society_search);

        List<Society> societies = new ArrayList<>();
        ServerRequests serverRequest1 = new ServerRequests(SocietySearch.this);
        serverRequest1.GetSocietyDataAsyncTask(societies, new GetSocietyCallback() {

            @Override
            public void done(final List<Society> societies) {
                ListView lv = (ListView) findViewById(R.id.ListView);
                List<ListViewItem> items = new ArrayList<>();
                for (final Society s : societies) {
                    items.add(new ListViewItem() {{
                        ThumbnailResource = R.drawable.test;
                        Title = s.socName;
                        Description = s.socDes;
                    }});
                }
                final CustomListViewAdapter adapter = new CustomListViewAdapter(SocietySearch.this, items, societies);
                lv.setAdapter(adapter);

                SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
                SearchView searchView = (SearchView) findViewById(R.id.search);
                searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
                searchView.setQueryHint("Search..");

                searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
                    @Override
                    public boolean onQueryTextSubmit(String query) {
                        return false;
                    }

                    @Override
                    public boolean onQueryTextChange(String newText) {
                        adapter.getFilter().filter(newText);
                        return false;
                    }
                });
            }
        });
    }

    public class ListViewItem {
        public int ThumbnailResource;
        public String Title;
        public String Description;
    }

CustomListViewAdapter.java:

public class CustomListViewAdapter extends ArrayAdapter {

    LayoutInflater inflater;
    List<SocietySearch.ListViewItem> items;

    public CustomListViewAdapter(Activity context, List<SocietySearch.ListViewItem> items, List<Society> societies) {

        super(context, R.layout.item_row, societies);

        this.items = items;
        this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        //Auto-generated method stub

        ListViewItem item = items.get(position);

        View vi = convertView;

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

        ImageView test = (ImageView) vi.findViewById(R.id.imgThumbnail);
        TextView txtTitle = (TextView) vi.findViewById(R.id.txtTitle);
        TextView txtSubTitle = (TextView) vi.findViewById(R.id.txtSubTitle);

        test.setImageResource(item.ThumbnailResource);
        txtTitle.setText(item.Title);
        txtSubTitle.setText(item.Description);


        return vi;
    }
}

Society.java:

public class Society {

    String socName, socEmail, socDes;
    int society_id;

    public Society(int society_id, String socName, String socEmail, String socDes) {

        this.society_id = society_id;
        this.socName = socName;
        this.socEmail = socEmail;
        this.socDes = socDes;

    }

    public String toString() {
        return socName;
    }
}

AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="k.unionapp">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".HomeScreenActivity"
            android:theme="@style/AppTheme.NoActionBar"></activity>
        <activity android:name=".SocietySearch"></activity>
    </application>
</manifest>
kmil
  • 243
  • 3
  • 13

2 Answers2

3

I believe you problem may be because you are holding onto the original list in memory, and binding your view off of that

ListViewItem item = items.get(position);

Instead, you may want to try getting the item from the adapter itself, since the underlying list is being changed by the Filter

ListViewItem item = this.getItem(position);
Brad
  • 513
  • 3
  • 8
2

You need to provide implementation of toString method in SocietySearch.ListViewItem class, which will return name of item.

public class ListViewItem {
    public int ThumbnailResource;
    public String Title;
    public String Description;

    @Override
    public String toString(){
        return Title;
    }
}

Default implementation of filter in ArrayAdapter uses this method to convert arbitrary item type into String before comparing it to search query. Also, default implementation - ArrayFilter - uses query string as prefix, FYI.


Also, as noted in other answer - don't hold onto original list in your constructor and getView method. Use getItem method of array adapter itself.

You also might want to change class declaration to include custom type of items instead of generic Object:

public class CustomListViewAdapter extends ArrayAdapter<SocietySearch.ListViewItem> {
weaknespase
  • 1,014
  • 8
  • 15