当前位置: 首页 > 知识库问答 >
问题:

Android为什么是RecycleView适配器崩溃?

明松
2023-03-14

我有一个RecyclerView列表,可以在两种布局中进行选择,一种是默认布局,另一种是带有适配器的CardView布局。当用户尚未创建任何CardView时,会首先显示默认的UI布局。用户创建并保存CardView后,布局会切换到CardView布局。布局使用“视图类型”切换,在0和1之间切换。

当我使用这两种方法时,布局之间的切换效果很好:

public int getItemCount() {
    return contactList.size()>0 ? contactList.size():1;
}

public int getItemViewType(int position) {
    return contactList.size() == 0 ? 0:1;
}

然后我添加了下面的方法供其他使用,应用程序正在崩溃:

public Contact getItem(int position) {
    return contactList.get(position);
}

我错过了什么?

Logcat:

致命的例外:主java。lang.RuntimeException:无法启动活动组件信息{com.example.jdw.v52/com.wimso.v052.MainActivity}:java。lang.IndexOutOfBoundsException:索引0无效,android上的大小为0。应用程序。活动线程。在android上执行LaunchActivity(ActivityThread.java:2059)。应用程序。活动线程。android上的handleLaunchActivity(ActivityThread.java:2084)。应用程序。活动线程。在Android上获得600美元(ActivityThread.java:130)。应用程序。android上的ActivityThread$H.handleMessage(ActivityThread.java:1195)。操作系统。汉德勒。android上的dispatchMessage(Handler.java:99)。操作系统。活套。android上的loop(Looper.java:137)。应用程序。活动线程。java上的main(ActivityThread.java:4745)。朗,反思一下。方法java上的Invokenactive(本机方法)。朗,反思一下。方法在com上调用(Method.java:511)。Android内部的操作系统。ZygoteInit$MethodandArgscaler。在com上运行(ZygoteInit.java:786)。Android内部的操作系统。合子体。dalvik的main(ZygoteInit.java:553)。系统原生艺术。main(本机方法)由以下原因引起:java。lang.IndexOutOfBoundsException:索引0无效,java的大小为0。util。ArrayList。java上的throwIndexOutOfBoundsException(ArrayList.java:251)。util。ArrayList。在com上获取(ArrayList.java:304)。维索。v052。适配器。ContactListAdapter。com上的getItem(ContactListAdapter.java:95)。维索。v052。适配器。ContactListAdapter。在com上清除(ContactListAdapter.java:72)。维索。v052。主要活动。com上的loadData(MainActivity.java:171)。维索。v052。主要活动。onStart(MainActivity.java:126)

Adapter.java
...
public ContactListAdapter(Context context) {
    this.context = context;
    this.contactList = new ArrayList<>();
    mLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
} 

public void add(Contact item) {
    if (contactList.size()==0) {
        // if list is empty 
        // remove empty cards first
        contactList.clear();
        notifyDataSetChanged();
    }
    contactList.add(item);
    notifyItemInserted(contactList.size() -1);
}

public void clear() {
    while (getItemCount() > 0) {
        remove(getItem(0));
    }
}

// Remove an item from the RecyclerView/
public void remove(Contact item) {
    if (contactList.size()==0) {
        // if no more contacts in list,
        // we rebuild from scratch
        contactList.clear();
        notifyDataSetChanged();
    }
    int position = contactList.indexOf(item);
    if (position > -1) {
        contactList.remove(position);
        notifyItemRemoved(position);
        notifyItemRangeChanged(position, contactList.size());  // I added this.
    }
}

// Get the Item's position.
public Contact getItem(int position) {
    return contactList.get(position);
}

// Update the existing List of RecyclerView items.
public void addAll(List<Contact> contactList) {
    for (Contact contact : contactList) {
        add(contact);
    }
}

@Override
public int getItemCount() {
    return contactList.size()>0 ? contactList.size():1;
}

// if there are zero CardViews, use viewType 0 to get default_layout,
// otherwise provide a viewType of 1 to for each CardView in order to
// show the singlecard_layout.
@Override
public int getItemViewType(int position) {
    return contactList.size() == 0 ? 0:1;
}

// Get the Item's Id.
public long getItemId(int position) {
    return contactList.get(position).getId();
}

private static class DefaultViewHolder extends RecyclerView.ViewHolder {
    DefaultViewHolder(View itemView) {
        super(itemView);
    }
}

private class ContactViewHolder extends RecyclerView.ViewHolder {

