I am seeking forgiveness for this simple problem. I am using FastAdapter for the first time and I am new to Kotlin.
Let me share the problem.
I have a layout for the recyclerview item holder, an adapter which extends AbstractItem class.
Actually I couldn't format the code correctly here on Stack overflow. So I created the code at GitHub Gist. Here is the link.
In the layout_add_item.xml file, I have two buttons, one's id is addStudent and another one's id is addTeacher.
So, my problem is, these two button's onClickListener is not triggered until I click on the root layout once on every onCreate method is called. If I click on the LinearLayout once, then these two button's onClickEvent get fired normally.
I don't know what's wrong here :-(
Any help would be appreciated. Thanks in advance.
The concept behind the EventHook system exposed in the FastAdapter is meant to ensure listeners are not loosely re-attached everytime the data gets bound to the item, or even worse to introduce memory leaks.
The API itself due to that tries to prevent those various aspects.
Using Kotlin the FastAdapter exposes a method which should simplify this setup procedure some more for you.
For example:
mFastAdapter.addClickListener({ vh: SimpleImageItem.ViewHolder -> vh.imageView }) { view, position, fastAdapter, item ->
// react on the click on the `imageView` of the `SimpleImageItem.ViewHolder`
}
Related
There is a need of sorting record in recycler view adapter, based on the platform chosen from buttons in fragment.
I can't use interface as I already used in Adapter to listen in fragment. if I use interface now it will cause cyclic redundancy.
Can you please let me know the procedure for this. Thanks!
I'm sorry I'm only allowed to upload image links, Thank you very much for all your support and looking forward for the solution!!
you get a variable from the fragment using intent, later you pass that variable to the recycler view through the adapter (create a method to update a variable inside the adapter class) and I'll say to update the adapter everytime your fragment variable changes.
if you provide a screenshot of your code I can give a better answer, it depends how you implemented it.
Basically I have a RecyclerView with chat messages. The scenario is as follows:
I add a single message -> Causes RecyclerView to add a new ViewHolder
Delay of about 2 seconds
I change the first message and add a new one -> Should cause RecyclerView to rebind the first message and create a new ViewHolder for the second one.
My problem lies in step 3. as the first ViewHolder is removed and a new one is created and then bound. This produces a very slight flickering which is a little bit annoying and all in all this shouldn't happen.
I am using DiffUtil to dispatch changes, the whole setup is a little bit more involved so it is hard to describe the whole picture but I narrowed it down to this:
The DiffUtil produces the correct result and calls onItemRangeChanged for the first item and onItemRangeInserted for the second item. For whatever reason the first ViewHolder is then removed and a new on is created, added and then bound.
Did somebody experienced similar behaviour or has a clue why this could be the case? I tried to debug through the RecyclerView code but it is a nightmare and I still don't understand the whole thing. What could be the reason that the first ViewHolder cannot be rebound and a new one has to be created?
If I can provide any more information just ask for it and I will try my best.
A small repository showing the problem can be found here: https://github.com/MaxGierlachowski/recyclerview_viewholder_bug
If you look into the error logs and look at the 4th "MESSAGE" log you see that a onChanged and a onInserted are dispatched to the adapter but there is a new ViewHolder created for the onChanged one. I know that RecyclerView checks for a lot of things like animation completion and so on but I really would like to know why the ViewHolder isn't rebound but recreated.
EDIT:
Something I figured out was that if that createViewHolder is called by the RecyclerView the ViewHolder that should be reused is inside the mChangedScrap list and mState.isPreLayout() is false so the function tryGetViewHolderForPositionByDeadline() doesn't search the mChangedScrap list and creates a new one. Still this shouldn't happen, the ViewHolder isn't even animated or something and it seems like all animations are finished at that point.
Small video of the flickering:
Hey so I figured it out myself but I still don't fully understand why this is necessary. So the ItemAnimator inside RecyclerView decides whether a changed ViewHolder will be just rebound or recreated. It will decide it on three factors that are mentioned in the article below. So basically because I was using the DiffUtil I just had to provide some arbitrary to the onItemRangeChanged call and it would reuse the ViewHolder instead of creating a new one.
It was this article that help me understand the problem:
https://medium.com/android-news/anatomy-of-recyclerview-part-1-a-search-for-a-viewholder-continued-d81c631a2b91
Probably you have a problem with your DiffUtil.Callback. From the documentation, there is a method areItemsTheSame(T oldItem, T newItem) based on the result diff util could remove and add new holder or just update the content of existing holder. Make sure that your implementation is right.
areItemsTheSame -> check for example that left and right holders are the same types of holders.
areContentsTheSame -> here you should check for equality. object1.equals(object2)
Initially I had an activity which shows some data after an api call. Now I need to convert this activity to a recyclerView.
The activity also had some async calls, means after the very first call it takes the data and call the second api and then update the ui.
My project is in mvp architecture. I wanted to know what component can I reuse in my view holder so I can achieve a list similar to my activiy with minimum code. Because copy pasting all the click interactions and api call is of too much pain.
I can provide code samples if needed. Currently I took a list of elements in the beginning for my recyclerview and started redoing the whole work.
Make your methods public which you want to reuse and call them like this
((Activity)holder.itemView.getContext()).method();
When I add page after current page, and flip to it, I see not added page, but cached page.
Is this possible recache pages manually after adding new page if new page is near current page?
P.S. notifyDataSetChanged() in adapter doesn't help.
I apologize as I can't comment so this will have to do as an answer:
This will depend on the adapter you wrote or are using, and the exact method. Namely, if you were using a customized adapter with the appropriate overridden methods [which would be best for anything fairly complicated like this]:
When you add the new fragment/page, add it to the internal list within the page [which should work naturally with the other overridden functions, including getCount()]
Make sure to set up the fragment appropriately and implement its lifecycle accordingly so its data changes. [Ie, this is a possible source for your bug if you're using an adapter] If you merely used the onCreate and other basic lifecycle functions, then it may be an issue where the lifecycle method already occurred so the changes won't be taken place [Possible solution: call a function in this case]
That's the basics of the issue. Without any code for the adapter and how+where it's being used, I can't say much else. Hope this helps.
I have put the all the binding code for UI events on OnCreate(). It has made my OnCreate() huge.
Is there pattern around implementing UI events in android ? Can I add methods in View xml file and then I can put all the handler code somewhere else.
In a nutshell , I think I am asking how can I implement MVVM pattern with android app code ?
Stuff that I do:
Keep all onClick functions in the XML. Avoids a lot of clutter in the Java code.
Initialize event listeners as members of the activity class rather than keeping them in a function. I don't like too many curly braces in my code. Confuses the hell out of me.
If my list adapters get too big I keep them in a separate class rather than as a member of the activity class and then keep all view listeners there in the adapter.
To avoid creating too many onClick functions I sometimes keep one function like onNavigatonClick and then use view.getId() to see which button was clicked. As the XML is not checked for valid function calls, it leads to runtime errors if your function name is wrong.
If a particular view needs a lot of UI interaction code, I create a custom view with a GestureDetector to handle UI interactions.
I guess this is still quite basic as I haven't had much experience with Java yet.
In 1.6 and later you can specify onClick methods in your layout XML file to trim a bit of the fat. I generally just hide it all away in a initUi() method that I have my onCreate method call. This way at least the onCreate is easier to read.
Lots of good answers to this already. :)
If you're using Android 1.6 or later you might find the new fragments API helpful for organizing and partitioning your activities into several logical units.
onCreate is usually the best place for calling setContentView and setting up listeners, but the code for handling the user interractions normally goes in onClick, onTouch, onKey etc. routines.
Maybe if you posted your code we could see what you've done?