LoginSignup
12
11

More than 5 years have passed since last update.

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

Last updated at Posted at 2016-04-21

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>

12
11
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
11