Пользовательский метод getView, вызываемый часто с позицией 0

У меня есть GridView, связанный с пользовательским производным ArrayAdapter.

<GridView
        android:id="@+id/measurements"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:columnWidth="100dp"
        android:gravity="center"


        android:numColumns="auto_fit"
        android:orientation="horizontal"
        android:stretchMode="columnWidth"/>

Каждый элемент завышен до представления (я использую шаблон повторного просмотра), как показано ниже.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" 
    android:orientation="vertical" android:background="#8800CC00">

    <TextView android:id="@+id/widget_view_id" 
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <TextView android:id="@+id/widget_status" 
        android:layout_width="match_parent" 
        android:layout_height="match_parent"
        android:layout_gravity="center"/>
    <TextView android:id="@+id/widget_timestamp" 
        android:layout_width="match_parent" 
        android:layout_height="match_parent" 
        android:layout_gravity="center"/>

</LinearLayout>

У меня есть HandlerThread, который затем заполняет каждый виджет значениями данных на периодической основе.

Однако я вижу, что первое представление "заморожено" - никаких обновлений. LogCat показывает мне, что адаптер # getView (position = 0) вызывается почти так, как если бы он находился в цикле.

public class WidgetAdapter extends ArrayAdapter<DataItem>
    {
        private DataServiceProxy _dataServiceProxy;

        public WidgetAdapter(Context context, List<DataItem> objects, DataServiceProxy dataServiceProxy) {
            super(context, 0, objects);
            _dataServiceProxy = dataServiceProxy;

        }


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

                View view;
                DataItem dataItem = getItem(position);

                if (convertView == null)
                {
                    view = getActivity().getLayoutInflater().inflate(R.layout.item_dataItem, parent, false);
                    view.setPadding(8, 8, 8, 8);
                }
                else
                {
                    view = convertView;
                    int oldId = ((Integer)view.getTag()).intValue();
                    _dataServiceProxy.removeListener(WidgetView.getFor(view), oldId);
                }

                ((TextView) view.findViewById(R.id.widget_view_id)).setText("View# " + dataItem.id);
                view.setTag(Integer.valueOf(dataItem.id));

                _dataServiceProxy.addListener(new WidgetView(view, dataItem), dataItem.id);
                return view;
        }
...     

В прошлый раз я это исправил - заменив height = 'wrap_content' на 'match_parent' во всех подтипах шаблона элемента GridView. (Ref: Romain Guy Google IO talk)

Но он вернулся и завел меня с ума...

Стек вызовов, когда я устанавливаю точку останова в getView (pos = 0), показывает

Тема [< 1 > main] (приостановлено (точка останова в строке 255 в WidgetFragment $WidgetAdapter)) WidgetFragment $WidgetAdapter.getView(int, View, ViewGroup): 255 GridView (AbsListView).obtainView(int, boolean []): 2456 GridView.onMeasure(int, int): 1030   GridView (View).measure(int, int): 15562
  RelativeLayout.measureChildHorizontal(вид, RelativeLayout $LayoutParams, int, int): 617
  RelativeLayout.onMeasure(int, int): 399
  RelativeLayout (View).measure(int, int): 15562
  FrameLayout (ViewGroup).measureChildWithMargins(View, int, int, int, int): 5109 FrameLayout.onMeasure(int, int): 310
  Строка FrameLayout (View).measure(int, int): 15562   FrameLayout (ViewGroup).measureChildWithMargins(View, int, int, int, int): 5109 FrameLayout.onMeasure(int, int): 310
  Строка FrameLayout (View).measure(int, int): 15562   LinearLayout.measureVertical(int, int) line: 833
  LinearLayout.onMeasure(int, int): 574
  LinearLayout (View).measure(int, int) line: 15562
  PhoneWindow $DecorView (ViewGroup).measureChildWithMargins(View, int, int, int, int) строка: 5109

Ответ 1

Найденное исправление - не уверен в рассуждениях.

В результате процесса исключения я понял, что вызовы getView (pos = 0) начинают pinging только после того, как пустой текстовый просмотр обновляется HandlerThread. Я дважды проверял идентификаторы потоков, которые пользовательский интерфейс обновляется в нужном потоке.

Затем я начал настраивать атрибуты textview, и следующая комбинация заставит симптомы исчезнуть, и первое представление теперь обновляется правильно. В основном высота должна быть жестко закодирована, match_parent имеет вышеупомянутую проблему, а wrap_content - нет-нет в соответствии с парнями Android.

<TextView android:id="@+id/widget_status" 
        android:layout_width="match_parent" 
        android:layout_height="20dp"
        android:gravity="center"/>

Ответ 2

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

У меня такая же проблема, как и вы, и что я сделал, это удалить ваш адаптер и заново создать его. Сделайте это шаг за шагом, как:

  • Создайте свой адаптер, расширьте BaseAdapter (лучше, чем ArrayAdapter, посмотрите, почему там)
  • реализовать методы unimplement
  • добавьте список в свой адаптер в качестве вашего datalist
  • изменить getCount(), getItem(), getItemId()
  • шаг за шагом редактируйте getView() (создайте представление с помощью LayoutInflater)
  • попробуйте свое приложение с 2-3 данными в списке

Если он работает, завершите свой адаптер, как вы хотите