Android - 将搜索栏添加到自定义列表视图和简单适配器

Android - Adding search-bar to custom-list-view & simple adaptor

我尝试创建自定义 ListView 并使用 ArrayHashMap 填充值。 UI 显示正常:

但是只要在搜索框中输入任何内容,应用就会关闭并显示 Unfortunately app is stopped

我搜索了很多,但无法完成。

也许我尝试应用过滤器的方法有误?

代码如下:

public class MyCustomListView extends ListActivity {
    SimpleAdapter adapter;
    EditText inputSearch;

    static final ArrayList<HashMap<String,String>> list = new ArrayList<HashMap<String,String>>();
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.custom_list_view);
        inputSearch = (EditText) findViewById(R.id.search);

        ImageView si = (ImageView) findViewById(R.id.search_icon);
        si.setImageResource(R.drawable.blue_search);

        adapter = new SimpleAdapter(
                this,
                list,
                R.layout.custom_row_view,
                new String[] {"img","name","dob","anniversary"},
                new int[] {R.id.image,R.id.text1,R.id.text2, R.id.text3}
        );

        try{
            getItemFromXMLandPopulateList(this); // gets the complete list
        } catch (Exception e){
            Toast.makeText(this, "Error:\n" + e, Toast.LENGTH_LONG).show();
        }

        setListAdapter(adapter);

        // Capture Text in EditText
        inputSearch.addTextChangedListener(new TextWatcher() {
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                adapter.getFilter().filter(s);
            }

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

            @Override
            public void afterTextChanged(Editable s) {
            }
        });
    }

    private void getItemFromXMLandPopulateList(Activity activity) throws XmlPullParserException, IOException {
        Resources res = activity.getResources();
        XmlResourceParser xpp = res.getXml(R.xml.db);
        String id=null, name=null, dob=null, anniversary=null;
        xpp.next();
        int eventType = xpp.getEventType();

        while (eventType != XmlPullParser.END_DOCUMENT){
            switch(eventType){
                case XmlPullParser.START_TAG:
                    String tagname = xpp.getName();
                    if(tagname.equals("ID")){
                        eventType = xpp.next();
                        if (eventType == XmlPullParser.TEXT) {
                            id = xpp.getText();
                        }
                    } else if(tagname.equals("Name")){
                        eventType = xpp.next();
                        if (eventType == XmlPullParser.TEXT) {
                            name = xpp.getText();
                        }
                    } else if(tagname.equals("DOB")){
                        eventType = xpp.next();
                        if (eventType == XmlPullParser.TEXT) {
                            dob = xpp.getText();
                        }
                    } else if(tagname.equals("Anniversary")){
                        eventType = xpp.next();
                        if (eventType == XmlPullParser.TEXT) {
                            anniversary = xpp.getText();
                        }
                    }
                    break;
                case XmlPullParser.END_TAG:
                    if(xpp.getName().equals("F")){
                        // Adding 3 value hash to array-list
                        HashMap<String,String> temp = new HashMap<String,String>();
                        temp.put("img", Integer.toString(R.mipmap.profile));
                        temp.put("id", id);
                        temp.put("name", name);
                        temp.put("dob", dob);
                        temp.put("anniversary", anniversary);
                        list.add(temp);
                        // Clearing values for next set
                        id=""; name = ""; dob = ""; anniversary = "";
                    }
                    break;
                default:
                    break;
            }
            eventType = xpp.next();
        }
    }

    protected void onListItemClick(ListView l, View v, int position, long id) {
        super.onListItemClick(l, v, position, id);
        HashMap<String, String> item = (HashMap<String, String>) getListAdapter().getItem(position);
        String xmlFile = "r" + item.get("id");
        String name = item.get("name");
        //Toast.makeText(this, "Showing details of: " + name, Toast.LENGTH_LONG).show();

        Intent intent = new Intent(this, ShowDetails.class);
        intent.putExtra("xml", xmlFile);
        startActivity(intent);
    }
}

崩溃日志贴在下面,好像说 NullPointerException,但不确定如何解决。

