自定义适配器 getView 方法经常调用,位置为 0



我有一个绑定到自定义 ArrayAdapter 派生的 GridView。

<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>

我有一个处理程序线程,然后定期用数据值填充每个小部件。

但是我看到第一个视图被"冻结" - 没有更新。LogCat向我展示了adapter#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;
        }
...     

上次发生这种情况时,我已经修复了它 - 通过在所有 GridView 项模板子视图中将 height='wrap_content' 替换为"match_parent"。(参考:Romain Guy's Google IO talk(

但它又回来了,让我发疯了...

当我在getView(pos=0(上设置断点时调用堆栈显示

线程 [<1> 主] (挂起(第 255 行的断点 WidgetFragment$WidgetAdapter(( WidgetFragment$WidgetAdapter.getView(int, View, ViewGroup( 行: 255 GridView(AbsListView(.obtainView(int, 布尔[]( 行: 2456 网格视图.on测量(整数, 整数( 行: 1030 网格视图(视图(.测量(整数,整数( 行: 15562
RelativeLayout.measureChildHorizontal(View, 相对布局$布局参数, int, int( 行: 617
RelativeLayout.onMeasure(int, int( 行: 399
相对布局(视图(.测量(整数,整数( 行: 15562
FrameLayout(ViewGroup(.measureChildWithMargins(View, int, int, int, int( 行: 5109 FrameLayout.onMeasure(int, int( 行: 310
框架布局(视图(.测量(整数,整数( 行: 15562 FrameLayout(ViewGroup(.measureChildWithMargins(View, int, int, int, int( 行: 5109 FrameLayout.onMeasure(int, int( 行: 310
框架布局(视图(.测量(整数,整数( 行: 15562 线性布局测量垂直(整数,整数(行:833
LinearLayout.onMeasure(int, int( 行: 574
线性布局(视图(.测量(整数,整数( 行: 15562
PhoneWindow$DecorView(ViewGroup(.measureChildWithMargins(View, int, 国际,国际,国际(行:5109

找到了一个修复程序 - 虽然不确定原因。

通过消除过程,我最终知道 getView(pos=0( 调用只有在 HandlerThread 更新空文本视图后才会开始 ping。我仔细检查了线程 ID,以确定 UI 是否正在右侧线程上更新。

然后,我开始调整文本视图的属性,以下组合使症状消失,并且第一个视图现在正在正确更新。基本上高度需要硬编码,match_parent有上述问题,wrap_content根据机器人家伙来说是一个禁忌

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

抱歉在这里发布,因为我暂时无法发表评论。

和你有同样的问题,我所做的是删除你的适配器并重新创建它。
像这样一步一步地做:

  • 创建你的适配器扩展 BaseAdapter(比 ArrayAdapter 更好,看看为什么有(
  • 实现
  • 取消实现方法
  • 在适配器中添加一个列表作为数据列表
  • 编辑 getCount((, getItem((, getItemId((
  • 逐步编辑getView(((使用LayoutInflater创建视图(
  • 尝试使用列表中包含 2-3 个数据的应用

如果有效,请根据需要完成适配器

最新更新