Coder Social home page Coder Social logo

example not using List about flexibleadapter HOT 40 CLOSED

davideas avatar davideas commented on September 21, 2024
example not using List

from flexibleadapter.

Comments (40)

davideas avatar davideas commented on September 21, 2024

I think it is feasible, it shouldn't have any impact, but I didn't get your use case, can you elaborate more, maybe there's another solutions?

getItemCount() is final because how it is designed the architecture, the SelectableAdapter doesn't know the existence of mItems, so it must always return the real size of the mItems through that method, and so it cannot be changed by the developer.

from flexibleadapter.

davideas avatar davideas commented on September 21, 2024

Some notes:

  • we might consider the Expandable item as an expandable section itself, without assigning it the IHeader interface -> (I still have to test the case when IExpandable object is also a IHeader, for now it can be a ISectionable object holding a header).
  • we have getExpandableOf(child) to retrieve the IExpandable object knowing the child.
  • we have getHeaderOf(item) to retrieve the IHeader object if not null.
  • isHeaderShared() works in both situations: 1. When all ISectionable objects have the reference to the header; 2. When only the first ISectionable object has the reference, others can have a null reference. (I have implemented the Sections feature with this second way, then I added the 1st way).
  • be sure to implement equals() in your model objects that go in the Adapter

(I will add all this in the doc, some time soon).

from flexibleadapter.

farfromrefug avatar farfromrefug commented on September 21, 2024

Ok so my use case is that the actual items are not holded by the adapter but per the section.
Each sections holds an mItems list (+ a header and a footer).
So the adapter actually only knows about n sections. Then it asks the section for the item at position.
I dont want to use the mItems of the adapter for the sake of not duplicating items and creating too many objects in memory.
I think you kind of implemented the ArrayAdapter.
may be it should be a an example of implementing FlexibleAdapter -> ArrayFlexibleAdapter

About getItemCount i don't really see the problem about making it NOT final. Yes it doesn't know about mItems, only that it has getItemCount items. But it's just any one asking the adapter how many items it has in the list? So that's what everyone is doing when using an adapter, and the base class is not final right?
Anyway thanks a lot for those explanations. I will look into it very soon.

from flexibleadapter.

davideas avatar davideas commented on September 21, 2024

Ok, better now.
First, the Adapter must work on a copy of the original list, because: expanding items, displaying extra items as headers, filtering items, add and remove items in the Adapter list depends by the current event. Others libraries actually copy the lists... I think, because it's the only way.
This is important: real Objects are not duplicated, instead, the references are. The subItems references are duplicated only if they are visible as explained above.

For your case (and many others use cases), you can inject in the Adapter only the Expandable items, (sutbItems are not yet injected). If the expand event occurs the Adapter must display the corresponding subItems just after the "parent", and in order to make them actually visible, they have to be inserted as references into the main list (mItems) between the Expandables: that list of references is actually copied inside the mItems not the objects (see AbstractExpandableItem, it is part of your model objects and holds the original subItems list).

  • To count only the "sections" (the expandables in your case), at this point you can use getItemCountOfTypes(viewTypes[]) it will count only the types you pass, the ones known by mItems.
  • To count the sections*subItems, you already know this information, it's in your original list (that must always be synchronized by the developer because of adding/removing events). This original list holds the Expandables with their subItems lists inside. We can evaluate to add the counting of expandable*subItems with a new function in the Adapter to know the total number of the subItems hold by all the expandables currently displayed.

Also, if you enable the option setAutoCollapseOnExpand() you have in the memory (mItems) only the references of the expanded subItems, the references of the ones collapsed are removed from the memory.

from flexibleadapter.

farfromrefug avatar farfromrefug commented on September 21, 2024

Ok could write a little example of doing this?
I am not sure i get how i should handle the mItems. For example i don't see what i should pass to the FlexibleAdapter constructor
THanks

from flexibleadapter.

davideas avatar davideas commented on September 21, 2024

OK, I do here on the fly, it will help me to create a better wiki page later.

Let's say you have to build 1 Expandable object. Your model object, called A, extends the AbstractExpandableItem or implements IExpandable. Then, your model object of subItem is called B. The signatures are:

public class A extends AbstractExpandableItem<ExpandableViewHolder class, B class>;
public class B extends AbstractFlexibleItem<SubItemViewHolder class> [implements IFilterable];
//So it's recognized for the filter functionality.

