Joey224
Joey224

Reputation: 15

How to display multiple objects type in RecyclerView?

I am creating Android app, using room database. I have two tables DogsTable:

@PrimaryKey(autoGenerate = true)
int dog_id;
String dogName;

and CatsTable (both tables have constructor and getter methods ):

@PrimaryKey(autoGenerate = true)
 int cat_id;
 String catName;

1- How to display in one RecyclerView two different object type

ArrayList<DogsTable> dog_list;
ArrayList<CatsTable> cat_list;

I am getting the values of dog_list and cat_list from ViewModel Query as show in MainActivity.class.
Image of the recyclerview explain the first problem

2- How to fix getItemCount() method? I don't know how to return two different object cat_list.size(); and dog_list.size();

3- Also in onBindViewHolder() method I don`t know how to get cat_list values to display them in UI?

4- Another problem is in swapToDelete() Method in MainActivity.class, I can get the dog id to delete it, but I can not get the cat id to delete it, how can I get the cat id ?

5- How can I display (dog1,dog2 , dog3) as show in first image? (i inserted the value manually in the first image just to show how i want to display them )

first image,

 Existing Output as below:

This is actually how it displayed

My code

MainActivity.java

public class MainActivity extends AppCompatActivity implements  MainActivityAdapter.ItemClickListener {


MyViewModel viewModel;
MainActivityAdapter adapter;
RecyclerView recyclerView;
LinearLayoutManager layoutManager;

Button btn_addDog, btn_addCat;
EditText et_addDogName, et_addCatName;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    initViews();
    viewModel = ViewModelProviders.of(this).get(MyViewModel.class);
    actionButton();


    buildRecyclerView();
    setUpViewModel_dogs();
    swapToDelete_dog();
}

private void initViews() {
    et_addDogName = findViewById(R.id.addDogNameET_xml);
    et_addCatName = findViewById(R.id.addCatNameET_xml);

}

public void actionButton() {
    btn_addDog = findViewById(R.id.AddDog_btn_xml);
    btn_addCat = findViewById(R.id.AddCat_btn_xml);
    btn_addDog.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            insertDog();
        }
    });
    btn_addCat.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            insertCat();
        }
    });
}

private void buildRecyclerView() {
    recyclerView = findViewById(R.id.recyclerView_id);
    adapter = new MainActivityAdapter(this, this);
    layoutManager = new LinearLayoutManager(this);
    recyclerView.setLayoutManager(layoutManager);
    recyclerView.setAdapter(adapter);
}

// Query
public void setUpViewModel_dogs() {
    viewModel = ViewModelProviders.of(this).get(MyViewModel.class);

    viewModel.getAllDogs().observe(this, new Observer<List<DogsTable>>() {
        @Override
        public void onChanged(@Nullable List<DogsTable> dogsTables) {
            adapter.setDog_list((ArrayList<DogsTable>) dogsTables);
        }
    });
}

public void setUpViewModel_cats(){
    viewModel.getAllCats().observe(this, new Observer<List<CatsTable>>() {
        @Override
        public void onChanged(@Nullable List<CatsTable> catsTables) {
            adapter.setCat_list((ArrayList<CatsTable>) catsTables);
        }
    });

}

// Add
public void insertDog() {

    String dogName = String.valueOf(et_addDogName.getText()).trim();
    DogsTable obj_dog = new DogsTable(dogName);
    viewModel.insertDog(obj_dog);
    Toast.makeText(this, "Dog Added", Toast.LENGTH_SHORT).show();

}

public void insertCat() {
    String catName = String.valueOf(et_addCatName.getText());
    CatsTable obj_cat = new CatsTable(catName);
    viewModel.insertCat(obj_cat);
    Toast.makeText(this, "cat Added", Toast.LENGTH_SHORT).show();
}

// Delete
public void swapToDelete_dog() {
    new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
        @Override
        public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
            return false;
        }
        @Override
        public void onSwiped(final RecyclerView.ViewHolder viewHolder, int direction) {
            List<DogsTable> dog_pos = adapter.getDog_list();
            viewModel.deleteDog(dog_pos.get(viewHolder.getAdapterPosition()));
         }
    }
    ).attachToRecyclerView(recyclerView);
}

public void swapToDelete_cat() {
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.menu, menu);
    return super.onCreateOptionsMenu(menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    int item_id = item.getItemId();

    if (item_id == R.id.menu_add) {
        Intent in = new Intent(this, Add.class);
        startActivity(in);
    }
    return super.onOptionsItemSelected(item);
}

@Override
public void onItemClickListener(int pet_id) {



}
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <EditText
        android:id="@+id/addDogNameET_xml"
        android:layout_width="250dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginEnd="8dp"
        android:hint="add Dog name" />
    <Button
        android:id="@+id/AddDog_btn_xml"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="add" />
</LinearLayout>

<LinearLayout
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
<EditText
    android:id="@+id/addCatNameET_xml"
    android:layout_width="250dp"
    android:layout_height="wrap_content"
    android:layout_marginStart="8dp"
    android:layout_marginEnd="8dp"
    android:hint="add Cat name" />
    <Button
        android:id="@+id/AddCat_btn_xml"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="add" />
</LinearLayout>

<android.support.v7.widget.RecyclerView
    android:id="@+id/recyclerView_id"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:ignore="MissingConstraints" />

   </LinearLayout>

MainActivityAdapter.java

public class MainActivityAdapter extends RecyclerView.Adapter<MainActivityAdapter.MyViewHolder> {

Context mContext;

ArrayList<DogsTable> dog_list;
ArrayList<CatsTable> cat_list;

ItemClickListener mItemClickListener;

public MainActivityAdapter(Context context , ItemClickListener itemClickListener) {
    this.mContext = context;
    this.mItemClickListener = itemClickListener;
}

public interface ItemClickListener {
     void onItemClickListener(int pet_id);
}

@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
    View view = LayoutInflater.from(mContext).inflate(R.layout.activity_main_adapter, viewGroup, false);
    return new MyViewHolder(view);
}

@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {

    DogsTable dog_pos = dog_list.get(position);
 //   CatsTable catsTable = cat_list.get(position);

    holder.dogName.setText(String.valueOf(dog_pos.getDogName()));

   // holder.catName.setText(String.valueOf(catsTable.getCatName()));

}


@Override
public int getItemCount() {
    if (dog_list == null  ) {
        return 0;
    } else {
        return dog_list.size();
    }
}

public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener , ItemClickListener {

    TextView dogName;
    TextView catName;

    public MyViewHolder(@NonNull View itemView) {
        super(itemView);

        dogName = itemView.findViewById(R.id.dogName_xml);
        catName = itemView.findViewById(R.id.catName_xml);
        itemView.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        int pet_id = dog_list.get(getAdapterPosition()).getDogs_id();
        mItemClickListener.onItemClickListener(pet_id);
    }

    @Override
    public void onItemClickListener(int pet_id) {
        int pos = dog_list.get(getAdapterPosition()).getDogs_id();
        mItemClickListener.onItemClickListener(pet_id);

    }
}

public void setDog_list(ArrayList<DogsTable> dog_list) {
    this.dog_list = dog_list;
    notifyDataSetChanged();
}

public ArrayList<DogsTable> getDog_list() {
    return dog_list;
}

public void setCat_list(ArrayList<CatsTable> cat_list) {
    this.cat_list = cat_list;
}
}

activity_main_adapter.xml

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

xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp">

<TextView

    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Dogs:  " />

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">


    <TextView
        android:id="@+id/dogName_xml"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />


</LinearLayout>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">


    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Cats: " />


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="10dp">


        <TextView
            android:id="@+id/catName_xml"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />


    </LinearLayout>
</LinearLayout>

Upvotes: 0

Views: 2086

Answers (1)

nyarian
nyarian

Reputation: 4365

To support different view types, RecyclerView.Adapter provides a useful method int getItemViewType(int position):

Return the view type of the item at position for the purposes of view recycling.

The default implementation of this method returns 0, making the assumption of a single view type for the adapter. Unlike ListView adapters, types need not be contiguous. Consider using id resources to uniquely identify item view types.

Then, in onCreateViewHolder you can see that a second parameter is int viewType which comes from the method int getItemViewType(int position). Based on that, you can instantiate a ViewHolder you need, e.g. DogViewHolder or CatViewHolder.

But what about storing multiple view models in a single adapter and defining which ViewHolder type should be actually instantiated? Here are two most popular approaches:

  1. Declaring multiple containers for multiple types and defining a custom logic for getItemViewType method, e.g. all odd numbers will go in the dogs' list and even numbers will go in the cats' list (or any other method, but beware that you will have to cope with different lists' sizes and all the view types you need). Also, getItemsCount should be overriden appropriately (return list1.size() + list2.size + ... + listN.size();)
  2. Put all the view models in a single list and perform some kind of attributes checks: either it will be some property or the type itself (not recommended for scalability reasons). Then your code will look like this:

    public int getItemViewType(int position) { CommonParentForUpcasting item = items.get(position); if (item instanceOf Dog) { // or something like item.type == Animal.CAT return R.id.holder_dog; } else { return R.id.holder_cat; } }

If you want to come up with a second solution, this solution should suit you well. Also, make sure to check this StackOverflow answer.

Upvotes: 4

Related Questions