Android

RecyclerViewが特定条件下で大量にViewを作ろうとする場合の対処

More than 3 years have passed since last update.


RecyclerViewとは


  • Qiitaを適当に検索すると出てきます

  • 多数のViewをリスト形式で表示するときに便利です

  • 以下はバージョン23.3.0で発生します


問題となる条件


  • タブレット端末等で、「左右に画面を等分2分割し、そのどちらかにRecyclerViewを入れる」という条件で発生します。

  • 現象としては、RecyclerViewがViewの幅高さを正常に計算できず、延々とAdapter.onCreateViewHolderを呼び出し続けます


レイアウト例


  • ここでは左半分をRecyclerViewとしています。

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"/>

<TextView android:layout_width="0dp"
android:layout_weight="1"
android:text="BLANK"
android:layout_height="match_parent"/>
</LinearLayout>


プログラム例


public class MainActivity extends AppCompatActivity {

RecyclerView mRecyclerView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);

mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
mRecyclerView.setAdapter(new RecyclerView.Adapter() {
int mCreatedViews;

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Log.i("onCreateViewHolder", "Created :: " + (++mCreatedViews));

return new RecyclerView.ViewHolder(new TextView(MainActivity.this)) {
};
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
((TextView) holder.itemView).setText("POSITION :: " + position);
}

@Override
public int getItemCount() {
return 100000;
}
});
}
}


対処方法

次のどちらかで対応可能


  1. RecyclerViewを含んだLayoutはweightの対象として扱わない

  2. もしくは等分したいだけならば wrap_content + weight の組み合わせではなく、 match_parent + weight=1 を組み合わせる(等分以外はうまくいかないけど)

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_weight="1"
android:layout_height="match_parent"/>

<TextView android:layout_width="match_parent"
android:layout_weight="1"
android:text="BLANK"
android:layout_height="match_parent"/>
</LinearLayout>