【问题标题】:GridView recycles child view that is still visibleGridView 回收仍然可见的子视图
【发布时间】:2017-05-25 11:02:43
【问题描述】:

我有一个使用适配器回收子视图的 GridView。每个子视图都由一个 ImageView 和一个覆盖在顶部的 TextView 组成。我看到的问题是,当我滚动并看到新图像时,网格中其他单元格的图像也可以更改为正在显示的图像。

调试后我可以看到这是因为当一个新行进入视图时,在适配器上调用 getView() 来获取新行的视图。然而,被传递给方法的视图,android 想要我回收,实际上仍然在视图中。因此,当我更新它给我的视图图像时,我最终也会更改网格中另一个项目的图像。

有谁知道这是什么原因造成的?

活动

<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/snapshot_list_swipe_refresh"
android:layout_width="match_parent"
android:layout_height="match_parent">

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_snapshot_list"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.vellocet.snapshotviewer.SnapshotListActivity">

    <GridView
        android:id="@+id/snapshot_grid"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="5dp"
        android:drawSelectorOnTop="true"
        android:gravity="center"
        android:numColumns="2"
        android:stretchMode="columnWidth"
        android:verticalSpacing="0dp"
        android:horizontalSpacing="0dp"
        android:focusable="true"
        android:clickable="true"/>

</RelativeLayout>

</android.support.v4.widget.SwipeRefreshLayout>

适配器:

private class SnapshotListAdapter extends BaseAdapter {
    private final Context context;
    private List<Snapshot> snapshots;

    public SnapshotListAdapter(Context context, List<Snapshot> snapshots) {
        this.context = context;
        snapshots = snapshots;
    }

    @Override
    public int getCount() {
        return snapshots.size();
    }

    @Override
    public Object getItem(int i) {
        return i < snapshots.size() ? snapshots.get(i) : null;
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        ViewHolder viewHolder;

        if (view == null) {
            LayoutInflater inflater = ((Activity)context).getLayoutInflater();
            view = inflater.inflate(R.layout.snapshot_grid_item_layout, viewGroup, false);
            viewHolder = new ViewHolder();
            viewHolder.image = (ImageView)view.findViewById(R.id.snapshot_grid_item_imageview);
            viewHolder.text = (TextView) view.findViewById(R.id.snapshot_grid_item_textview);
            view.setTag(viewHolder);

            view.setLayoutParams(new GridView.LayoutParams(
                    GridView.LayoutParams.MATCH_PARENT,
                    (int)getResources().getDimension(R.dimen.snapshot_grid_item_height)));
        }
        else {
            viewHolder = (ViewHolder)view.getTag();
        }

        final Snapshot snapshot = snapshots.get(i);
        viewHolder.snapshot = snapshot;
        viewHolder.image.setImageDrawable(null);
        viewHolder.updateText();

        snapshot.getSnapshotFiles(new GetSnapshotCallback(viewHolder, snapshot));

        return view;
    }
}

感谢您的帮助

【问题讨论】:

  • 这是您的整个适配器代码吗?另外,您是如何确定回收的视图在屏幕上仍然可见的?
  • 这就是一切,除了我剪掉了 GetSnapshotCallback 实现和一些在子视图上设置点击侦听器的代码。我知道它仍然可见,因为传递给 getView 的视图标签包含顶行中一项的标签(如果您向下滚动)。
  • 同样在调试器中,传入的视图的对象 ID 与之前创建的相匹配,它在屏幕上,但部分在屏幕外

标签: android gridview adapter recycle


【解决方案1】:

我的错。尽管正在回收仍在屏幕上的视图,但随后会为原始位置创建一个新视图。

例如,如果位置 0 在屏幕上,并且您滚动以将位置 8 显示在视图中,则即使位置 0 仍在屏幕上,位置 0 的视图也会被回收到位置 8。但是,它将为位置 0 调用另一个 createView,不传入任何回收视图,因此创建了一个新实例。有点奇怪的过程,但它不会导致我看到的图像出现在多个图像视图中的问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-03
    • 1970-01-01
    • 2014-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多