I/ActivityManager( 1596): Displayed com.karthikhiraskar.samplesqlitedb/.MyCustomListView: +237ms
W/Filter  (10785): An exception occured during performFiltering()!
W/Filter  (10785): java.lang.NullPointerException
W/Filter  (10785):  at android.widget.SimpleAdapter$SimpleFilter.performFiltering(SimpleAdapter.java:354)
W/Filter  (10785):  at android.widget.Filter$RequestHandler.handleMessage(Filter.java:234)
W/Filter  (10785):  at android.os.Handler.dispatchMessage(Handler.java:102)
W/Filter  (10785):  at android.os.Looper.loop(Looper.java:136)
W/Filter  (10785):  at android.os.HandlerThread.run(HandlerThread.java:61)
I/LatinIME:LogUtils( 1692): Dictionary info: dictionary = contacts.en_US.dict ; version = ? ; date = ?
D/AndroidRuntime(10785): Shutting down VM
W/dalvikvm(10785): threadid=1: thread exiting with uncaught exception (group=0xacd4eb20)
E/AndroidRuntime(10785): FATAL EXCEPTION: main
E/AndroidRuntime(10785): Process: com.karthikhiraskar.samplesqlitedb, PID: 10785
E/AndroidRuntime(10785): java.lang.NullPointerException
E/AndroidRuntime(10785):    at android.widget.SimpleAdapter.getCount(SimpleAdapter.java:93)
E/AndroidRuntime(10785):    at android.widget.AdapterView.checkFocus(AdapterView.java:713)
E/AndroidRuntime(10785):    at android.widget.AdapterView$AdapterDataSetObserver.onInvalidated(AdapterView.java:836)
E/AndroidRuntime(10785):    at android.widget.AbsListView$AdapterDataSetObserver.onInvalidated(AbsListView.java:6288)
E/AndroidRuntime(10785):    at android.database.DataSetObservable.notifyInvalidated(DataSetObservable.java:50)
E/AndroidRuntime(10785):    at android.widget.BaseAdapter.notifyDataSetInvalidated(BaseAdapter.java:59)
E/AndroidRuntime(10785):    at android.widget.SimpleAdapter$SimpleFilter.publishResults(SimpleAdapter.java:383)
E/AndroidRuntime(10785):    at android.widget.Filter$ResultsHandler.handleMessage(Filter.java:282)
E/AndroidRuntime(10785):    at android.os.Handler.dispatchMessage(Handler.java:102)
E/AndroidRuntime(10785):    at android.os.Looper.loop(Looper.java:136)
E/AndroidRuntime(10785):    at android.app.ActivityThread.main(ActivityThread.java:5017)
E/AndroidRuntime(10785):    at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime(10785):    at java.lang.reflect.Method.invoke(Method.java:515)
E/AndroidRuntime(10785):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
E/AndroidRuntime(10785):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
E/AndroidRuntime(10785):    at dalvik.system.NativeStart.main(Native Method)
W/ActivityManager( 1596):   Force finishing activity com.karthikhiraskar.samplesqlitedb/.MyCustomListView
D/dalvikvm( 1596): GC_FOR_ALLOC freed 505K, 21% free 9295K/11692K, paused 7ms, total 7ms
W/ActivityManager( 1596): Activity pause timeout for ActivityRecord{ad45ab60 u0 com.karthikhiraskar.samplesqlitedb/.MyCustomListView t59 f}
E/SoundPool( 1596): error loading /system/media/audio/ui/Effect_Tick.ogg
W/AudioService( 1596): Soundpool could not load file: /system/media/audio/ui/Effect_Tick.ogg
E/SoundPool( 1596): error loading /system/media/audio/ui/Effect_Tick.ogg
W/AudioService( 1596): Soundpool could not load file: /system/media/audio/ui/Effect_Tick.ogg
E/SoundPool( 1596): error loading /system/media/audio/ui/Effect_Tick.ogg
W/AudioService( 1596): Soundpool could not load file: /system/media/audio/ui/Effect_Tick.ogg
E/SoundPool( 1596): error loading /system/media/audio/ui/Effect_Tick.ogg
W/AudioService( 1596): Soundpool could not load file: /system/media/audio/ui/Effect_Tick.ogg
E/SoundPool( 1596): error loading /system/media/audio/ui/Effect_Tick.ogg
W/AudioService( 1596): Soundpool could not load file: /system/media/audio/ui/Effect_Tick.ogg
E/SoundPool( 1596): error loading /system/media/audio/ui/KeypressStandard.ogg
W/AudioService( 1596): Soundpool could not load file: /system/media/audio/ui/KeypressStandard.ogg
E/SoundPool( 1596): error loading /system/media/audio/ui/KeypressSpacebar.ogg
W/AudioService( 1596): Soundpool could not load file: /system/media/audio/ui/KeypressSpacebar.ogg
E/SoundPool( 1596): error loading /system/media/audio/ui/KeypressDelete.ogg
W/AudioService( 1596): Soundpool could not load file: /system/media/audio/ui/KeypressDelete.ogg
E/SoundPool( 1596): error loading /system/media/audio/ui/KeypressReturn.ogg
W/AudioService( 1596): Soundpool could not load file: /system/media/audio/ui/KeypressReturn.ogg
I/Process (10785): Sending signal. PID: 10785 SIG: 9
E/SoundPool( 1596): error loading /system/media/audio/ui/KeypressInvalid.ogg
W/AudioService( 1596): Soundpool could not load file: /system/media/audio/ui/KeypressInvalid.ogg
W/AudioService( 1596): onLoadSoundEffects(), Error -1 while loading samples
W/InputDispatcher( 1596): channel 'ad54e4b0 com.karthikhiraskar.samplesqlitedb/com.karthikhiraskar.samplesqlitedb.MyCustomListView (server)' ~ Consumer closed input channel or an error occurred.  events=0x9
E/InputDispatcher( 1596): channel 'ad54e4b0 com.karthikhiraskar.samplesqlitedb/com.karthikhiraskar.samplesqlitedb.MyCustomListView (server)' ~ Channel is unrecoverably broken and will be disposed!
I/ActivityManager( 1596): Process com.karthikhiraskar.samplesqlitedb (pid 10785) has died.
W/InputDispatcher( 1596): Attempted to unregister already unregistered input channel 'ad54e4b0 com.karthikhiraskar.samplesqlitedb/com.karthikhiraskar.samplesqlitedb.MyCustomListView (server)'
W/Binder  ( 1692): Caught a RuntimeException from the binder stub implementation.
W/Binder  ( 1692): java.lang.NullPointerException
W/Binder  ( 1692):  at android.inputmethodservice.IInputMethodWrapper.setSessionEnabled(IInputMethodWrapper.java:280)
W/Binder  ( 1692):  at com.android.internal.view.IInputMethod$Stub.onTransact(IInputMethod.java:129)
W/Binder  ( 1692):  at android.os.Binder.execTransact(Binder.java:404)
W/Binder  ( 1692):  at dalvik.system.NativeStart.run(Native Method)
W/SurfaceFlinger( 1162): couldn't log to binary event log: overflow.
I/WindowState( 1596): WIN DEATH: Window{ad54e4b0 u0 com.karthikhiraskar.samplesqlitedb/com.karthikhiraskar.samplesqlitedb.MyCustomListView}
W/InputMethodManagerService( 1596): Got RemoteException sending setActive(false) notification to pid 10785 uid 10060
W/PlatformStatsUtil( 2013): Could not retrieve Usage & Diagnostics setting. Giving up.

