I need to get the parameter from the argument inside my fragment and give it to the view model, so that it filters the list based on it or not. I thought that it is possible to pass this argument to the factory for the view model, and from there to the constructor of the view model itself, so it will have val onlyFavorites and it can be used right away in the init block.
ContentFragment.kt
class ContentFragment : Fragment(), ItemFavoriteClickListener {
private val viewModel: ContentViewModel by viewModels(factoryProducer = {
ContentViewModel.Factory()
})
private var adapter: MyItemModelsAdapter? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.getBoolean("onlyFavorites", false)
viewModel.items.observe(this) {
adapter?.items = it
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
recyclerView?.layoutManager = LinearLayoutManager(context)
adapter = MyItemModelsAdapter(this)
recyclerView?.adapter = adapter
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_favourites, container, false)
}
override fun onFavoriteClick(item: ItemModel, isFavorite: Boolean) {
viewModel.changeFavoriteState(item, isFavorite)
}
companion object {
fun newInstance(onlyFavorites: Boolean): ContentFragment {
val contentFragment = ContentFragment()
val args = Bundle()
args.putBoolean("onlyFavorites", onlyFavorites)
contentFragment.arguments = args
return contentFragment
}
}
}
ContentViewModel.kt
class ContentViewModel(
private val repository: MyItemsRepository
) : ViewModel() {
class Factory : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
return ContentViewModel(MyItemsRepositoryImpl.getInstance()) as T
}
}
private val _items: MutableLiveData<List<ItemModel>> = MutableLiveData()
val items: LiveData<List<ItemModel>>
get() = _items
fun changeFavoriteState(item: ItemModel, favorite: Boolean) {
repository.setFavorite(item, favorite)
}
init {
_items.value = repository.items.filter { it.isFavorite }
repository.addItemChangeListener {
_items.value = repository.items.filter { it.isFavorite }
}
}
}
I need your help writing the code. I mentally understand how to do it, but I don't know how to write it. I would be very grateful for a written example with an explanation.
It's not that hard as it seems; just create a new public variable inside your ContentViewModel
Say
var isFavorite: Boolean = false
Then instead of init of a ViewModel, put your fetching logic inside a method.
fun getItems() {
_items.value = repository.items.filter { it.isFavorite == isFavorite }
}
And now call this method in fragment's onViewCreated() something like this:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
recyclerView?.layoutManager = LinearLayoutManager(context)
adapter = MyItemModelsAdapter(this)
recyclerView?.adapter = adapter
val isFavorite = arguments?.getBoolean("onlyFavorites", false) ?: false
viewModel.isFavorite = isFavorite
viewModel.getItems()
viewModel.items.observe(this) {
adapter?.items = it
}
}
This way, you have the value for isFavorite before you actually call the getItems method.
I haven't tested this code, but I'm pretty sure it'll work.
Leave a comment if you need any more help with this.