Reputation: 15
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.
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 )
Existing Output as below:
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
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:
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();
)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