Search code examples
javaandroidandroid-recyclerviewandroid-viewandroid-adapter

Is initializing a new RecyclerView Adapter an asynchronous call?


My question is, is the initialization of a new RecyclerView adapter an asynchronous call?

I have an adapter that I am creating:

mRecyclerAdapter = new TestAdapter(mContext, mListImages);
mRecycler.setLayoutManager(mLayoutManager);
mRecycler.setAdapter(mRecyclerAdapter);

After initializing it, I can call .add() directly after these methods without calling .notifyDataSetChanged() and they would still be added to my adapter, and displayed.

mRecyclerAdapter = new TestAdapter(mContext, mListImages);
mRecycler.setLayoutManager(mLayoutManager);
mRecycler.setAdapter(mRecyclerAdapter);

mListImages.add( . . .);
mListImages.add( . . .);
mListImages.add( . . .);

Are RecyclerView adapters automatically initialized on a background thread?

Here is my adapter:

public class SelectBucketAdapter extends RecyclerView.Adapter<SelectBucketAdapter.ViewHolder> {

    private static final String TAG = "SelectBucketAdapter";

    private Context mContext;
    private ArrayList<String> mBucketList;

    public SelectBucketAdapter(Context mContext, ArrayList<String> mBucketList,
                               ) {
        this.mContext = mContext;
        this.mBucketList = mBucketList;

    }

    @NonNull
    @Override
    public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int viewType) {
        View view = LayoutInflater.from(viewGroup.getContext())
                .inflate(R.layout.vh_selectbucketmenu_layout, viewGroup, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull ViewHolder holder, int i) {
        ... binding views
    }

    @Override
    public int getItemCount() {
        return mBucketList.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder{

        @BindView(R.id.vh_selectbucketmenu_name)
        TextView vhBucketName;


        int mPosition;
        public ViewHolder(@NonNull View itemView) {
            super(itemView);

        }


    }
}

Solution

  • Are RecyclerView adapters automatically initialized on a background thread?

    No, they are not.

    Is the initialization of a new RecyclerView adapter an asynchronous call?

    No, it is not.

    The layout creation and attachment to window is async.

    What this means?

    Assume we have following code:

    override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      ...
    
      val adapter = MyAdapter()
      recyclerView.adapter = adapter
    
      adapter.list.add("1")
    }
    

    In this case we will see the "1" being displayed on the screen, because at the point when adapter.list.add("1") was executed RecyclerView hasn't yet passed through its measure-layout-draw cycle.

    Now let's consider following code:

    override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      ...
    
      val adapter = MyAdapter()
      recyclerView.adapter = adapter
    
      Handler().postDelayed({ adapter.list.add("AAA") }, 2000)
    }
    

    In this case adapter.list.add("AAA") will be executed in roughly 2 seconds. As long as RecyclerView will already be laid out by that time, then mutating the adapter dataset won't make the RecyclerView show the item, because RecyclerView doesn't know if dataset has suffered a change.

    Let's consider following case:

    override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      ...
    
      val adapter = MyAdapter()
      recyclerView.adapter = adapter
    
      recyclerView.doOnPreDraw { adapter.list.add("preDraw") }
      recyclerView.doOnLayout { adapter.list.add("layout") }
      adapter.list.add("onCreate")
    }
    

    In this case still only "onCreate" will be displayed on screen.

    To sum up: as soon as RecyclerView has passed its measure step (i.e. View#onMeasure) then mutating adapter won't be reflected unless adapter explicitly notifies RecyclerView.