im trying to be a junior android developer and im trying to make a fake product list from an api. I'm using a recyclerview with gridlayout. I created an asynclist in my adapter and gathering values from viewmodel and observing and submitting in the fragment. And i would add the sort and filter options on my fragment. I would do that like real apps. I created 2 alertdialogs for my buttons. I can sort and filter respectively. But sorting after filter does not work for second time. For first time i can filter and sort. But if i changed filter i cant sort the items. List comes empty from filter alertdialog...
Here is my codeblock;
@AndroidEntryPoint
class ProductFragment : Fragment(R.layout.fragment_product) {
private var fragmentBinding : FragmentProductBinding? = null
@Inject
lateinit var viewModel: HomeViewModel
@Inject
lateinit var adapter: ProductsAdapter
lateinit var list : MutableList<Product>
private var filteredList = mutableListOf<Product>()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val binding = FragmentProductBinding.bind(view)
fragmentBinding = binding
viewModel.getAllProducts()
viewModel.products.observe(viewLifecycleOwner){
adapter.recyclerListDiffer.submitList(it.data)
list = adapter.recyclerListDiffer.currentList
}
filteredList.addAll(adapter.recyclerListDiffer.currentList)
binding.productsRecycler.adapter = adapter
binding.productsRecycler.layoutManager = StaggeredGridLayoutManager(2,RecyclerView.VERTICAL)
adapter.setOnItemClickListener {
val action = ProductFragmentDirections.actionProductFragmentToDetailScreenFragment(it)
findNavController().navigate(action)
}
//**BACK BUTTON
binding.productsBackbutton.setOnClickListener {
findNavController().popBackStack()
}
//** SORT ***///
val sortArray = arrayOf("Best Match","Price Asc","Price Desc")
var adbIndex = 0
var selectedItem = ""
binding.productsSortbutton.setOnClickListener {
MaterialAlertDialogBuilder(requireContext())
.setSingleChoiceItems(sortArray,adbIndex){ dialog,which->
adbIndex = which
selectedItem = sortArray[which]
}
.setPositiveButton("Sort"){dialog,which->
when(selectedItem){
sortArray.get(0) ->{
adapter.recyclerListDiffer.submitList(filteredList)
}
else {
adapter.recyclerListDiffer.submitList(list)
}
binding.productsRecycler.smoothScrollToPosition(0)
}
sortArray.get(1) ->{
if (filteredList.isNotEmpty()){
adapter.recyclerListDiffer.submitList(filteredList.sortedBy { it.price.toDouble() })
}
else {
adapter.recyclerListDiffer.submitList(list.sortedBy { it.price.toDouble() })
}
binding.productsRecycler.smoothScrollToPosition(0)
}
sortArray.get(2) -> {
if (filteredList.isNotEmpty()){
adapter.recyclerListDiffer.submitList(filteredList.sortedByDescending { it.price.toDouble() })
}
else{
adapter.recyclerListDiffer.submitList(list.sortedByDescending { it.price.toDouble() })
}
binding.productsRecycler.smoothScrollToPosition(0)
}
}
}
.show()
}
//FILTER
val filterArray = arrayOf("Electronics","Jewelery","Men's Clothing","Women's Clothing")
var filterArrayBool : BooleanArray = booleanArrayOf(false,false,false,false)
val currentItemList = Arrays.asList(*filterArray)
val selectedItemList = ArrayList<String>()
binding.productsFilterbutton.setOnClickListener {
MaterialAlertDialogBuilder(requireContext())
.setCancelable(false)
.setMultiChoiceItems(filterArray,filterArrayBool) {dialog,which,isChecked ->
filterArrayBool[which] = isChecked
}
.setPositiveButton("FILTER"){dialog,which->
for (i in filterArrayBool.indices){
val checked = filterArrayBool[i]
if (checked){
selectedItemList.add(currentItemList[i].lowercase())
}
when(selectedItemList.size){
1 -> {
filteredList.clear()
viewModel.products.observe(viewLifecycleOwner){
adapter.recyclerListDiffer.submitList(it.data?.filter { it.category== selectedItemList.get(0) })
}
filteredList.addAll(adapter.recyclerListDiffer.currentList.filter { it.category == selectedItemList.get(0) })
}
2 -> {
viewModel.products.observe(viewLifecycleOwner){
adapter.recyclerListDiffer.submitList(it.data?.filter { it.category== selectedItemList.get(0) || it.category == selectedItemList.get(1) })
filteredList.clear().also { filteredList.addAll(adapter.recyclerListDiffer.currentList.filter { it.category== selectedItemList.get(0) || it.category == selectedItemList.get(1) }) }
}
}
3 -> {
viewModel.products.observe(viewLifecycleOwner){
adapter.recyclerListDiffer.submitList(it.data?.filter { it.category== selectedItemList.get(0) || it.category == selectedItemList.get(1) || it.category == selectedItemList.get(2) })
filteredList.clear().also { filteredList.addAll(adapter.recyclerListDiffer.currentList.filter { it.category== selectedItemList.get(0) || it.category == selectedItemList.get(2) }) }
}
}
4 -> {
viewModel.products.observe(viewLifecycleOwner){
adapter.recyclerListDiffer.submitList(it.data?.filter { it.category== selectedItemList.get(0) || it.category == selectedItemList.get(2) || it.category == selectedItemList.get(3) })
filteredList.clear().also { filteredList.addAll(adapter.recyclerListDiffer.currentList.filter { it.category== selectedItemList.get(0) || it.category == selectedItemList.get(2) || it.category == selectedItemList.get(3) }) }
}
} else ->
viewModel.products.observe(viewLifecycleOwner){
adapter.recyclerListDiffer.submitList(it.data)
filteredList.clear().also { filteredList.addAll(adapter.recyclerListDiffer.currentList) }
}
}
}
binding.productsRecycler.smoothScrollToPosition(0)
selectedItemList.clear()
} .setNeutralButton("Show All"){dialog,which ->
viewModel.products.observe(viewLifecycleOwner){
adapter.recyclerListDiffer.submitList(it.data) }
filterArrayBool.forEach { it==false }
binding.productsRecycler.smoothScrollToPosition(0)
}.show()
}
}
}
How can i update the list everytime when i select the positive button?
CodePudding user response:
I think it's because you are observing the whole data for everytime when you filter, i mean again and again. It should be one for getting all data like you do on top:
viewModel.products.observe(viewLifecycleOwner){
adapter.recyclerListDiffer.submitList(it.data)
list = adapter.recyclerListDiffer.currentList
}
Do not touch it and delete all other observe methods, you already got that data and assigned to the global list as "list : MutableList", use that one and do not observe all time because it confilicts. I mean instead of below :
1 -> {
filteredList.clear()
viewModel.products.observe(viewLifecycleOwner){
adapter.recyclerListDiffer.submitList(it.data?.filter {
it.category== selectedItemList.get(0) })
}
filteredList.addAll(adapter.recyclerListDiffer.currentList.filter { it.category == selectedItemList.get(0) })
}
use this for the cases:
1 -> {
filteredList.clear()
adapter.recyclerListDiffer.submitList(list.filter {
list.category== selectedItemList.get(0) })
}
filteredList.addAll(adapter.recyclerListDiffer.currentList.filter { list.category == selectedItemList.get(0) })
CodePudding user response:
After many hours i feel like stupid. The problem is that trying to call list from current list. Submitting the list with as an example with jewelery and i was trying to call electronics from currentlist. I changed adapter.recyclerDiffer.currentlist.filter{} to list.filter{}. The problem has been solved with this code.
1 -> {
filteredList.clear()
adapter.recyclerListDiffer.submitList(list.filter { it.category == selectedItemList[0] })
filteredList.addAll(list.filter { it.category == selectedItemList[0] })
}
By the way there was an another mistake in the code as the that user("Mert) said. There was a lot of observing method. It should be deleted, and should be call for once. I send my thanks to him.