Check my example app under eu.davidea.examples.models package.
You now create the list of subItems and assign them to the A class:

List<B> subItems = new ArrayList<B>();
subItems.add(new B(..));
...
A a = new A(id).setSubItems(subItems);
//maybe I should change to protected the mSubItems so it's visible in
//the A object and so in the constructor. To analyse..

One of your services holds the original list, so, you can add the A objects to the original list, this list is filled only with types of IExpandable types.

List <A> originalList = new ArrayList<A>();
originalList.add(a);
...

When you create the Adapter, you do so:

mAdapter = new FlexibleAdapter(getCopyOfOriginalList(), listeners);

Here, it's still to evaluate if the Adapter should create the copy of the original list automatically or the list is already passed as a copy. To make a copy: new ArrayList<A>(getOriginalList()); for the moment you should pass a copy.
Also you can create a custom Adapter that extends FlexibleAdapter.
The signature with its constructor is:

public class CustomAdapter extends FlexibleAdapter<Class> {
    public CustomAdapter(List<Class> items, Activity activity) {
        super(items, listeners(represented by the Activity or Fragment object));
    }
}

"Class" should represents all the types the Adapter shall handle, it can be:

  • The most generic possible IFlexible
  • AbstractFlexibleItem
  • Or you can create a common abstract class of your fantasy that in the end will implement the IFlexible and represents all your model objects that have in common many fields, and put this Class name in the signature :-)

I remain open to the changes.

from flexibleadapter.

farfromrefug avatar farfromrefug commented on September 21, 2024

Ok so i had to take another approch.
I can't use your library as it is. Using mItems is not a possibility for me. My main issue is performances, when the list is really long some actions like showAllHeaders or hideAllHeaders can get quite long (you need to remove or add items to the list) when a simple notifyOnDataChanged could be enough.
What i though was best in my case is to still have headers as an adapter item like you do, and mix it with the adapters from @timehop and @edubarr.

So i ended up simplifying (and also disabling a few features) from FlexibleAdapter.
And now i have sticky headers working great (fixed the decoration a bit too).
Normally selection things should still work but i don't have time to test it right now. Will do
You can see it in my fork :
Akylas@feeaa43

What's important is that if you wanted we could merge the two and make you library work with non ArrayList adapters.
You would simply need to inherit the FlexibleAdapter class i simplified and create a FlexibleArrayAdapter class.

Some features don't really make sense without the array(move, ...) because the intelligence needs to be somewhere else.
I need to think about features like expandable cause i think it's doable but it might require some work.

Let me know what you think

from flexibleadapter.

davideas avatar davideas commented on September 21, 2024

You can use the demo and increase headers and subItems to a very high numbers, and see if it's fast enough.

Watch out that, those 2 libraries for sticky header, make lot of work more, I took inspiration from them, but you already saw that my version doesn't have cycles 👍 I saw your modifications in the decoration and in the Adapter, some I like some I need to understand...
In the decoration now getHeader() you return a view: I was saving the reference instead of the position because the position can change as explained before, with the reference you can always retrieve the correct position, no matter the changes applied in mItems. But ok, you removed mItems now :-)
So now you have a sort of Array Adapter over this?

from flexibleadapter.

farfromrefug avatar farfromrefug commented on September 21, 2024

I am not sure i understand what you mean by the position can change?
getHeader() is obviously used to get the header View
Now i also use this as trick to now when a new header appeared on screen.
It works great but may it does not in your case?

Now about my adapter. It is some kind of an array adapter but not managed by the adapter or the recyclerview. Those object are handled separately.
The array is made of Section (a class). Each section handles its items, headerView, filtering, hidden status ...
That's why i could not use your array adapter.

I am still fixing things in my implementation

from flexibleadapter.

farfromrefug avatar farfromrefug commented on September 21, 2024

@davideas I totally rewrote the sticky headers features and i think you are going to like it.
Now i don't "draw" the sticky header. I actually make the View sticky, which means interactions are now possible with the sticky header.

To Do that i had to do something ressembling what you did. I use a special ViewHolder class to find headers.
That ViewHolder wraps the actual ViewHolder returned by the user in a frameLayout.
It had a few consequences:

  • you can't override onCreateViewHolder anymore, instead you get onCreateNormalViewHolder and onCreateHeaderViewHolder. Same goes with getItemViewType and onBindViewHolder
  • you need a sticky holder view to add the sticky header view to. Usually the recyclerView parent is enough.
  • it should be faster as the intelligence is not in each onDraw call but in scroll events.
  • it works in both directions with linear and grid layout.

