support library v23.1.1 で以下のコードを実行すると落ちます。
java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid item position 0(offset:20).state:20
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:4405)
...
public class RecyclerViewGoneActivity extends AppCompatActivity {
private TextAdapter textAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recycler_view_gone);
final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
// 1. 初期状態がGONE
recyclerView.setVisibility(View.GONE);
// 2. setHasFixedSize(true);
recyclerView.setHasFixedSize(true);
textAdapter = new TextAdapter();
recyclerView.setAdapter(textAdapter);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
ArrayList<String> data = new ArrayList<>();
for (int i = 0; i < 20; i++) {
data.add("data : " + i);
}
// 3. notifyItemRangeInserted(); を呼ぶ
textAdapter.addAll(data);
// 4. visibility を VISIBLE にする
recyclerView.setVisibility(View.VISIBLE);
}
}, 1000);
}
private static class TextAdapter extends RecyclerView.Adapter<ViewHolder> {
private final ArrayList<String> data = new ArrayList<>();
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
return new ViewHolder(inflater.inflate(ViewHolder.LAYOUT_ID, parent, false));
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.textView.setText(data.get(position));
}
@Override
public int getItemCount() {
return data.size();
}
public void add(String s) {
final int positionStart = getItemCount();
data.add(s);
notifyItemInserted(positionStart);
}
public void addAll(ArrayList<String> d) {
final int positionStart = getItemCount();
final int itemCount = d.size();
data.addAll(d);
notifyItemRangeInserted(positionStart, itemCount);
}
public void clear() {
final int itemCount = getItemCount();
data.clear();
notifyItemRangeRemoved(0, itemCount);
}
}
private static class ViewHolder extends RecyclerView.ViewHolder {
public static final int LAYOUT_ID = android.R.layout.simple_list_item_1;
final TextView textView;
public ViewHolder(View itemView) {
super(itemView);
this.textView = (TextView) itemView.findViewById(android.R.id.text1);
}
}
}
落ちなくする方法がいくつかあります。
- 1. setHasFixedSize(true); を呼ばないようにする(ただしその分パフォーマンスに影響する)
- 2. あらかじめデータを入れておいて VISIBLE にする前に消す
textAdapter = new TextAdapter();
recyclerView.setAdapter(textAdapter);
textAdapter.add("dummy"); // これを追加
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
textAdapter.clear(); // これを追加
ArrayList<String> data = new ArrayList<>();
for (int i = 0; i < 20; i++) {
data.add("data : " + i);
}
textAdapter.addAll(data);
recyclerView.setVisibility(View.VISIBLE);
}
}, 1000);
0 件のコメント:
コメントを投稿