2016-04-14 3 views
1

У меня есть длинный список объектов, которые я извлекаю из базы данных SQLite. Для упрощения предположим, что объект Event имеет свойства Date, Name и Location.Расширяемые элементы списка ListView по годам/месяцам

я могу иметь хронологические 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, которое может быть использовано для сортировки.

Моя первая мысль состояла в том, чтобы передать весь список адаптеру и дать адаптеру определить группы и назначить элементы для групп при создании адаптера. Но я боюсь, что обработка всего списка таким образом, создание групп и назначение элементов этим группам до того, как список будет показан, будет дорогостоящим процессом в уже настроенном для производительности представлении.

Я могу представить, что это довольно распространенный сценарий, и что есть более элегантный способ его решения. Какой был бы лучший подход?

+1

Не могли бы вы добавить код для DataModel в вопрос также. Почему вы не можете правильно упорядочить свои данные перед тем, как поместить их в свой «ListView»? – Darwind

+0

Да, это был мой подход. И я получил его как-то работать с Lollipop и позже. На старых устройствах список по-прежнему пуст. Я очищу код и добавлю его на вопрос в ближайшее время. Благодарю. – jerry

+0

Я обновил вопрос с помощью текущего кода. Надеюсь, что фрагмент выявит достаточную информацию о модели данных - попытка избежать чрезмерного количества кода. – jerry

ответ

1

Просто чтобы добавить ответ.

Вместо того, чтобы пытаться заказать данные после их получения из базы данных, я бы рекомендовал правильно группировать данные, изменив способ запроса базы данных.

Надеется, что это помогает :-)

+0

Да, спасибо. Функциональная проблема была решена вашим первым комментарием. Действительно, «ExpandableListView» не включает «Интеллект» для группировки элементов по заданному критерию. Поэтому вам нужно «вручную» группировать данные по частям с заголовками. Это то, что мне нужно было знать. Производительность в порядке, и есть несколько улучшений, которые можно выполнить: 1. обрабатывать группировку в «DatabaseManager» и 2. (как вы полагаете) использовать интеллектуальные запросы для их группировки. Теперь есть два дополнительных итерации во всем наборе данных поверх запроса.1. легко сделать. 2. может быть предметом другого вопроса. – jerry

1

комментарии и ответ Darwind ответили на вопрос в принципе. Для всех, кто интересуется кодом, я добавляю этот ответ.

Подготовка групп и детей до создания ListView - правильный подход. Как указано в ответе Дарвина, дополнительное усиление производительности может быть достигнуто тем, как данные извлекаются из базы данных (не включены здесь). Код в настоящее время выглядит следующим образом:

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; } 
} 
Смежные вопросы