按年/月分类的可扩展ListView项目

时间:2016-04-14 12:58:02

标签: android sqlite listview expandablelistview

我有一长串从SQLite数据库中检索的对象列表。为简化起见,我们假设Event对象的属性为DateNameLocation

我可以使用以下列表适配器按时间顺序排列ListView Event,并从按Event排序的数据库中提取Date

public class ImageListButtonListAdapter extends ArrayAdapter<ImageListButtonListItem> {

    public ImageListButtonListAdapter(Context c, List<ImageListButtonListItem> items) {
        super(c, 0, items);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ImageListButtonView itemView = (ImageListButtonView)convertView;
        if (null == itemView)
            itemView = ImageListButtonView.inflate(parent);
        itemView.setItem(getItem(position));
        return itemView;
    }

    @Override
    public void notifyDataSetChanged() {
        super.notifyDataSetChanged();
    }
}

到目前为止,这么好。现在这个列表很长,我希望使用ExpandableListView进一步构建列表,并按月对Event项进行分组。我发现创建从BaseExpandableListAdapter派生的列表适配器的示例通常包括预定义的组和组名。我只有一大组项目,每个项目包含一个(Joda Time)LocalDate,我可以根据它添加一个可用于排序的计算属性YearMonth

我的第一个想法是将整个列表传递给适配器,让适配器确定组,并在创建适配器时将项目分配给组。但我担心以这种方式处理整个列表,创建组并在列表显示之前为这些组分配项目在已经对性能敏感的视图中将是一个代价高昂的过程。

我可以想象这是一个相当常见的场景,并且有一种更优雅的方式来解决它。什么是最好的方法?

2 个答案:

答案 0 :(得分:1)

只是为了添加答案。

我建议您不要尝试从数据库中提取数据后对数据进行排序,而是建议您通过更改查询数据库的方式对数据进行正确分组。

希望这会有所帮助: - )

答案 1 :(得分:1)

Darwind的评论和回答原则上回答了这个问题。对于任何对代码感兴趣的人,我都会添加这个答案。

在创建ListView之前准备组和子项是正确的方法。正如Darwin的回答所示,通过从数据库中检索数据的方式可以实现额外的性能提升(此处不包括在内)。现在的代码如下:

public class EventsListFragment extends ExpandableListFragment{

    (...)

    public void onResume() {
        super.onResume();

        dbManager = new DatabaseManager(getActivity());
        mEvents = dbManager.GetEvents();

        mItems.clear();
        mGroups.clear();
        mChildGroups.clear();

        ArrayList<ImageListButtonListItem> childGroup = new ArrayList<>();

        for (int i = mEvents.size()-1; i >= 0; i--) {

            LocalDate date = mEvents.get(i).getDate();
            DateTimeFormatter dtf = DateTimeFormat.longDate();
            String date =  dtf.print(date);
            String name = mEvents.get(i).getEventName();
            String location = mEvents.get(i).getLocation();
            String imagePath = (...)
            ImageListButtonListItem item = new ImageListButtonListItem(date, name, location, imagePath);

            // List category (sorted by months).
            YearMonth yearMonth = new YearMonth(date.getYear(), date.getMonthOfYear());

            if(mGroups.isEmpty()) {
                mGroups.add(yearMonth);
            } else if(!mGroups.contains(yearMonth)) {
                mChildGroups.add(childGroup);
                mGroups.add(yearMonth);
                childGroup = new ArrayList<>();
            }
            childGroup.add(item);
        }
        if (!childGroup.isEmpty()) {
            mChildGroups.add(childGroup);
        }

        mAdapter.notifyDataSetChanged();
    }

    (...)
}

-

public class MonthExpandableImageListButtonListAdapter extends BaseExpandableListAdapter {

    private Context mContext;
    private List<Object> mChildGroups;
    private List<YearMonth> mGroups;
    public LayoutInflater mInflater;
    public Activity mActivity;

    public MonthExpandableImageListButtonListAdapter(Context context, List<Object> childGroups, List<YearMonth> groups) {
        mContext = context;
        mChildGroups = childGroups;
        mGroups = groups;
    }
    public void setInflater(LayoutInflater inflater, Activity act) {
        mInflater = inflater;
        mActivity = act;
    }
    @Override
    public int getGroupCount() { return mGroups.size(); }

    @Override
    public int getChildrenCount(int groupPosition) { return  ((ArrayList<Object>)mChildGroups.get(groupPosition)).size(); }

    @Override
    public Object getGroup(int groupPosition) { return null; }

    @Override
    public Object getChild(int groupPosition, int childPosition) { return null; }

    @Override
    public long getGroupId(int groupPosition) { return 0; }

    @Override
    public long getChildId(int groupPosition, int childPosition) { return 0; }

    @Override
    public boolean hasStableIds() { return false; }

    @Override
    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
            if (convertView == null) {
                convertView = mInflater.inflate(R.layout.view_month_expandable_list_header, null);
            }
            ((CheckedTextView) convertView).setText(mGroups.get(groupPosition).toString());
            ((CheckedTextView) convertView).setChecked(isExpanded);
            return convertView;
    }

    @Override
    public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
        ImageListButtonView itemView = (ImageListButtonView)convertView;
        if (null == itemView)
            itemView = ImageListButtonView.inflate(parent);
        itemView.setItem(((ArrayList<ImageListButtonListItem>) mChildGroups.get(groupPosition)).get(childPosition));
        return itemView;
    }

    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) { return false; }
}