2017-01-08 118 views
0

我有一個RecyclerView列表,它可以在兩個佈局之間進行選擇,默認佈局和CardView佈局。當用戶尚未創建任何CardView's時,默認UI佈局首先顯示。在用戶創建並保存CardView之後,佈局切換到CardView佈局。佈局使用「viewType」,0和1之間Android爲什麼RecyclerView適配器崩潰?

切換佈局之間的切換工作正常,當我用這兩種方法進行切換:

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:無法啓動活動 ComponentInfo {com.example.jdw.v52/com.wimso.v052.MainActivity}: 的java。 lang.IndexOutOfBoundsException:無效索引0,大小爲0 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059) 在 android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084) 在和roid.app.ActivityThread.access $ 600(ActivityThread.java:130) at android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1195) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:4745) at java.lang.reflect.Method.invokeNative(Native Method) at java .lang.reflect.Method.invoke(Method.java:511) 在 com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run(ZygoteInit.java:786) 在com.android.internal.os.ZygoteInit。主(ZygoteInit。的java:553)在dalvik.system.NativeStart.main(本機方法) 所致:java.lang.IndexOutOfBoundsException:無效索引0,大小 是0 在 java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java: 251) 在java.util.ArrayList.get(ArrayList.java:304) 在 com.wimso.v052.adapter.ContactListAdapter.getItem(ContactListAdapter.java:95) 在 com.wimso.v052.adapter。 ContactListAdapter.clear(ContactListAdapter.java:72) at com.wimso.v052.MainActivity.loadData(MainActivity.java:171) 在com.wimso.v052.MainActivity.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; 
    ... 

回答

1

這裏的問題:

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

contactList的大小爲0,你還在返回RecyclerView至少有1視圖。這一個觀點試圖訪問你的contactList這已經是0,因此這一點:

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

你可以這樣做:

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

的情況下,你會得到一個空contactList。

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

如果你從來沒有輸入一個空contactList到適配器,只需返回列表的大小就行了。

+0

好的,但如果我只是使用「return contactList.size();」那麼當尺寸從0(應該顯示默認佈局)到1或更多(顯示CardView佈局)時,佈局不能正確切換......任何想法? – AJW

+0

您不應該爲此目的使用getItemType。這用於在單個回收站視圖內創建多個視圖類型。使用不同的方法。 –

+0

關於如何更好地在兩個CardView佈局之間切換,您有任何建議嗎? – AJW

1

的問題是你的適配器的getItem()getItemId()不正確檢查聯繫人列表是空的。由於即使列表爲空,您的適配器也會報告大小爲1,因爲RecyclerView預期會顯示一個項目,所以將調用這些方法。

當適配器沒有項目時,您似乎試圖顯示不同的視圖。雖然可以在適配器中單獨執行此操作,但我認爲在佈局中單獨使用View會更簡單,更簡單,並且只需加載聯繫人列表即可相應地更改可見性。這樣你的適配器不需要太複雜。

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); 
} 
0

我有一個類似的崩潰是由於託管活動的主題。

<item name="android:windowIsTranslucent">true</item>

我的活性爲透明與具有內部的recyclerview的片段。一切都會加載,但旋轉後我得到相同的錯誤。我的分段或回收視圖實現沒有什麼問題,它是活動的樣式。刪除可修復此問題。