如何在listview数组适配器上正确实现filterable

时间:2017-08-09 00:02:13

标签: java android

我正在处理一个笔记应用程序,我需要帮助实现listview的笔记标题的可搜索功能。我有一个数组适配器类,其中扩展了filterable,还有一个序列化内容的Note类。 现在,我已经在工具栏上实现了一个搜索栏,但每当我输入一个字母时,列表项就会消失,之后我会收到错误。

主要活动

    public class NoteAdapter extends ArrayAdapter<Note> implements Filterable{
    public static final int WRAP_CONTENT_LENGTH = 50;
    public ArrayList<Note> notes;
    public NoteAdapter(Context context, int resource, List<Note> objects) {
        super(context, resource, objects);

    }

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

        if(convertView == null) {
            convertView = LayoutInflater.from(getContext())
                    .inflate(R.layout.view_note_item, null);
        }

        Note note = getItem(position);

        if(note != null) {
            TextView title = (TextView) convertView.findViewById(R.id.list_note_title);
            TextView date = (TextView) convertView.findViewById(R.id.list_note_date);
            TextView content = (TextView) convertView.findViewById(R.id.list_note_content_preview);

            title.setText(note.getTitle());
            date.setText(note.getDateTimeFormatted(getContext()));

            //correctly show preview of the content (not more than 50 char or more than one line!)
            int toWrap = WRAP_CONTENT_LENGTH;
            int lineBreakIndex = note.getContent().indexOf('\n');
            //not an elegant series of if statements...needs to be cleaned up!
            if(note.getContent().length() > WRAP_CONTENT_LENGTH || lineBreakIndex < WRAP_CONTENT_LENGTH) {
                if(lineBreakIndex < WRAP_CONTENT_LENGTH) {
                    toWrap = lineBreakIndex;
                }
                if(toWrap > 0) {
                    content.setText(note.getContent().substring(0, toWrap) + "...");
                } else {
                    content.setText(note.getContent());
                }
            } else { //if less than 50 chars...leave it as is :P
                content.setText(note.getContent());
            }
        }

        return convertView;
    }
    Filter filter = new Filter() {
        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults filterResults = new FilterResults();
            ArrayList<Note> myList = new ArrayList<>();
            if (constraint !=null && notes!= null) {
                int length = notes.size();
                int i = 0;
                while (i<length) {
                    Note item = notes.get(i);
                    myList.add(item);
                    i++;
                }
                filterResults.values = myList;
                filterResults.count = myList.size();
            }
            return null;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
notes = (ArrayList<Note>) results.values;
            if (results.count > 0) {
                notifyDataSetChanged();
            } else {
                notifyDataSetInvalidated();
            }

        }

    };
public Filter getFilter(){
    return filter;
}
}

NoteAdapter.java

public class Note implements Serializable {
    private long mDateTime; //creation time of the note
    private String mTitle; //title of the note
    private String mContent; //content of the note

    public Note(long dateInMillis, String title, String content) {
        mDateTime = dateInMillis;
        mTitle = title;
        mContent = content;
    }

    public void setDateTime(long dateTime) {
        mDateTime = dateTime;
    }

    public void setTitle(String title) {
        mTitle = title;
    }

    public void setContent(String content) {
        mContent = content;
    }

    public long getDateTime() {
        return mDateTime;
    }

    /**
     * Get date time as a formatted string
     * @param context The context is used to convert the string to user set locale
     * @return String containing the date and time of the creation of the note
     */
    public String getDateTimeFormatted(Context context) {
        SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy                                           HH:mm:ss"
                , context.getResources().getConfiguration().locale);
        formatter.setTimeZone(TimeZone.getDefault());
        return formatter.format(new Date(mDateTime));
    }

    public String getTitle() {
        return mTitle;
    }

    public String getContent() {
        return mContent;
    }
}

Note.java

java.lang.NullPointerException: Attempt to read from field 'int android.widget.Filter$FilterResults.count' on a null object reference
                                                                         at com.app.ben.notetaker.NoteAdapter$1.publishResults(NoteAdapter.java:82)
                                                                         at android.widget.Filter$ResultsHandler.handleMessage(Filter.java:282)
                                                                         at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                         at android.os.Looper.loop(Looper.java:154)
                                                                         at android.app.ActivityThread.main(ActivityThread.java:6119)
                                                                         at java.lang.reflect.Method.invoke(Native Method)
                                                                         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
                                                                         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

log cat

{{1}}

我需要在逻辑中包含哪些内容才能正确过滤listview项目的标题?

1 个答案:

答案 0 :(得分:0)

当您返回null时,您始终会从performFiltering()返回filterResults。这是NoteAdapter.java。可能还有其他事情要发生,但从这里开始。

修改:您似乎也没有在任何地方设置notes,因此无需过滤。你似乎也缺少其他一些功能,但也许你没有发布所有功能。

Here是一个自定义适配器的示例,其自定义过滤看起来像是包含所有部分。您可以将此作为指南。

我希望这会有所帮助。