2014-10-13 2 views
3

В одном из моих прошлых проектов я реализовал «Карусель времени». Он основан на HorizontalScrollView. Пользователь может выбрать время, прокручивая это представление. Значение времени рассчитывается из X-смещения HorizontalScrollView.HorizontalScrollView: CustomAdapter с getView() не повторно использует convertView, как ListView

enter image description here

Я хотел разделить этот проект на GitHub, но в то время очистки кода я понял, некоторые плохой производительности вопрос.

HorizontalScrollView заполнен обычным ArrayAdapter. В getView() используется Holder для convertView. Я думал, что это может работать как адаптер в пределах ListView, поэтому только видимые элементы отображаются и повторно используются, если они будут уничтожены. Вместо этого, все предметы визуализируются !!! (в моем случае 1008!) Я добавляю их сам (# 1 в примере кода), но даже если я пытаюсь добавить меньше, логика из удаления (и утилизации) старых не работает или мне что-то не хватает?

Итак, мой основной вопрос: Что мне нужно изменить, чтобы сделать мой адаптер таким, как ListView?

  1. Я нашел this so link и попытался перекрывая remove функцию, но это никогда не называют (как-то логика, потому что я только добавление)
  2. Там хороший PagerAdapter example на GitHub, но почему-то я не могу перевести это ArrayAdapter<String>

Любые мысли, ссылки приветствуются!

И, пожалуйста, не предлагайте вместо этого использовать ListView. Мы решили использовать HorizontalScrollView из-за обратных вызовов и того факта, что у нас уже есть ListView в макете.

HorizontalScrollView

InfiniteTimeScrubberHorizontalView extends HorizontalScrollView{ 
... 
public void setAdapter(Context context, TimeScrubberListAdapter mAdapter) { 
    this.mAdapter = mAdapter; 
    try { 
     fillViewWithAdapter(mAdapter); 
    } catch (ZeroChildException e) { 
     e.printStackTrace(); 
    } 
} 

private void fillViewWithAdapter(TimeScrubberListAdapter mAdapter) { 
    //... 

    ViewGroup parent = (ViewGroup) getChildAt(0); 
    parent.removeAllViews(); 
    for (int i = 0; i < mAdapter.getCount(); i++) { 
     //#1: Here: ALL views are added 
     parent.addView(mAdapter.getView(i, null, parent)); 
    } 
} 

Adpater

public class TimeScrubberListAdapter extends ArrayAdapter<String> { 

//... 
private ArrayList<String> list; //list from 0:00,0:30...23:00,23:30 
final static int MAXIMUM_DAYS = 21 

@Override 
public int getCount() { 
    return list.size() * MAXIMUM_DAYS; 
} 

@Override 
public String getItem(int position) { 
    return list.get(position % list.size()); 
} 

@Override 
public View getView(final int position, View convertView, ViewGroup parent) { 
    RelativeLayout layout; 

    if (convertView == null) { 
     layout = (RelativeLayout) View.inflate(context, layoutId, null); 
     holder = new Holder(); 
     holder.title = (TextView) layout.findViewById(R.id.epg_item_text); 
     layout.setTag(holder); 
    } else { 
     layout = (RelativeLayout) convertView; 
     view = layout; 
     holder = (Holder) layout.getTag(); 
    } 

    layout.setLayoutParams(mLP);   

    String timeValue = getItem(position); 
    holder.title.setText(timeValue);    

    return layout; 
} 
//... 
@Override 
public void remove(String object) { 
    //not called...some how logic, because i do not remove an item 
    super.remove(object);  
} 
+0

Вы пытались использовать некоторые реализации HorizontalListView? –

+0

Ну, в начале мы решили использовать 'ScrollView' вместо' HorizontalListView' ... но я попробую, если не найду решение для моей текущей проблемы – longilong

+0

, возможно, попробуйте добавить что-то вроде: if (convertView == null && convertView.isVisible()). Обратите внимание, что это выстрел в темноте. Надеюсь, это поможет – AmaJayJB

ответ

14

Я думаю, может быть, вы путаете, где логика лежит для рендеринга между видом и адаптером. Использование адаптера не приводит к изменению режима просмотра. Это ListView, а также его родительский AbsListView, которые реализуют поведение рециркуляции вида. Адаптер требуется ListView, чтобы правильно заполнить Представления, которые отображаются на экране по мере необходимости, но логика для фактического выбора того, какие виды отображать, а также когда и как перерабатывать эти представления вообще не входит в адаптер.

Если вы посмотрите на исходный код для HorizontalScrollView и на номер ListView, вы увидите, что они сильно отличаются друг от друга. Это не одно и то же в разных ориентациях.

Таким образом, длинный и короткий, что вы не сможете получить переработанную рекламу, которую ищете, используя HorizontalScrollView или даже простой потомок. Если вы хотите просмотреть рециркуляцию, вы должны проверить RecyclerView.

+0

спасибо за ваш ответ, все еще глядя для решения для рециркуляции для scrollview – longilong

+0

@ longilong Удачи вам в этом. Рециркуляционные представления не тривиальны, и их нельзя просто взломать на ScrollView. –

+0

ОК, может быть, я открою коробку пандоры еще один день, спасибо за ваши комментарии! ;) – longilong

2

ScrollView сохраняет все дочерние представления в памяти, поэтому проблема с производительностью является обычной при использовании.

Почему бы не использовать некоторую библиотеку HorizontalListView с открытым исходным кодом. В поиске у меня есть эти две библиотеки, из которых я использовал первый в одном из моих проектов, и он работал плавно без каких-либо проблем с памятью.

Эти ЛИЭС горизонтальны реализация ListView, что делает переработку товаров для Вас на основе представлений, которые видны на экране. Scrollview - плохой выбор для просмотра inifinite прокрутки.

UPDATE: Теперь у нас есть RecyclerView от самого Android, который поддерживает горизонтальную прокрутку, а также, он также усиливает использование Viewholder шаблона

+0

https://github.com/MeetMe/Android-HorizontalListView не работает для растровых изображений .... может помочь? –

+1

Вы можете использовать RecyclerView, обновленный мой ответ – Akhil

Смежные вопросы