Search code examples
androidkotlinfilterandroid-alertdialogandroid-asynclistdiffer

AlertDialog does not update the list - Kotlin Android


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?


Solution

  • 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.