I have multiple ViewHolders that work as separated views inside a vertical RecyclerView. I'm practicing with the new Architecture Components ViewModel.
Inside my ViewModel I have a couple of MutableLiveData lists that i want to observe, but how can I call
ViewModelProviders.of((AppCompatActivity)getActivity()).get(FilterViewModel.class)
and
mFilterViewModel.getCountries().observe(this, new Observer<ArrayList<TagModel>>() { @Override public void onChanged(@Nullable ArrayList<TagModel> tagModels) { } });
without leaking the activity or save the activity inside the adapter?
my ViewModel
public class FilterViewModel extends ViewModel { private final MutableLiveData<ArrayList<TagModel>> mCountries; private final MutableLiveData<ArrayList<TagModel>> mSelectedCountryProvinceList; private final MutableLiveData<ArrayList<TagModel>> mDistanceList; public FilterViewModel(){ mCountries = new MutableLiveData<>(); mSelectedCountryProvinceList = new MutableLiveData<>(); mDistanceList = new MutableLiveData<>(); TagStore.getInstance().subscribe(new StoreObserver<TagSearchList>() { @Override public void update(TagSearchList object) { mCountries.setValue(object.getCountries()); } @Override public void update(int id, TagSearchList object) { if (id == 5){ TagStore.getInstance().unSubcribe(this); update(object); } } @Override public void error(String error) { } }).get(5,"parent"); TagStore.getInstance().subscribe(new StoreObserver<TagSearchList>() { @Override public void update(TagSearchList object) { mSelectedCountryProvinceList.setValue(object.toList()); } @Override public void update(int id, TagSearchList object) { if (id == 6){ TagStore.getInstance().unSubcribe(this); update(object); } } @Override public void error(String error) { } }).get(6,"parent"); TagStore.getInstance().subscribe(new StoreObserver<TagSearchList>() { @Override public void update(TagSearchList object) { mDistanceList.setValue(object.toList()); } @Override public void update(int id, TagSearchList object) { if (id == 51){ TagStore.getInstance().unSubcribe(this); update(object); } } @Override public void error(String error) { } }).get(51,"parent"); } public void selectCountry(final TagModel country){ TagStore.getInstance().subscribe(new StoreObserver<TagSearchList>() { @Override public void update(TagSearchList object) { mSelectedCountryProvinceList.setValue(object.toList()); } @Override public void update(int id, TagSearchList object) { if (id == country.getId()){ TagStore.getInstance().unSubcribe(this); update(object); } } @Override public void error(String error) { } }).get(country.getId(),"parent"); } public LiveData<ArrayList<TagModel>> getCountries(){ return mCountries; } public LiveData<ArrayList<TagModel>> getDistances(){ return mDistanceList; } public LiveData<ArrayList<TagModel>> getProvinces(){ return mSelectedCountryProvinceList; }
create a new variable(ViewModel) for the layout (fragment or activity layout) in your activity or fragment get the instance of your viewModel with ViewModelProviders. hold the data which fills your recyclerView in MutableLiveData and observe it and fill the adapter of recyclerView with the value you observed.
I am using Room Persistence library. Below is my code for recyclerview adapter using MVVM.
You can see CartViewModel and I have initialized it into the constructor. The constructor gets the context from the activity, and I have cast it into FragmentActivity.
private CartViewModel cartViewModel; public CartListAdapter(Context context, List<CartModel> cartModels) { this.context = context; this.cartModels = cartModels; cartViewModel = ViewModelProviders.of((FragmentActivity) context).get(CartViewModel.class); }
Here is my full adapter class. I hope it will help.
public class CartListAdapter extends RecyclerView.Adapter<CartListAdapter.CartListViewHolder> { private static final String TAG = "CartListAdapter"; private Context context; private List<CartModel> cartModels; private Double totalQuantity = 0.0; private CartViewModel cartViewModel; public CartListAdapter(Context context, List<CartModel> cartModels) { this.context = context; this.cartModels = cartModels; cartViewModel = ViewModelProviders.of((FragmentActivity) context).get(CartViewModel.class); } @NonNull @Override public CartListViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { return new CartListViewHolder(LayoutInflater.from(context).inflate(R.layout.list_all_cart_item,parent,false)); } @Override public void onBindViewHolder(@NonNull CartListViewHolder holder, int position) { CartModel cartModel = cartModels.get(position); Glide.with(context) .load(cartModel.getPPICLocate()) .into(holder.cartItemImage); holder.tvCartProductName.setText(cartModel.getProductName()); holder.tvCartProductCategory.setText(cartModel.getPCategorySubID()); holder.tvCartProductPrice.setText(cartModel.getPPriceSales()); holder.etCartProductQuantity.setText(cartModel.getPQuantity()); holder.btnCartPQtIncrease.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { totalQuantity = Double.valueOf(holder.etCartProductQuantity.getText().toString()); totalQuantity = totalQuantity+1; cartModel.setPQuantity(totalQuantity.toString()); updateCart(cartModel); } }); holder.btnCartPQtDecrease.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { totalQuantity = Double.valueOf(holder.etCartProductQuantity.getText().toString()); totalQuantity = totalQuantity-1; cartModel.setPQuantity(totalQuantity.toString()); updateCart(cartModel); } }); } @Override public int getItemCount() { return cartModels.size(); } public class CartListViewHolder extends RecyclerView.ViewHolder{ private ImageView cartItemImage; private TextView tvCartProductName,tvCartProductCategory,tvCartProductPrice, etCartProductQuantity,tvCartProductPrevPrice; private ImageButton btnCartPQtIncrease,btnCartPQtDecrease; public CartListViewHolder(@NonNull View itemView) { super(itemView); cartItemImage= itemView.findViewById(R.id.cartItemImage); tvCartProductName= itemView.findViewById(R.id.tvCartProductName); tvCartProductCategory= itemView.findViewById(R.id.tvCartProductCategory); tvCartProductPrice= itemView.findViewById(R.id.tvCartProductPrice); etCartProductQuantity= itemView.findViewById(R.id.etCartProductQuantity); tvCartProductPrevPrice= itemView.findViewById(R.id.tvCartProductPrevPrice); btnCartPQtIncrease= itemView.findViewById(R.id.btnCartPQtIncrease); btnCartPQtDecrease= itemView.findViewById(R.id.btnCartPQtDecrease); } } public void addItems(List<CartModel> cartModels) { this.cartModels = cartModels; notifyDataSetChanged(); } private void updateCart(CartModel cartModel){ String tqt = String.valueOf(cartModel.getPQuantity()); Log.d(TAG, "updateQuantity: "+tqt); /*cartRepository.updateCartRepo(cartModel);*/ cartViewModel.updateCartItemVM(cartModel); } }
You could create an OnClickListener
interface instead, then implement the onClick
method (defined in your interface) in your fragment or activity where you have access to your view model.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With