    CountDownTimer timer;
    ...
    private ContactViewHolder(View itemView) {
        super(itemView);

    ...
    @Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    if (viewType == 0) {
        View itemView = mLayoutInflater.inflate(R.layout.defaultcard_layout, parent, false);
        return new DefaultViewHolder(itemView);
    } else {
        View itemView = mLayoutInflater.inflate(R.layout.list_contact_item, parent, false);
...
public void onBindViewHolder(final RecyclerView.ViewHolder viewHolder, final int position) {
    int type = getItemViewType(position);
    if (type == 1) {
        Contact contact = contactList.get(position);
        final ContactViewHolder holder = (ContactViewHolder) viewHolder;
    ...

共有3个答案

云浩然
2023-03-14

我有一个类似的崩溃,这是由于主办活动的主题。

<代码>

我的活动是透明的,里面有一个片段,里面有一个回收器视图。一切都会加载,但是在旋转时,我得到了同样的错误。我的片段或回收器视图实现没有问题,这是活动的样式。删除修复了这个问题。

云英才
2023-03-14

问题是适配器的getItem()getItemId()没有正确检查联系人列表是否为空。因为即使列表为空,适配器也会报告1的大小,所以将调用这些方法,因为RecyclerView希望显示一个项。

当适配器没有项目时,您似乎试图显示不同的视图。虽然只在适配器中就可以做到这一点,但我认为在布局中有一个单独的视图,只要在加载联系人列表时相应地更改可见性,就会更简单、更干净。这样你的适配器就不需要那么复杂了。

adapter.setItems(list); // or add, whatever
if (list.size() > 0) {
    recyclerView.setVisiblity(View.VISIBLE);
    emptyView.setVisiblity(View.GONE);
} else {
    emptyView.setVisiblity(View.VISIBLE);
    recyclerView.setVisiblity(View.GONE);
}
祝嘉懿
2023-03-14

问题是:

public int getItemCount() {
   return contactList.size()>0 ? contactList.size():1;
}

当联系人列表的大小为0时,您仍然会返回RecyclerView,使其至少有一个视图。这一视图试图访问您的联系人列表,该列表已为0,因此:

java.lang.IndexOutOfBoundsException: Invalid index 0, size is 0

你可以这样做:

public int getItemCount() {
      return contactList.size() != null ? contactList.size() : 0;
}

以防你的联系人列表为空。

或者

public int getItemCount() {
   return contactList.size();
}

如果从未向适配器输入空的联系人列表,只需返回列表大小即可。

 类似资料:
  • 问题内容: 名称(和javadocs)暗示这是一个适配器(设计模式)。但我不这么认为-至少一见钟情,它无法使任何事物适应任何事物 发生的唯一变化是,您可以将的实例传递给需要任何一个接口的任何方法。因此,您可以使用仅预期的实例。但是没有“翻译”发生。而且它不符合GoF的UML-在“类适配器”版本中,期望对一个方法的调用会从适配器中调用一个方法。 那么,这是一个适配器(设计模式),还是仅仅是一个引起混

  • 我有一个回收演示,但当我运行该演示时,总是显示错误消息“recycleview recycerview:No adapter attached;skipping layout” 这是我主要的activity课 这是我的RecyclerViewAdapter代码

  • 问题内容: 我有这个代码: 当我滚动我的回收站视图时,出现此错误: 如何处理此错误并获得第一个可见项目的位置? 问题答案: 我用此代码对其进行了测试,并且对我来说效果很好 我使用了回收视图参数。

  • 本节将会引入一个全新的概念——适配器,这个名字很形象,和电源适配器的功能类似,从程序设计的角度出发,它可以将不同类型、不同结构的数据适配到一起。 在 Android 中,适配器是 UI 组件和数据之间的桥梁,它帮助我们将数据填充到 UI 组件当中,实现了一个典型的 MVC 模式。我们可以分别编写独立的 UI 样式和数据模型,至于数据如何与 UI 组件绑定都由 Adapter 帮我们完成,这样的好处

  • 我尝试按照幻灯片youtube 6部分教程创建一个带有自定义行的列表视图。在他的教程中,他使用了1个图像和2个文本视图,我需要3个图像和3个文本视图,当我运行应用程序时,它在尝试加载列表视图时崩溃。 -------------家庭单行.xml----------------------- - Homelistview.xml - Homeactivitylistview.java 04-22 15

  • 我读过PingFederate的文档,上面写着: SP适配器用于为用户创建本地应用程序会话,以便PingFederate提供对您的应用程序或其他受保护资源的SSO访问。为了建立到IdP伙伴的连接,您必须至少配置一个SP适配器实例。您还可以配置多个适配器实例(基于一个或多个适配器),以满足您的IdP合作伙伴的不同需求。 但我不明白为什么IdP连接需要SP适配器?为什么需要它?它真正做什么? 在我的用