1

我有一个显示日期的 ListView。通过使用 Spinner,我可以选择要显示多少天(如果列表太长,我可以滚动浏览它)。

在此处输入图像描述

当我看到 30 天并且位于列表底部时,如果我使用微调器并选择查看 15 天、30 天、15 天,我最终会得到重复或错误的元素。

在此处输入图像描述

我已经阅读了很多关于此的内容,并应用了每一个建议:

  • 无效

  • 无效视图

  • notifyDataSetInvalidated

  • notifyDataSetChanged

  • refreshDrawableState

  • 使用 Handler 来运行这些调用

但没有解决我的问题。

我正在使用以下代码:

=== 自定义适配器 ===

public class CustomAdapter extends BaseAdapter {

    private List<ViewHolder> viewHolders;

    @Inject
    public CustomAdapter(@Assisted List<ViewHolder> viewHolders) {
        this.viewHolders = viewHolders;
    }

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

    @Override
    public Object getItem(int i) {
        return viewHolders.get(i);
    }

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

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        return viewHolders.get(i).getView(view);
    }
}

=== ListViewHolder ===

public class ListViewHolder extends ViewHolder {

    @Override
    public View getView(View view) {
        Holder holder;

        if (view == null) {
            view = LayoutInflater.from(contextProvider.get()).inflate(R.layout.entry, null);
            holder = new Holder();

            holder.text = (TextView) view.findViewById(R.id.textView);

            view.setTag(viewStructure);
        } else {
            holder = (Holder) view.getTag();
        }

        holder.text.setText(/* date */);

        return view;
    }
}

=== 列表片段 ===

public class ListFragment extends RoboFragment {

    private CustomAdapter customAdapter = null;

    private List<ViewHolder> viewHolders = new ArrayList<ViewHolder>();

    private ListView listView;

    private Handler handler = new Handler();

    @Inject
    private ListFragment(AdapterFactory adapterFactory) {
        customAdapter = adapterFactory.createAdapter(viewHolders);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        final View view = inflater.inflate(R.layout.list, container, false);

        listView = (ListView) view.findViewById(R.id.listView);

        listView.setAdapter(customAdapter);

        return view;
    }

    public void setContentRange(List<ViewHolder> viewHolders, int range) {
        update(viewHolders.subList(0, range));
    }

    private void update(List<ViewHolder> content) {
        viewHolders.clear();
        viewHolders.addAll(content);

        if (customAdapter != null) {
            handler.post(new Runnable() {
                @Override
                public void run() {
                    customAdapter.notifyDataSetChanged();
                    //customAdapter.notifyDataSetInvalidated();

                    if (listView != null) {
                        listView.invalidateViews();
                    //    listView.requestLayout();
                    //    listView.refreshDrawableState();
                    }
                }
            });
        }
    }
}

有什么建议么?提前致谢。

抱歉,不能发图,知名度不够。。。

编辑:

  • 添加图片链接

  • ListViewHolder 的代码实际上是这样的。我将其简化为在这里发布,但也许它很重要:

    公共类 ListViewHolder 扩展 ViewHolder {

    @Inject
    private ListViewHolder(Holder holder) { // Guice will create the holder
        super(holder);
    }
    
    @Override
    public View getView(View view) {
        Holder holder;
    
        if (view == null) {
            view = LayoutInflater.from(contextProvider.get()).inflate(R.layout.entry, null);
            holder = getHolder(); // getHolder is defined in ViewHolder, and returns the object created in the constructor
    
            holder.text = (TextView) view.findViewById(R.id.textView1);
    
            view.setTag(viewStructure);
        } else {
            holder = (DualTextViewStructure) view.getTag();
        }
    
        holder.text.setText(/* Date */);
    
        return view;
    }
    

    }

4

1 回答 1

0

事实证明,在构造函数中使用由 Guice 创建的 Holder 是问题所在。如果我使用提供者,则列表的行为符合预期

public class ListViewHolder extends ViewHolder {

    @Override
    public View getView(View view) {
        Holder holder;

        if (view == null) {
            view = LayoutInflater.from(contextProvider.get()).inflate(R.layout.entry, null);
            // getHolder looks like this:
            // @Inject
            // private Provider<Holder> holderProvider;
            // public Holder getHolder() {
            //     holderProvider.get();
            // }
            holder = getHolder();

            holder.text = (TextView) view.findViewById(R.id.textView1);

            view.setTag(viewStructure);
        } else {
            holder = (DualTextViewStructure) view.getTag();
        }

        holder.text.setText(/* Date */);

        return view;
    }
}
于 2013-10-14T21:59:32.240 回答