I will post a video shortly
Akylas@523e278

from flexibleadapter.

farfromrefug avatar farfromrefug commented on September 21, 2024

Image of Yaktocat

from flexibleadapter.

davideas avatar davideas commented on September 21, 2024

@farfromrefug, it works great 👍 Very good... Only need to check/analyse if it is possible to still override onCreateViewHolder. It is an essential part of the new development with the items. During today and next days I will look into your implementation :-)

(This week is very heavy for me, many things are happening).

from flexibleadapter.

farfromrefug avatar farfromrefug commented on September 21, 2024

Yes i understand about onCreateViewHolder. I was wondering if we could make something in the line of what you did. make onCreateViewHolder final but make another one that you can override where any mask is removed. By the mask trick is something you can also use for expandable ....

Take your time!

from flexibleadapter.

davideas avatar davideas commented on September 21, 2024

We can try to merge something, but better to create another branch. I should create it I guess.

from flexibleadapter.

farfromrefug avatar farfromrefug commented on September 21, 2024

Yes i think we can merge that in another branch.
Also what do you think about making all features completely optional?
That would mean using interfaces in FlexibleAdapter instead of inheritance.
I think it's fairly doable.
Also that way users would not have to implement methods for features they dont want.

from flexibleadapter.

davideas avatar davideas commented on September 21, 2024

@farfromrefug, you can make the pull request in the new branch: sticky_views.
I will try to merge everything, and maybe have the array adapter over it or maybe a second adapter, I don't know yet.

from flexibleadapter.

davideas avatar davideas commented on September 21, 2024

@farfromrefug, I started to see your version, basically your version of FlexibleAdapter is an adapter for headers. I was wondering that we keep your abstract implementation for headers and name it HeaderAdapter, and over it we should keep the name FlexibleAdapter with the ArrayList. This is important to maintain compatibility without refactoring the existing name that people are using, me included.

Can you make this refactor and then pull request to branch sticky_views when you have time?
Also, can you move outside the adapter the HeaderViewHolder class into the package eu.davidea.viewholders, I will check later if it may extends FlexibleViewHolder as well.

About the features to put as optional, we might have interfaces, but in somehow they need to implement that, so we can provide an implementation as well (the original idea was to have something already done ready to be used in all project, without implement them again and again).

from flexibleadapter.

farfromrefug avatar farfromrefug commented on September 21, 2024

@davideas You are right it totally needs refactoring !
But i am en thinking about it a step further.
Yesterday i stubbled upon advancedrecyclerview and especially its translator class
And i think this is a great way to handle sections !
But it s also a great way to handle expandables! I thought about it and i think expandable and sections are one and the same. A section is a non expandable expandable :P
So i think i will refactor it removing the "Header" thing and just make it sectionnable.
Are you ok with this? then you might merge expandable with it

from flexibleadapter.

davideas avatar davideas commented on September 21, 2024

@farfromrefug, it's not a bad idea to consider an Expandable as Section/Header itself and make it sticky or non-sticky and expandable or non-expandable, so we can benefit of the expandable feature for the header as well, but better to keep far the project advancedrecyclerview, that project is too far complex and huge.
I also mentioned earlier in this conversation this idea as well, to have expandable as header combined. But we should apply this idea to what you have done for the sticky header and I for the rest.

However, I would like to keep the item interfaces and work around them.

from flexibleadapter.

farfromrefug avatar farfromrefug commented on September 21, 2024

@davideas Totally agree on advancedrecyclerview. I tried to improve it to add sticky. It was far too big!
However the work done with the translator is really a great idea!
The reason is to easily go back and forth between android positioning and section/child position.
If you have a section adapter you will have to go through that.
I already exported that in my adapter and it's working great.

I get that you want to keep your item interface for your array adapter. I propose that i integrate what i have in my branch. You look at it and import what you want.
And i get it if you dont ;)

from flexibleadapter.

davideas avatar davideas commented on September 21, 2024

Yes, for the moment let's do it, and see what is comes.

from flexibleadapter.

davideas avatar davideas commented on September 21, 2024

@farfromrefug, I was looking at your last commit, SectionAdapterHelper.java is it necessary? lot of calculations are there, I do not understand that class to be honest.

