带有自定义适配器的 Android ListView 有视觉故障

Posted

技术标签:

【中文标题】带有自定义适配器的 Android ListView 有视觉故障【英文标题】:Android ListView with Custom Adapter Has Visual Glitch 【发布时间】:2020-01-31 16:41:41 【问题描述】:

我是 android 编程新手,正在尝试弄清楚如何优化我的 ListView 适配器。我编写了一个自定义适配器来将 CardViews 添加到我的 ListView:

public class CardAdapter extends BaseAdapter 

    private final ArrayList<CardView> cards = new ArrayList<CardView>();
    private Context context;

    public CardAdapter( Context context ) 
        this.context = context;
    

    public void add( CardView view ) 
        cards.add( view );
    

    @Override
    public int getCount() 
        return cards.size();
    

    @Override
    public int getViewTypeCount() 
        return getCount();
    

    @Override
    public int getItemViewType(int position) 
        return position;
    

    @Override
    public Object getItem(int i) 
        if( i >= cards.size() || i < 0 )
            return null;
        return cards.get( i );
    

    @Override
    public long getItemId(int i) 
        return cards.get(i).getId();
    

    @Override
    public View getView(int position, View view, ViewGroup viewGroup) 
        if( view == null ) 
            view = (CardView) getItem( position );
        

        return view;
    

MainActivity 类似于:

public class MainActivity extends AppCompatActivity 

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ListView list = findViewById(R.id.notesList);
        CardAdapter adapter = new CardAdapter(getBaseContext());
        adapter.add( makeCard() );
        // repeat making cards however many times...
        list.setAdapter(adapter);
    

    private CardView makeCard() 
        CardView card = new CardView(this);
        // Do some things to customize the CardView
        return card;
    



现在看来,Android 正在尝试回收视图,但做得很糟糕。最初页面看起来不错,但是当我开始滚动时,卡片开始在屏幕上移动,间距发生变化,卡片开始重叠等等。。

请注意,我只滚动了几秒钟,这不是逐渐变化的,卡片有点像在屏幕上“跳跃”。到目前为止,我想出的唯一解决方案是将我的 getView 更改为:

    @Override
    public View getView(int position, View view, ViewGroup viewGroup) 
        return (CardView) getItem(position);
    

这很有效,但即使加载大约 10 个项目也很慢,而且滚动滞后。

【问题讨论】:

请发布适配器 xml 文件。 @Chintan 我不确定你在问什么,你的意思是 activity_main.xml 吗? 您的activity_main.xml 和您的卡片xml 可能有助于找到问题,但我会先尝试RecyclerView。 @RicardoA。是的,我稍后会在 recyclerview 上试一试。卡片是通过代码创建的,没有对应的 XML,这会导致什么问题吗? Activity_main 只是一个包含列表视图的线性布局。 不,那些代码可能没问题,问题应该是您的适配器或只是 ListView 本身的实现。正如 ghazanfar ali 试图解释的那样,RecyclerView 是专门为解决这种情况而创建的。而且 ListView 已经过时了,所以你真的应该换成 RecylerView,即使它不能解决问题,但在使用最新技术时更容易找到帮助,因为大多数人都在使用它。 【参考方案1】:

请使用 RecyclerView,它使用视图持有者模式来解决所有这些滞后问题

【讨论】:

【参考方案2】:

将您的实现从 ListView 更改为 RecyclerView。

RecyclerView 是作为继承者添加到 android studio 中的 ViewGroup 的 GridView 和 ListView。这是对他们两个的改进,并且 可以在最新的 v-7 支持包中找到。它已创建 可以构建任何带有 XML 布局的列表作为项目 它可以在提高效率的同时进行大量定制 列表视图和网格视图。这种改进是通过回收 用户不可见的视图。例如,如果一个 用户向下滚动到项目 4 和 5 可见的位置; 项目 1、2 和 3 将从内存中清除以减少内存 消费。

来自GeeksforGeeks。 Ps:链接有很多解释、教程和代码...

RecyclerView 是专门为解决您遇到的问题而创建的。它比 ListView 有很多改进,比如更少的内存消耗、更少的滞后、更好的滚动...

【讨论】:

【参考方案3】:

好吧,太简单了

首先记住你必须传递你想在适配器中使用的东西,但现在你只需将一个(this)传递给这个适配器。 为您的构造函数使用下面的代码。

有良好的编码。

private final ArrayList<CardView> cards = new ArrayList<CardView>();
private Context context;

public CardAdapter( Context context , ArrayList<CardView> cards) 
    this.context = context;
    this.cards =cards

【讨论】:

他稍后会添加卡片,使用空列表启动适配器绝对没有问题。

以上是关于带有自定义适配器的 Android ListView 有视觉故障的主要内容,如果未能解决你的问题,请参考以下文章

带有过滤器 Android 的自定义 Listview 适配器

Android ListView 和带有 ViewHolder 的自定义适配器

带有自定义适配器的 ListView

列表视图在android中不起作用

如何在 Xamarin Android 的 AlertDialog 中创建带有自定义适配器的列表视图

如何在 FirebaseListAdapter 中使用自定义适配器