如果你搜索任何东西,你将使用 Textchange 侦听器,我们将使用两个数据列表,一个用于备份,另一个用于根据搜索重新填充。

 edit_text.addTextChangedListener(new TextWatcher() {

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            List<LocationSearchModel> textToCheckList=new ArrayList<>();
            String textToCheck=s.toString();
            if(s.length()!=0){
                //code for making First letter of string CAPITAL
                textToCheck = textToCheck.substring(0, 1).toUpperCase() + textToCheck.substring(1); 

                //code for filling second list from backup list based on text to search here in this case, it is "textToCheck"
                for (LocationSearchModel searchModel: locationSearchList) {
                    if(searchModel.getLocationName().startsWith(textToCheck)){
                        textToCheckList.add(searchModel);
                    }
                }
            }else{
                textToCheckList.addAll(locationSearchList) ;
            }

            // Setting new list to adapter and notifying it
            locationSearchAdapter.setLocationSearchList(textToCheckList);
            locationSearchAdapter.notifyDataSetChanged();
        }

    });

在上面的例子中,"locationSearchList" 是我的备份列表,我将用它来填充我的第二个列表,即

 List<LocationSearchModel> textToCheckList=new ArrayList<>();

在这种情况下。

我在上面的代码中提到了注释,跟着它你会到达solution.and如果发现确实如此,请将我的解决方案标记为已满。