from flexibleadapter.

farfromrefug avatar farfromrefug commented on September 21, 2024

@davideas this is actually the whole trick . The idea is to store 2 int into 1 (section index and sectionItemIndex).
That way you can easily store a "map" of your current section layout.
The storing is done in SectionPositionTranslator. SectionAdapterHelper is only a helper class to pack/unpack sectionIndex/sectionItemIndex as bytes.
I am still fixing a few thing. But the sticky header feature will even be faster! The reason is that now it's a lot faster to get sectionIndex/sectionItemIndex from position.

Before everytime we had to go through the sections list, and increment a counter until we find the right position. Now SectionPositionTranslator stores those positions and only update them when necessary (insert, remove, collapse, expand...)

from flexibleadapter.

davideas avatar davideas commented on September 21, 2024

I understand, is what I was trying to avoid, recalculate the positions at every event, also undo, filtering, move. Not only 1 position, but all the subsequent positions. This actually takes long time with many items, instead of just retrieving by reference. Storing positions imply more memory and more process to update them continuously at each change. Don't you think so?

from flexibleadapter.

farfromrefug avatar farfromrefug commented on September 21, 2024

Yes you are right. But your technique only works for array adapter like you do.
Otherwise i don't think it's possible. This solution is generic.
You can easily "deactive it" in your array sub class.
I just pushed all the fixes
BTW: it's a simple loop through all items at first. Something every user still has to do with your array implemention. You need to do it to create the Item object associated with your actual item.

from flexibleadapter.

davideas avatar davideas commented on September 21, 2024

@farfromrefug, this weekend I have some time, do you want to commit on the sticky_views branch, so I can start to review and assimilate your work? Then, if any I will propose my changes :-)

from flexibleadapter.

farfromrefug avatar farfromrefug commented on September 21, 2024

Right all is in my dev branch. I made a few structural changes to make the flexible adapter correctly work with sections.
The thing is that i also needed to add header/footer support to my recyclerview. And as it is related to item/section count i had no choice but to integrate it directly in the flexible adapter. It should also work with your array impl!
Do you want to merge it all? If so you can just merge from my dev branch.

from flexibleadapter.

davideas avatar davideas commented on September 21, 2024

@farfromrefug, I'm working on sections branch, you can checkout it, from now let's use this branch for all modifications, better to not develop on "dev" branch, until the full merge is complete.

I renamed your adapter to FlexibleAdapterSection because I still need to work on the real merge and didn't want to loose my work. I've improved a little bit the current code and added some comments starting with "Davideas". Moved also the ViewHolders under the viewholder package.
Now, I work on the real merge, even if I see it quite hard because it is totally different. The problem I was mentioning about the positions, if we start to remove items and user starts to generate events of collapsing/expanding (for instance) and then again he clicks on Undo, all positions need to be recalculated, so I don't understand the usage of the class SectionPositionTranslator.

Also, if we have multiple view types, onCreate and onBind methods will be multiplied which I think it make more complex the development and the maintenance, if instead we use the items, we delegate the creation and the binding to them we'll have a much cleaner adapter. I will try to do it.

from flexibleadapter.

davideas avatar davideas commented on September 21, 2024

@farfromrefug, probably we don't need any HeaderViewHolders, I see you add the itemView to a FrameLayout (very smart!) so we can take that view from FlexibleViewHolder.itemView directly. The holder is recycled not the view since we keep it inside our FrameLayout, I think we can super optimize this process.
Basically the ViewHolder is perfect as it is until it becomes sticky, in the moment it becomes, the itemView is added to the FrameLayout and so this layout is translated. What do you think?

from flexibleadapter.

farfromrefug avatar farfromrefug commented on September 21, 2024

Well actually the problem i think is not making the view sticky, but instead "unsticking" it. If you don't have the framelayout, how do you know how to add it to ?
I am up for any imrpovement :D
Now HeaderViewHolder is(i think) kind of important. You need to know it s not an item holder. I use it a in the divider item deco for example. I could be used by any deco or layoutManager ...

from flexibleadapter.

davideas avatar davideas commented on September 21, 2024

Hi @farfromrefug, I've committed something in sections branch, basically I've changed the calls getSectionIndex(), getFlatPosition() and similar (which I don't know exactly what they means and do there's no comment on them), because my adapter doesn't have those methods.
I use my getHeaderStickyOn() to identify the header/section object. Code must be fixed more, it works when it recognizes a new section, but the view actually disappears and I don't get it why.
If you execute the demo app you will see. Can you have a look because basically it is your code, I just adapted for my adapter.

