I try get data from internet, after done i update my Recyclerview, but it never show. Method onDone() Toast size of result, it's not empty.
My code:
class SearchFragment : Fragment() {
private lateinit var requestSearchPresenter: RequestSearchPresenter
private lateinit var recyclerViewAdapter: RecyclerViewAdapter
private var searchResult = ArrayList<ItemNewFeedCollection?>()
private val onRequestSearchResult = object : OnRequestSearchResult {
override fun onEmpty(result: ListNewFeedCollection) {
recyclerViewAdapter.notifyDataSetChanged()
}
override fun onDone(result: ListNewFeedCollection) {
searchResult = result.post
Toast.makeText(requireContext(), "${searchResult.size}", Toast.LENGTH_SHORT).show()
recyclerViewAdapter.notifyDataSetChanged()
}
override fun onFail(t: String) {
recyclerViewAdapter.notifyDataSetChanged()
}
}
private var recyclerViewItemClickListener = object : OnRecyclerViewItemClickListener {
override fun onItemClick(view: View, postion: Int) {
(requireActivity() as NewFeedActivity).apply {
val post = searchResult
if (post[postion]!!.date == "null" && post[postion]!!.date == post[postion]!!.description &&
post[postion]!!.date == post[postion]!!.full_post && post[postion]!!.date == post[postion]!!.image &&
post[postion]!!.date == post[postion]!!.full_post
) {
} else {
val link = post[postion]!!.link
val source = post[postion]!!.source
val intent = Intent(requireContext(), PostActivity::class.java)
intent.putExtra("link", link)
intent.putExtra("source", source)
startActivity(intent)
}
}
}
override fun onLongItemClick(view: View, postion: Int) {
}
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_search, container, false)
}
private fun configRecyclerView() {
recyclerViewAdapter = RecyclerViewAdapter(requireContext(), searchResult, recyclerViewItemClickListener)
recycler_view.layoutManager = LinearLayoutManager(requireContext())
recycler_view.adapter = recyclerViewAdapter
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
configRecyclerView()
val keyWord = arguments?.getString("key_word")
keyWord?.let {
requestSearchPresenter = RequestSearchPresenter(onRequestSearchResult)
requestSearchPresenter.search(it)
}
}
}
But i move method configRecyclerView() to onDone(), it show on:
override fun onDone(result: NewFeedCollection) {
searchResult = result.post
Toast.makeText(requireContext(), "${searchResult.size}", Toast.LENGTH_SHORT).show()
configRecyclerView()
recyclerViewAdapter.notifyDataSetChanged()
}
in fun onDone you are reassigning the result: searchResult = result.post
Instead of that you have to update the list's reference you've passed to the adapter initially. That means you need to change the code:
from:
searchResult = result.post
to
searchResult.clear();
searchResult.addAll(result.post);
Related
When I click on order menu the app suddenly stopped working, and on the log show this error
image, it says java.lang.IllegalStateException: Fragment already added: InprogressFragment
I have 2 section pager on order menu, it's for inprogress & pastOrders.
here is the code
inProgressFragment:
class InprogressFragment : Fragment(), InprogressAdapter.ItemAdapterCallback {
private var adapter: InprogressAdapter? = null
private var inprogressList: ArrayList<Data>? = ArrayList()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?, savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_inprogress, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
inprogressList = arguments?.getParcelableArrayList("data")
if (!inprogressList.isNullOrEmpty()) {
adapter = InprogressAdapter(inprogressList!!, this)
val layoutManager: RecyclerView.LayoutManager = LinearLayoutManager(activity)
rvList.layoutManager = layoutManager
rvList.adapter = adapter
}
}
override fun onClick(v: View?, data: Data) {
val detail = Intent(activity, OrdersDetailActivity::class.java).putExtra("data", data)
startActivity(detail)
}
}
OrderFragment:
class OrderFragment : Fragment(), OrderContract.View{
lateinit var presenter: OrderPresenter
var progressDialog: Dialog? = null
private var inprogressList: ArrayList<Data>? = ArrayList()
private var pastordersList: ArrayList<Data>? = ArrayList()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?, savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_order, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
initView()
presenter = OrderPresenter(this)
presenter.getTransaction()
}
override fun onTransactionSuccess(transactionResponse: TransactionResponse) {
Log.v("tamvan", "ini token "+IcaCraft.getApp().getToken())
if (transactionResponse.data.isNullOrEmpty()) {
include_toolbar.visibility = View.GONE
ll_tab.visibility = View.GONE
ll_empty.visibility = View.VISIBLE
} else {
for (a in transactionResponse.data.indices) {
// past order
if (transactionResponse.data[a].status.equals("ON_DELIVERY", true)
|| transactionResponse.data[a].status.equals("PENDING", true)) {
inprogressList?.add(transactionResponse.data[a])
// progress
} else if (transactionResponse.data[a].status.equals("DELIVERY", true)
|| transactionResponse.data[a].status.equals("DELIVERED", true)
|| transactionResponse.data[a].status.equals("CANCELLED", true)
|| transactionResponse.data[a].status.equals("SUCCESS", true)) {
pastordersList?.add(transactionResponse.data[a])
}
}
if (inprogressList.isNullOrEmpty() && pastordersList.isNullOrEmpty()) {
include_toolbar.visibility = View.GONE
ll_tab.visibility = View.GONE
ll_empty.visibility = View.VISIBLE
} else {
val sectionsPagerAdapter = SectionsPagerAdapter(
childFragmentManager
)
sectionsPagerAdapter.setData(inprogressList, pastordersList)
//viewPager!!.offscreenPageLimit = 3
viewPager.adapter = sectionsPagerAdapter
tabLayout.setupWithViewPager(viewPager)
}
}
}
override fun onTransactionFailed(message: String) {
Toast.makeText(activity, message, Toast.LENGTH_LONG).show()
}
private fun initView() {
progressDialog = Dialog(requireContext())
val dialogLayout = layoutInflater.inflate(R.layout.dialog_loader, null)
progressDialog?.let {
it.setContentView(dialogLayout)
it.setCancelable(false)
it.window?.setBackgroundDrawableResource(android.R.color.transparent)
}
include_toolbar.toolbar.title = "Your Orders"
include_toolbar.toolbar.subtitle = "Wait for the best meal"
}
override fun showLoading() {
progressDialog?.show()
}
override fun dismissLoading() {
progressDialog?.dismiss()
}
}
SectionPagerAdapter:
class SectionsPagerAdapter(fm: FragmentManager) :
FragmentPagerAdapter(
fm
) {
var inprogressList: ArrayList<Data>? = ArrayList()
var pastOrdersList: ArrayList<Data>? = ArrayList()
override fun getItem(position: Int): Fragment {
var fragment : Fragment
return when (position) {
0 -> {
fragment = InprogressFragment()
val bundle = Bundle()
bundle.putParcelableArrayList("data", inprogressList)
fragment.setArguments(bundle)
return fragment
}
1 -> {
fragment = PastordersFragment()
val bundle = Bundle()
bundle.putParcelableArrayList("data", pastOrdersList)
fragment.setArguments(bundle)
return fragment
}
else -> {
fragment = InprogressFragment()
val bundle = Bundle()
bundle.putParcelableArrayList("data", inprogressList)
fragment.setArguments(bundle)
return fragment
}
}
}
override fun getPageTitle(position: Int): CharSequence? {
return when (position) {
0 -> "In Progress"
1 -> "Past Orders"
else -> null
}
}
override fun getCount(): Int {
return 2
}
fun setData(inprogressListParms: ArrayList<Data>?, pastOrdersListParms: ArrayList<Data>?) {
inprogressList = inprogressListParms
pastOrdersList = pastOrdersListParms
}
}
Try something like this(I didn't test this code, it's just a concept for your app):
enum class FragmentType {
IN_PROGRESS,
POSTORDERS
}
data class Data(
val fragmentType: FragmentType,
val fragmentName: String,
val orderList: ArrayList<Data>?
)
class SectionsPagerAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm) {
var inprogressList: ArrayList<Data> = ArrayList()
override fun getItem(position: Int): Fragment {
val item = inprogressList[position]
return when (item.fragmentType) {
FragmentType.IN_PROGRESS -> {
InprogressFragment().apply {
val bundle = Bundle()
bundle.putParcelableArrayList("data", item.orderList)
setArguments(bundle)
}
}
FragmentType.POSTORDERS -> {
PastordersFragment().apply {
val bundle = Bundle()
bundle.putParcelableArrayList("data", item.orderList)
setArguments(bundle)
}
}
}
}
override fun getPageTitle(position: Int): CharSequence {
return inprogressList[position].fragmentName
}
override fun getCount(): Int {
return inprogressList.size
}
fun setData(items: ArrayList<Data>) {
inprogressList = items
notifyDataSetChanged()
}
}
Here is when the list increase
I call data from API and place it in recycleview horizontal and vertical, but when I try to move on Profile Menu with bottom navigation and back again on Home Menu where my horizontal and vertical recycleview is, the data on recycleview start to increase, it only happen for vertical recycleview
Here is my code:
SectionPagerAdapter for vertical recycleview
class SectionsPagerAdapter(fm: FragmentManager) :
FragmentPagerAdapter(
fm
) {
var new_craft: ArrayList<Data>? = ArrayList()
var popular: ArrayList<Data>? = ArrayList()
var recommended: ArrayList<Data>? = ArrayList()
override fun getItem(position: Int): Fragment {
var fragment : Fragment
return when (position) {
0 -> {
fragment = HomeNewCraftFragment()
val bundle = Bundle()
bundle.putParcelableArrayList("data", new_craft)
fragment.setArguments(bundle)
return fragment
}
1 -> {
fragment = HomePopularFragment()
val bundle = Bundle()
bundle.putParcelableArrayList("data", popular)
fragment.setArguments(bundle)
return fragment
}
2 -> {
fragment = HomeRecommendedFragment()
val bundle = Bundle()
bundle.putParcelableArrayList("data", recommended)
fragment.setArguments(bundle)
return fragment
}
else -> {
fragment = HomeNewCraftFragment()
val bundle = Bundle()
bundle.putParcelableArrayList("data", new_craft)
fragment.setArguments(bundle)
return fragment
}
}
}
override fun getPageTitle(position: Int): CharSequence? {
return when (position) {
0 -> "New Craft"
1 -> "Popular"
2 -> "Recommended"
else -> null
}
}
override fun getCount(): Int {
return 3
}
fun setData(newStateListParms: ArrayList<Data>?, popularListParms: ArrayList<Data>?, recomendedListParms: ArrayList<Data>?) {
new_craft = newStateListParms
popular = popularListParms
recommended = recomendedListParms
}
}
Home Fragment:
class HomeFragment : Fragment(), HomeAdapter.ItemAdapterCallback, HomeContract.View {
private var adapter: HomeAdapter? = null
var progressDialog: Dialog? = null
private var newStateList: ArrayList<Data>? = ArrayList()
private var popularList: ArrayList<Data>? = ArrayList()
private var recomendedList: ArrayList<Data>? = ArrayList()
private lateinit var presenter: HomePresenter
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?, savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_home, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
initView()
presenter = HomePresenter(this)
presenter.getHome()
}
private fun initView() {
progressDialog = Dialog(requireContext())
val dialogLayout = layoutInflater.inflate(R.layout.dialog_loader, null)
progressDialog?.let {
it.setContentView(dialogLayout)
it.setCancelable(false)
it.window?.setBackgroundDrawableResource(android.R.color.transparent)
}
var user = IcaCraft.getApp().getUser()
var userResponse = Gson().fromJson(user, User::class.java)
if (!userResponse.profile_photo_url.isNullOrEmpty()) {
Glide.with(requireActivity())
.load(userResponse.profile_photo_url)
.into(ivProfile)
}
}
override fun onClick(v: View?, data: Data) {
var bundle = Bundle()
bundle.putParcelable("data", data)
val detail = Intent(activity, DetailActivity::class.java).putExtras(bundle)
startActivity(detail)
}
override fun onHomeSuccess(homeResponse: HomeResponse) {
for (a in homeResponse.data.indices) {
var items: List<String> = homeResponse.data[a].types?.split(",") ?: ArrayList()
for (x in items.indices)
{
if (items[x].equals("new_craft", true)) {
newStateList?.add(homeResponse.data[a])
} else if (items[x].equals("recommended", true)) {
recomendedList?.add(homeResponse.data[a])
} else if (items[x].equals("popular", true)) {
popularList?.add(homeResponse.data[a])
}
}
}
adapter = HomeAdapter(homeResponse.data, this)
val layoutManager: RecyclerView.LayoutManager =
LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
rvList.layoutManager = layoutManager
rvList.adapter = adapter
val sectionsPagerAdapter = SectionsPagerAdapter(
childFragmentManager
)
sectionsPagerAdapter.setData(newStateList, popularList, recomendedList)
viewPager.adapter = sectionsPagerAdapter
tabLayout.setupWithViewPager(viewPager)
}
override fun onHomeFailed(message: String) {
Toast.makeText(activity, message, Toast.LENGTH_LONG).show()
}
override fun showLoading() {
progressDialog?.show()
}
override fun dismissLoading() {
progressDialog?.dismiss()
}
}
HomeCraftAdapter: adapter for vertical recycleview
class HomeNewCraftAdapter (
private val listData: ArrayList<Data>,
private val itemAdapterCallback: ItemAdapterCallback
) : RecyclerView.Adapter<HomeNewCraftAdapter.ViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val view = layoutInflater.inflate(R.layout.item_home_vertical, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(listData[position], itemAdapterCallback)
}
override fun getItemCount(): Int {
return listData.size
}
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(data : Data, itemAdapterCallback : ItemAdapterCallback) {
itemView.apply {
tvTitle.text = data.name
tvPrice.formatPrice(data?.price.toString())
rbCraft.rating = data.rate?.toFloat() ?: 0f
Glide.with(context)
.load(data.picturePath)
.into(ivPoster)
itemView.setOnClickListener { view -> itemAdapterCallback.onClick(view, data) }
}
}
}
interface ItemAdapterCallback {
fun onClick(v: View?, data:Data)
}
}
And HomeNewCraftFragment : for vertical recycleview fragment
class HomeNewCraftFragment : Fragment() , HomeNewCraftAdapter.ItemAdapterCallback {
private var adapter: HomeNewCraftAdapter? = null
private var newcraftlist: ArrayList<Data>? = ArrayList()
private var test: String? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?, savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_home_new_craft, container, false)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
newcraftlist = arguments?.getParcelableArrayList("data")
adapter = HomeNewCraftAdapter(newcraftlist!!, this)
val layoutManager: RecyclerView.LayoutManager = LinearLayoutManager(activity)
rcListNewCraft.layoutManager = layoutManager
rcListNewCraft.adapter = adapter
}
override fun onClick(v: View?, data: Data) {
val detail = Intent(activity, DetailActivity::class.java).putExtra("data", data)
startActivity(detail)
}
}
When you leave from your HomeFragment and coming back again, your HomeFragment keeps the old newStateList and add same values in it again. So, you need to empty the values before adding new values.
override fun onHomeSuccess(homeResponse: HomeResponse) {
newStateList = ArrayList() // empty it before load it again.
for (a in homeResponse.data.indices) {
You might need to empty the recomendedList and popularList as well.
This question has been asked multiple times, but the proposed solutions do not function in my specific case.
When the onProjectImageViewClick function is executed I receive the following error:
java.lang.IllegalStateException: Fragment HomeFragment{191080d} (9545b64c-bf0a-4464-8a71-b8c474526181)} not associated with a fragment manager.
One of the proposed solutions was to use the code below to navigate, but since my fragment is detached I can't navigate to the other fragment.
view?.post {
findNavController().navigate(R.id.fragment_project_info)
}
Also, when I troubleshoot using println(Homefragment().isAdded), it returns false, therefore I can't use the solution written above.
Before implementing the firebase database (only using placeholders for my recyclerview), I could navigate to my fragment_project_info.
My Fragment:
class HomeFragment : Fragment(), HomeProjectListAdapter.OnItemClickListener {
private lateinit var auth: FirebaseAuth
private lateinit var databaseReference: DatabaseReference
lateinit var listener: ValueEventListener
var recentPostRef = FirebaseDatabase.getInstance().getReference("projects").limitToLast(50)
val TAG = "loadPostData Result"
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_home, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
auth = Firebase.auth
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
postQueryValueListener()
}
override fun onStart() {
super.onStart()
val currentUser = auth.currentUser
updateUI(currentUser)
}
override fun onProjectImageViewClick(position: Int, projectData: ProjectData) {
findNavController().navigate(R.id.fragment_project_info)
}
private fun updateUI(currentUser: FirebaseUser?){
if(currentUser == null){
upload_button.visibility = View.GONE
projects_button.visibility = View.GONE
}
}
private fun postQueryValueListener() {
listener = recentPostRef.addValueEventListener(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
for (postSnapshot in dataSnapshot.children) {
var list = ArrayList<ProjectData>()
for (dataSnapshot1 in dataSnapshot.children) {
val p: ProjectData? = dataSnapshot1.getValue(ProjectData::class.java)
if (p != null) {
list.add(p)
}
}
var adapter = HomeProjectListAdapter(list, HomeFragment())
recycler_view.adapter = adapter
recycler_view.layoutManager = LinearLayoutManager(context)
recycler_view.hasFixedSize()
}
}
override fun onCancelled(databaseError: DatabaseError) {
Log.w(TAG, "loadPost:onCancelled", databaseError.toException())
}
})
}
override fun onStop() {
super.onStop()
recentPostRef.removeEventListener(listener)
}
}
Here is my adapter:
class HomeProjectListAdapter(
private val projectList: List<ProjectData>,
private val listener: HomeFragment
) : RecyclerView.Adapter<HomeProjectListAdapter.ProjectListViewHolder>() {
val TAG = "loadUserData Result"
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProjectListViewHolder {
val itemView = LayoutInflater.from(parent.context).inflate(R.layout.layout_project_card,
parent, false)
return ProjectListViewHolder(itemView)
}
override fun onBindViewHolder(holder: ProjectListViewHolder, position: Int) {
val currentItem = projectList[position]
Glide.with(holder.projectImageView.context)
.load(currentItem.mainImageURL)
.into(holder.projectImageView)
}
override fun getItemCount() = projectList.size
inner class ProjectListViewHolder(itemView: View): RecyclerView.ViewHolder(itemView),
View.OnClickListener{
var projectImageView: ImageView = itemView.project_card_image
init {
projectImageView.setOnClickListener(this)
}
override fun onClick(v: View?) {
val position = adapterPosition
val projectData: ProjectData = projectList[position]
if (position != RecyclerView.NO_POSITION){
if (v != null) {
if(v.id == R.id.project_card_image) {
listener.onProjectImageViewClick(position, projectData)
}
}
}
}
}
interface OnItemClickListener {
fun onProjectImageViewClick(position: Int, projectData: ProjectData)
}
}
When you run HomeProjectListAdapter(list, HomeFragment()), you're passing in a brand new instance of HomeFragment. That brand new instance is never attached to a FragmentManager.
Instead, you need to pass in your current fragment instance:
var adapter = HomeProjectListAdapter(list, this#HomeFragment)
I'm still trying to wrap my head around working with viewmodels and a bit confused now that I also have a dialog and recyclerview items but will try to be as clear as I can here if I can get any help please.
I have a dialog with items that when one of them is selected and closed should return data to my calling fragment so the selected item is displayed under that view.
However, once the item is selected and the dialog dismissed, I don't see the new selected item as the one showing on the UI but still the old item instead. (When the fragment is first started it displays the item that is set as selected on my list. The selected value is hardcoded at first but updated when the item is clicked and I can see the update has taken place when I debug the viewmodel observer inside the onDismiss method for the dialog).
I'm a couple of hours on this and have tried a few different things such as calling the viewmodel inside onResume or onDismiss and changing the viewmodel to be initiated by by activityViewModels() as per this post but none of these have worked so far and I think I'm stuck at the moment. Below my most recent version of the code.
class CovidCheckInFragment : Fragment(R.layout.fragment_covid_check_in) {
var navController: NavController? = null
private val model: MainViewModel by activityViewModels()
#RequiresApi(Build.VERSION_CODES.M)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
navController = Navigation.findNavController(view)
model.userMutableLiveData.observe(viewLifecycleOwner, Observer<Any?> { list ->
if (list != null)
(list as Iterable<*>).map {
if ((it as ModelDialogOption).selected == true) {
tvHeader.text = it.title
}
}
})
}
}
..
class MyDialogFragment : DialogFragment(), RecyclerDialogOptionsItem.AdapterListener {
private val viewModel: MainViewModel by activityViewModels()
private lateinit var adapter: GroupAdapter<GroupieViewHolder>
var selectedPosition = -1
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setStyle(STYLE_NO_TITLE, R.style.AppTheme_Dialog_Custom)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_dialog, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
rvOptions.layoutManager = LinearLayoutManager(activity)
adapter = GroupAdapter()
rvOptions.adapter = adapter
ivClose.setOnClickListener {
this.dismiss()
}
initViewModel()
}
private fun initViewModel() {
viewModel.userMutableLiveData.observe(this, Observer { list ->
for (i in list!!) {
adapter.add(
RecyclerDialogOptionsItem(
this#MyDialogFragment,
i,
this#MyDialogFragment
)
)
}
})
}
override fun onClickItem(position: Int) {
selectedPosition = position
adapter.notifyDataSetChanged()
Log.i("clicked", "position: $position")
}
}
..
class MainViewModel : ViewModel() {
private var list: ArrayList<ModelDialogOption>? = null
val userMutableLiveData: MutableLiveData<ArrayList<ModelDialogOption>?> = MutableLiveData()
init {
populateList()
userMutableLiveData.value = list!!
}
private fun populateList() {
list = ArrayList()
list!!.add(ModelDialogOption("Prefer not to say", false))
list!!.add(ModelDialogOption("16-39", false))
list!!.add(ModelDialogOption("40-59", true))
list!!.add(ModelDialogOption("60+", false))
}
}
..
class RecyclerDialogOptionsItem(
private val fragment: MyDialogFragment,
private val modelDialogOption: ModelDialogOption,
private val adapterListener: AdapterListener
) : Item<GroupieViewHolder>() {
companion object {
var clickListener: AdapterListener? = null
}
override fun bind(viewHolder: GroupieViewHolder, position: Int) {
viewHolder.apply {
with(viewHolder.itemView) {
tvTitle.text = modelDialogOption.title
clickListener = adapterListener
if (fragment.selectedPosition == position) {
ivChecked.visible()
modelDialogOption.selected = true
} else {
ivChecked.invisible()
modelDialogOption.selected = false
}
itemView.setOnClickListener {
clickListener?.onClickItem(adapterPosition)
}
}
}
}
override fun getLayout() = R.layout.rv_options_item_row
interface AdapterListener {
fun onClickItem(position: Int)
}
}
Thank you very much.
Your main view model should be like this
class MainViewModel : ViewModel() {
private var list: ArrayList<ModelDialogOption>? = null
val userMutableLiveData = MutableLiveData<ArrayList<ModelDialogOption>>()
init {
populateList()
userMutableLiveData.value = list!!
}
private fun populateList() {
list = ArrayList()
list!!.add(ModelDialogOption("Prefer not to say", false))
list!!.add(ModelDialogOption("16-39", false))
list!!.add(ModelDialogOption("40-59", true))
list!!.add(ModelDialogOption("60+", false))
}
fun updateItem(position:Int){
val itemToUpdate = list!!.get(position)
itemToUpdate.selected = !itemToUpdate.selected!!
list!![position] = itemToUpdate
}
fun flushItems(){
userMutableLiveData.value = list!!
}
}
Then from MyDialogFragment Should be like this.
class MyDialogFragment : DialogFragment(), RecyclerDialogOptionsItem.AdapterListener {
private val viewModel: MainViewModel by activityViewModels()
private lateinit var adapter: GroupAdapter<GroupieViewHolder>
var selectedPosition = -1
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setStyle(STYLE_NO_TITLE, R.style.AppTheme_Dialog_Custom)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_dialog, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
rvOptions.layoutManager = LinearLayoutManager(activity)
adapter = GroupAdapter()
rvOptions.adapter = adapter
ivClose.setOnClickListener {
this.dismiss()
}
initViewModel()
}
override fun onDismiss(dialog: DialogInterface) {
super.onDismiss(dialog)
viewModel.flushItems()
}
private fun initViewModel() {
viewModel.userMutableLiveData.observe(this, Observer { list ->
for (i in list!!) {
adapter.add(
RecyclerDialogOptionsItem(
this#MyDialogFragment,
i,
this#MyDialogFragment
)
)
}
})
}
override fun onClickItem(position: Int) {
selectedPosition = position
adapter.notifyDataSetChanged()
viewModel.updateItem(position)
Log.i("clicked", "position: $position")
}
}
In Kotlin, I attach scroll listener to recyclerview in onViewCreated() of fragment.
I load first 20 records, then next 20 and so on..., when I clear data of adapter for the purpose of search and reload with searched data then scroll listener is not working.
I face this issue in load more functionality.
I resolved this by reattaching scroll listener after clear the adapter.
Why scroll listener is detached after clearing adapter?
Below is my fragment
class Fragment: MvpFragment<View, PresenterImpl>(), View{
private lateinit var presenterImpl: PresenterImpl
private lateinit var myListAdapter: MyListAdapter
private var OFFSET: Long = 0
private var layoutManager: LinearLayoutManager? = null
private var mSearchTextWatcher: TextWatcher = object : EditextTextWatcher() {
override fun afterTextChanged(editable: Editable) {
if (TextUtils.isEmpty(editable)) {
addScrool()
myListAdapter.clear()
loadData()
} else {
recyclerView.clearOnScrollListeners()
}
}
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
recyclerView!!.setHasFixedSize(true)
addData!!.visibility = View.GONE
layoutManager = LinearLayoutManager(activity)
recyclerView!!.layoutManager = layoutManager
searchData!!.addTextChangedListener(mSearchTextWatcher)
myListAdapter= MyListAdapter(context!!, mutableListOf<Bean>(), this)
recyclerView!!.adapter = myListAdapter
idBtSearch.setOnClickListener {
searchClick()
}
addScrool()
}
private fun addScrool() {
recyclerView.addOnScrollListener(object : RecyclerViewScrollListener() {
override fun onScrollUp() {
}
override fun onScrollDown() {
}
override fun onLoadMore(totalItemsCount: Int) {
myListAdapter.setLoaded(true)
myListAdapter.notifyItemInserted(myListAdapter.getListSize() - 1)
myListAdapter.notifyDataSetChanged()
OFFSET = totalItemsCount.toLong()
Handler().postDelayed({
if (search_name != null && search_name.text.toString().isEmpty()) {
if (idSortedOption.text == getString(R.string.name)) {
presenterImpl.loadDataByName(context!!, OFFSET, LIMIT)
} else {
presenterImpl.loadDataByDate(context!!, OFFSET, LIMIT)
}
}
}, 1000)
}
})
}
override fun onResume() {
super.onResume()
if (TextUtils.isEmpty(search_patient!!.text.toString())) {
loadData()
} else {
searchClick()
}
OFFSET = 0
}
private fun searchClick() {
val searchText = search_name!!.text.toString()
if (searchText.length < 3) {
Aarogya.showToastShort(context, getString(R.string.pls_enter_at_least_3_char))
} else {
Aarogya.hideKeyboard(activity!!)
presenterImpl.searchData(context!!, search_name!!.text.toString().trim { it <= ' ' }, 1L, 20L)
}
}
override fun createPresenter(): PresenterImpl {
presenterImpl = PresenterImpl(this)
return presenterImpl
}
override fun showData(list: MutableList<Bean>) {
myListAdapter.setLoaded(false)
if (OFFSET == 0L) {
myListAdapter.run {
clear()
addAll(list)
}
} else {
myListAdapter.addAll(list)
}
}
override fun showSearchData(beanList: MutableList<Bean>) {
myListAdapter.setLoaded(false)
myListAdapter.clear()
myListAdapter.addAll(beanList)
}
private fun loadData() {
presenterImpl.loadDataByName(context!!, 0L, LIMIT)
}
companion object {
private val LIMIT = 20L
fun newInstance(): Fragment {
return Fragment()
}
}
}