from flexibleadapter.

farfromrefug avatar farfromrefug commented on September 21, 2024

Hi @davideas What have you changed in getSectionIndex and getFlatPosition? I don't see any difference.
I have to comment them ;) They are just practical method to switch between Android position (which we call flat position) and the section indexed position.

For example 2 sections with 4 items.
Let's take the first item in the second section.
It's flat position is 4 (simply count all items from start)
It's sectionIndex is 1 (second section)
It's sectionItemIndex is 0 (first item in its section)

Those methods are really important when working with sections.

getHeaderStickyOn is not needed anymore. You don't need a decoration for sticky headers anymore. You needed that function to draw the view, which is not needed anymore

from flexibleadapter.

davideas avatar davideas commented on September 21, 2024

Indeed I've not changed the implementation of the 2 methods, just commented the calls. Also I'm not using decorator anymore but your Headers Manager, doing that I'm trying to reuse my adapter (still named FlexibleAdapter while yours, I renamed into FlexibleAdapterSections to not make confusions).
I've added calls to getHeaderStickyOn() just to identify the section, as said it works but the FrameLayout disappears once getTop() reaches 0, and it seems not traslated when using setTranslationY().
As you see I also use the StickyHeaderViewHolder created inside the HeaderItem in my example.

from flexibleadapter.

davideas avatar davideas commented on September 21, 2024

Hello @farfromrefug, can you explain how this method should be implemented?

/**
 * Returns the view sticky headers will be attached to
 *
 * @return FrameLayout the view
 */
public abstract FrameLayout getStickySectionHeadersHolder();

How the FrameLayout is created, where is it located?
Is it correct if I do return new FrameLayout(mRecyclerView.getContext());? because it seems not rendered.

from flexibleadapter.

farfromrefug avatar farfromrefug commented on September 21, 2024

It s not created. It's the view you want sticky headers to be added to. Most of the time it can be the RecyclerView parent.
You cant return just a new FrameLayout. You must return an existing view.
In my case this is the architecture
FrameLayout
RecyclerView

getStickySectionHeadersHolder only returns the FrameLayout.
It's there to give choice to the user as we don't know what hierarchy might be used.

from flexibleadapter.

davideas avatar davideas commented on September 21, 2024

It starts to work... finally. However, RecyclerView cannot hold the sticky header since addView is used for children with position.

Does FrameLayout includes the RecyclerView or it is placed before?
Also it would be nice to add the FrameLayout programmatically, I tried I didn't succeed, sometimes RecyclerView must be the only child of a ViewGroup this is very important because (for instance) SwipeRefreshLayout wants only 1 child view.

from flexibleadapter.

farfromrefug avatar farfromrefug commented on September 21, 2024

Yes sorry the indentation did not work.
Well if you have a SwipeRefreshLayout do this:

  • FrameLayout
    • SwipeRefreshLayout
      • RecyclerView

If not

  • FrameLayout
    • RecyclerView

from flexibleadapter.

davideas avatar davideas commented on September 21, 2024

I've committed on sections branch my latest change, now it works but code needs to be optimized.
For example it would be nice to add FrameLayout from code.
Now FrameLayout is on user layout at same level of RV and after the RV. In this way a bug (NPE) is avoided when scrolling with SwipeRefreshLayout or CoordinatorLayout on top.

from flexibleadapter.

farfromrefug avatar farfromrefug commented on September 21, 2024

I am not sure i get your point on the FrameLayout being added from code.
As explained this is not possbile and should be handled by user because it depends on the activity layout.

For example in my case i don't even use a FrameLayout i use a custom layout class inheriting FrameLayout

from flexibleadapter.

davideas avatar davideas commented on September 21, 2024

Clickable StickyHeaders merging is now complete, thanks @farfromrefug!
I had to optimize the code for my version, but now it is much better, since it is able to recognize the existing clickListeners with the correct position. The StickyHeaderManager (in my case is an helper) is also optimized. ViewGroup is now semi automatic configured. I will have a look also at fixed header and footer you have done.

List is an essential part of this Adapter and so I cannot remove it, items are by reference and also never fail in case of removal and similar.
I will close this issue, but we can always write here :-)

from flexibleadapter.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.