Giter Club home page Giter Club logo

oneadapter's People

Contributors

idanatz avatar meruiden avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

oneadapter's Issues

Scroll to first added element

Hello, I use MVVM pattern with OneAdapter in my app. When new element added to 0 position in items list, we need to manually scroll up to see recently added element. If, for example, new element has index 1, then all work correct and there is animation of adding element.
Do you know any way to automatically scroll to top of list when new element has index 0 and old element with index 0 was visible by user before updating?
Or, probably, scroll to top of list always - it also acceptable for me)

Short code fragment to update adapter:

        dialogViewModel.allDialogs.observe(this) { dialogs ->
            oneAdapter.setItems(dialogs)
        }

Update: When elements in the list takes smaller space then available on screen, animation of adding element with 0 index works correct, but after empty space on screen left, list just stop updating even if the user is at the very beginning of the list and expects to see new items from the top.

How do i filter the list ?

hello, first of all thanks for this library. What is the best way to filter between items in a list? remove and add back items or update method?

Random crash in onCreate

Hello!

Sometimes (<1%) there is an exceptiom in onCreate with this stacktrace:

2020-12-05 18:23:07.758 14685-14685/com.sample.app E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.sample.app, PID: 14685
    kotlin.TypeCastException: null cannot be cast to non-null type V
        at com.idanatz.oneadapter.internal.holders.ViewBinder.findViewById(ViewBinder.kt:31)
        at com.sample.app.DialogsActivity$DialogModule$2.invoke(DialogsActivity.kt:50)
        at com.sample.app.DialogsActivity$DialogModule$2.invoke(DialogsActivity.kt:37)
        at com.idanatz.oneadapter.internal.InternalAdapter$register$1$create$1.onBind(InternalAdapter.kt:233)
        at com.idanatz.oneadapter.internal.holders.OneViewHolder.onBindViewHolder(OneViewHolder.kt:51)
        at com.idanatz.oneadapter.internal.InternalAdapter.onBindViewHolder(InternalAdapter.kt:118)
        at com.idanatz.oneadapter.internal.InternalAdapter.onBindViewHolder(InternalAdapter.kt:39)
        at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:7065)
        at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:7107)
        at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:6012)
        at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6279)
        at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6118)
        at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6114)
        at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2303)
        at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1627)
        at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587)
        at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:665)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4134)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3851)
        at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4404)
        at android.view.View.layout(View.java:19692)
        at android.view.ViewGroup.layout(ViewGroup.java:6057)
        at androidx.coordinatorlayout.widget.CoordinatorLayout.layoutChild(CoordinatorLayout.java:1213)
        at androidx.coordinatorlayout.widget.CoordinatorLayout.onLayoutChild(CoordinatorLayout.java:899)
        at androidx.coordinatorlayout.widget.CoordinatorLayout.onLayout(CoordinatorLayout.java:919)
        at android.view.View.layout(View.java:19692)
        at android.view.ViewGroup.layout(ViewGroup.java:6057)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:19692)
        at android.view.ViewGroup.layout(ViewGroup.java:6057)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:19692)
        at android.view.ViewGroup.layout(ViewGroup.java:6057)
        at androidx.appcompat.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:530)
        at android.view.View.layout(View.java:19692)
        at android.view.ViewGroup.layout(ViewGroup.java:6057)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:19692)
        at android.view.ViewGroup.layout(ViewGroup.java:6057)
        at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1791)
        at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1635)
        at android.widget.LinearLayout.onLayout(LinearLayout.java:1544)
        at android.view.View.layout(View.java:19692)
        at android.view.ViewGroup.layout(ViewGroup.java:6057)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at com.android.internal.policy.DecorView.onLayout(DecorView.java:759)
        at android.view.View.layout(View.java:19692)
        at android.view.ViewGroup.layout(ViewGroup.java:6057)
2020-12-05 18:23:07.759 14685-14685/com.sample.app E/AndroidRuntime:     at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2515)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2224)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1410)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6834)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:966)
        at android.view.Choreographer.doCallbacks(Choreographer.java:778)
        at android.view.Choreographer.doFrame(Choreographer.java:713)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:952)
        at android.os.Handler.handleCallback(Handler.java:789)
        at android.os.Handler.dispatchMessage(Handler.java:98)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6809)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
2020-12-05 18:23:07.761 14685-14685/com.sample.app E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.sample.app, PID: 14685
    kotlin.TypeCastException: null cannot be cast to non-null type V
        at com.idanatz.oneadapter.internal.holders.ViewBinder.findViewById(ViewBinder.kt:31)
        at com.sample.app.DialogsActivity$DialogModule$2.invoke(DialogsActivity.kt:50)
        at com.sample.app.DialogsActivity$DialogModule$2.invoke(DialogsActivity.kt:37)
        at com.idanatz.oneadapter.internal.InternalAdapter$register$1$create$1.onBind(InternalAdapter.kt:233)
        at com.idanatz.oneadapter.internal.holders.OneViewHolder.onBindViewHolder(OneViewHolder.kt:51)
        at com.idanatz.oneadapter.internal.InternalAdapter.onBindViewHolder(InternalAdapter.kt:118)
        at com.idanatz.oneadapter.internal.InternalAdapter.onBindViewHolder(InternalAdapter.kt:39)
        at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(RecyclerView.java:7065)
        at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(RecyclerView.java:7107)
        at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(RecyclerView.java:6012)
        at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6279)
        at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6118)
        at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6114)
        at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2303)
        at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1627)
        at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587)
        at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:665)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4134)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3851)
        at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4404)
        at android.view.View.layout(View.java:19692)
        at android.view.ViewGroup.layout(ViewGroup.java:6057)
        at androidx.coordinatorlayout.widget.CoordinatorLayout.layoutChild(CoordinatorLayout.java:1213)
        at androidx.coordinatorlayout.widget.CoordinatorLayout.onLayoutChild(CoordinatorLayout.java:899)
        at androidx.coordinatorlayout.widget.CoordinatorLayout.onLayout(CoordinatorLayout.java:919)
        at android.view.View.layout(View.java:19692)
        at android.view.ViewGroup.layout(ViewGroup.java:6057)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:19692)
        at android.view.ViewGroup.layout(ViewGroup.java:6057)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:19692)
        at android.view.ViewGroup.layout(ViewGroup.java:6057)
        at androidx.appcompat.widget.ActionBarOverlayLayout.onLayout(ActionBarOverlayLayout.java:530)
        at android.view.View.layout(View.java:19692)
        at android.view.ViewGroup.layout(ViewGroup.java:6057)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:19692)
        at android.view.ViewGroup.layout(ViewGroup.java:6057)
        at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1791)
        at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1635)
        at android.widget.LinearLayout.onLayout(LinearLayout.java:1544)
        at android.view.View.layout(View.java:19692)
        at android.view.ViewGroup.layout(ViewGroup.java:6057)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at com.android.internal.policy.DecorView.onLayout(DecorView.java:759)
        at android.view.View.layout(View.java:19692)
        at android.view.ViewGroup.layout(ViewGroup.java:6057)
2020-12-05 18:23:07.761 14685-14685/com.sample.app E/AndroidRuntime:     at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2515)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2224)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1410)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6834)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:966)
        at android.view.Choreographer.doCallbacks(Choreographer.java:778)
        at android.view.Choreographer.doFrame(Choreographer.java:713)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:952)
        at android.os.Handler.handleCallback(Handler.java:789)
        at android.os.Handler.dispatchMessage(Handler.java:98)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6809)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
2020-12-05 18:23:07.761 14685-14685/com.sample.app D/AppTracker: App Event: crash

Code DialogsActivity.kt, line 50:

onBind { model, viewBinder, metadata ->
    viewBinder.findViewById<TextView>(R.id.titleTv).text = model.name
   ...
}

DialogsActivity has DataBinding and ViewBinding, probably. there is some conflict between internal oneAdapter binding?

select all

Hi, how to implement the select all feature?

Support for StateRestorationPolicy

Hi,

Could you add support to get and set the StateRestorationPolicy? this is currently not accessible since the adapter is private.

Edit:
After peeking in OneAdapter.kt it can be done simply by adding this line:

    var stateRestorationPolicy: StateRestorationPolicy
        get() = internalAdapter.stateRestorationPolicy
        set(value) {
            internalAdapter.stateRestorationPolicy = value
        }

and it would be nice if the paginator could also implement some sort of state restoring so that after a state has been restored the pagination can go on where it left off

use setItem, but the onBind method not be invoke

i use setItem(), the onBind{} not be invoke, but UI has changed a little, and then i try invoke notifyDataSetChanged() of recycleview's adapter on next line, the onBind{} is invoked. when i want to delete an item, i use the data to setItem() that has been deleted the item, but the onBind{} not working, throught i have invoke notifyDataSetChanged() on next line, like this:
oneAdapterForOther?.setItems(it)
sharedForOtherRecycler?.adapter?.notifyDataSetChanged()

Inconsistency detected. Invalid view holder adapter positionViewHolder

I followed a basic usage tutorial and I got a exception:

Process: com.example, PID: 13642
    java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder{232efed position=2 id=-969824770, oldPos=0, pLpos:0 scrap [attachedScrap] tmpDetached no parent} androidx.recyclerview.widget.RecyclerView{3f2d670 VFED..... ......I. 0,0-1080,1516 #7f0900e6 app:id/recyclerView}, adapter:com.idanatz.oneadapter.internal.InternalAdapter@65b9de9, layout:androidx.recyclerview.widget.LinearLayoutManager@a556a6e, context:com.example.MainActivity@6c3203e
        at androidx.recyclerview.widget.RecyclerView$Recycler.validateViewHolderForOffsetPosition(RecyclerView.java:5953)
        at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:6137)
        at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6097)
        at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:6093)
        at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2303)
        at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1627)
        at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587)
        at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:665)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep1(RecyclerView.java:4066)
        at androidx.recyclerview.widget.RecyclerView.onMeasure(RecyclerView.java:3515)
        at android.view.View.measure(View.java:24510)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6828)
        at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1552)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:842)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
        at android.view.View.measure(View.java:24510)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6828)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
        at android.view.View.measure(View.java:24510)
        at androidx.recyclerview.widget.RecyclerView$LayoutManager.measureChildWithMargins(RecyclerView.java:9352)
        at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1653)
        at androidx.recyclerview.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1587)
        at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:665)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(RecyclerView.java:4115)
        at androidx.recyclerview.widget.RecyclerView.onMeasure(RecyclerView.java:3521)
        at android.view.View.measure(View.java:24510)
        at android.view.ViewGroup.measureChild(ViewGroup.java:6799)
        at androidx.viewpager2.widget.ViewPager2.onMeasure(ViewPager2.java:482)
        at android.view.View.measure(View.java:24510)
        at android.widget.RelativeLayout.measureChildHorizontal(RelativeLayout.java:735)
        at android.widget.RelativeLayout.onMeasure(RelativeLayout.java:481)
        at android.view.View.measure(View.java:24510)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6828)
        at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1552)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:842)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
        at android.view.View.measure(View.java:24510)
        at android.widget.ScrollView.measureChildWithMargins(ScrollView.java:1414)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
        at android.widget.ScrollView.onMeasure(ScrollView.java:452)
        at android.view.View.measure(View.java:24510)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6828)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
        at androidx.appcompat.widget.ContentFrameLayout.onMeasure(ContentFrameLayout.java:143)
        at android.view.View.measure(View.java:24510)
2019-08-13 12:33:05.879 13642-13642/com.example E/AndroidRuntime:     at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6828)
        at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1552)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:842)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
        at android.view.View.measure(View.java:24510)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6828)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
        at android.view.View.measure(View.java:24510)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6828)
        at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1552)
        at android.widget.LinearLayout.measureVertical(LinearLayout.java:842)
        at android.widget.LinearLayout.onMeasure(LinearLayout.java:721)
        at android.view.View.measure(View.java:24510)
        at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6828)
        at android.widget.FrameLayout.onMeasure(FrameLayout.java:194)
        at com.android.internal.policy.DecorView.onMeasure(DecorView.java:736)
        at android.view.View.measure(View.java:24510)
        at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:3004)
        at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1833)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2122)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1721)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7595)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:966)
        at android.view.Choreographer.doCallbacks(Choreographer.java:790)
        at android.view.Choreographer.doFrame(Choreographer.java:725)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:951)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7319)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:934)

Below you can find my classes.

Model:

class Model(private val id: Long) : Diffable {

    override fun areContentTheSame(other: Any) = other is Model && other.id == id

    override fun getUniqueIdentifier() = id
}

ItemModule:

class ExampleItemModule : ItemModule<Model>() {

    override fun onBind(model: Model, viewBinder: ViewBinder) {
        //unused for now
    }

    override fun provideModuleConfig(): ItemModuleConfig = object : ItemModuleConfig() {
        override fun withLayoutResource() = R.layout.example_item
    }

}

Adapter initialization:

recyclerView.layoutManager = LinearLayoutManager(context)
val oneAdapter = OneAdapter()
        .attachItemModule(ExampleItemModule())
        .attachTo(recyclerView)

oneAdapter.setItems(listOf(Model(1L), Model(2L)))

I execute all of the code on the main thread, so modification on the background thread is not the reason for the exception. I would be very grateful if you consider my request ASAP.

ButterKnife

I thanks for this library, so I want to use ButterKnife to bind my view. I can not this.

Multiple Selection Cancellation Issue When Item Is Not Visible

First of all, thank you very much for this great library. If you start making multiple selections and then want to cancel the selection when the selected item is not visible, the invisible items remain selected. To understand whether it is my mistake, I tried it in the sample application, and I see the same issue here as well.

I am adding a video for better understanding.
https://github.com/ironSource/OneAdapter/assets/45034416/e4905816-59eb-4bc0-8652-6a51dd7c4316

Thank you

IndexOutOfBoundsException: Inconsistency detected

Hello, thank you again for a wonderful library :)

Seems like one of fixed issue present in 2.0.2 version: #3 (comment) + fresh comment.

Issue reproduced many times (but not in 100% of case) when using OneAdapter for search result output.
When search query deleted from EditText and all elements set to adapter again, I got following crash:

java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder{8d1f079 position=650 id=-982111498, oldPos=0, pLpos:0 scrap [attachedScrap] tmpDetached not recyclable(1) no parent} androidx.recyclerview.widget.RecyclerView{e7fe2ea VFED..C.. ......ID 0,147-1080,1272 #7f0a01db app:id/stickerRV}, adapter:com.idanatz.oneadapter.internal.InternalAdapter@a3ef664, layout:a.b.c.ChatActivity$onCreate$layoutManager$1@13990cd, context:a.b.c.ChatActivity@1d3c1e

java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder{1ea3008 position=962 id=-982111498, oldPos=0, pLpos:0 scrap [attachedScrap] tmpDetached not recyclable(1) no parent} androidx.recyclerview.widget.RecyclerView{a1072c1 VFED..C.. ......ID 0,147-1080,1272 #7f0a01db app:id/stickerRV}, adapter:com.idanatz.oneadapter.internal.InternalAdapter@fcde36a, layout:a.b.c.ChatActivity$onCreate$layoutManager$1@3f0505b, context:a.b.c.ChatActivity@ce1c807

I think fast filling and changing data in the adapter can cause this error. Can you check this when you have time?
Thanks)

I read all the relevant information but the pagination does not work

public class Productadaptermodel extends ItemModule {
@NotNull
@OverRide
public ItemModuleConfig provideModuleConfig() {
return new ItemModuleConfig() {
@OverRide
public int withLayoutResource() { return R.layout.layout_category_list; }
};
}

@Override
public void onBind(@NotNull Item<Product> item, @NotNull ViewBinder viewBinder) {
    LayoutCategoryListBinding binding= (LayoutCategoryListBinding) viewBinder.getDataBinding();
    binding.setProduct(item.getModel());
    binding.executePendingBindings();

}

}
////////
class Pagation extends PagingModule{

    @Override
    public void onLoadMore(int i) {
        viewModel.getProductListByPaging(cat_id,String.valueOf(i)).observe(owner, new Observer<Resource<List<Product>>>() {
            @Override
            public void onChanged(Resource<List<Product>> listResource) {
                if (listResource.status.equals(Status.SUCCESS)) {
                    oneAdapter.add(listResource.data);
                }

            }
        });

    }

    @NotNull
    @Override
    public PagingModuleConfig provideModuleConfig() {
        return new PagingModuleConfig() {
            @Override
            public int withVisibleThreshold() {
                return 0;
            }

            @Override
            public int withLayoutResource() {
                return R.layout.item_progress;
            }
        };
    }
}

public class Product implements Serializable, Diffable {
SerializedName("Unique")
@expose
public String unique;
@OverRide
public boolean areContentTheSame(@nonnull Object other) {
return other instanceof Product && unique.equals(((Product) other).unique);
}

@Override
public long getUniqueIdentifier() {
    return UUID.randomUUID().getMostSignificantBits();
}

}
///////
oneAdapter = new OneAdapter(recycler_product)
.attachPagingModule(new Pagation())
.attachItemModule(new Productadaptermodel());

Calling update method force recyclerview to scroll to updated position if not visible

Maybe I am doing something wrong, but I am setting up the Adapter as explained in the documentation (I am using databinding), but when I call the method update() of the OneAdapter instance, the recyclerview scrolls to the updated position if it is not visible.

I dont want this behavior... If it is not visible, it should stay in the same scroll position. Is this behavior expected or there is any way to avoid this?

By the way, great library! Started to using it and it seems very handy.

Invalid view holder adapter position

Hi, the library is really great due to its modular design. It really does help a lot.

Unfortunately I have encountered an issue. I will first show some code, but I do not have a small, executable example at the moment, I might add it later.

My code uses the OneAdapter as follows:

Within the fragment:

recyclerView = view.findViewById(R.id.ingredients_list);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
oneAdapter = new OneAdapter(recyclerView);
oneAdapter.attachEmptinessModule(new PantryEmptinessModule());
oneAdapter.attachPagingModule(new PantryPagingModule());
oneAdapter.attachItemModule(new PantryItemModule());
prepopulateAdapter();

Within prepopulateAdapter (on main thread):

oneAdapter.add(recipes); //recipes is an ArrayList

Within PantryPagingModule:

@Override
public PagingModuleConfig provideModuleConfig() {
    return new PagingModuleConfig() {
        @Override
        public int withVisibleThreshold() {
            return 3;
        }
        @Override
        public int withLayoutResource() {
            return R.layout.load_more_item;
        }
    };
}

@Override
public void onLoadMore(int i) {
     //Recipes are obtained in the background...
     //on main thread
      oneAdapter.add(recipes); //recipes is an ArrayList
}

The item looks as follows:

@PrimaryKey
    public int id;

    @ColumnInfo(name = "name")
    public String name;

    @ColumnInfo(name = "amount")
    public int amount;

    @Override
    public boolean areContentTheSame(@NotNull Object o) {
        if (!(o instanceof Recipe)) {
            return false;
        }
        Ingredient other = (Recipe) o;
        boolean names = this.name.equals(other.name);
        boolean amount = this.amount == other.amount;
        return names && amount;
    }

    @Override
    public long getUniqueIdentifier() {
        return id;
    }

And the error message that sometimes comes when scrolling is:

ava.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder

Now, I have no idea where this error might come from. Maybe we can find a solution to this and fix it. If any more information is needed, I'll be happy to help. Thanks in advance.

Retry button

Is it possible to add retry button (and message TextView to show some error hint message) to paging module? (Like in Android Paging 3).

Multiple ViewType

Hi!

I have this use case. Show admob native Ads in the recycler view. I can use multi modulo adapter, but how can i show Every 3 items of the modulo A, One item of the module B?

Thanks a lot

Load more animation when submit empty list

Hello, in version 2.1.1 there is load more intermediate progress bar when calling
oneAdapter.setItems(listOf())
or
oneAdapter.clear()
if adapter has items previously.

For example, I call this method in swipeRefreshLayout.setOnRefreshListener to clear previously loaded items (and clear onLoadMore with error), then I get two circle animation: one from swipeRefreshLayout, another one from OneAdapter - this looks bad.
image

Probably adapter should not try to load more items, if empty list submitted?

Get Emptiness module programmatically

Hi! very nice library
I'm trying to change programmatically text and lottieview of the emptiness module. This is my flow:

  1. show emptiness module
  2. loading some data in recycler view
  3. swipe to refresh and data now is empty
  4. emptiness module is not showing

or

  1. show emptiness module
  2. loading some data in recycler view
  3. search for some data
  4. data is empty
  5. show emptiness module with a text like "Nothing found during the research"

Thanks!

Selection without long click

First of all thank you for this great library which makes working with RecyclerView much easier.

OneAdapter supports selection with a long click.
Unfortunately i have not yet found a way to enable selection with just a normal (short) click.
My first approach was to clone the project and implement it myself. Unfortunately the project is very complex and i couln't get it done.

Is there any way to enable/implement selection with short clicks? And is there a way to set a default selection?

Any help is appreciated.

Span size with GridLayoutManager

Hi, it's currently not possible to implement spanSizeLookup of GridLayoutManager because we can't access the getItemViewType function of the adapter. so whenever you have a list with a GridLayoutManager the loading icon of the paginator gets fit within the grid size which looks weird

See #16

CalledFromWrongThreadException in 2.1.0

Hello, thanks for update.

Seems like calling oneAdapter.setItems(...) from background thread no longer supported in 2.1.0, but works fine in 2.0.2.
Is it expected behaviour?

Code:

lifecycleScope.launch(Dispatchers.Default) {
    val items = ...
    oneAdapter.setItems(items)
}

Result:

2021-04-05 10:48:06.193 29570-29650/a.b.c E/AndroidRuntime: FATAL EXCEPTION: DefaultDispatcher-worker-2
    Process: a.b.c, PID: 29570
    android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
        at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:8648)
        at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:1533)
		...

Seems like this can easily be fixed with: withContext(Dispatchers.Main) { oneAdapter.setItems(items) }, but probably this should be done on the library side for backwards compatibility?

Get item position from item module

its not possible to make a layout where you have a list where every 1 item it has a darker background

  • light background
  • darker background
  • light background
  • darker background

It would be nice if I could get the item position from the ItemModule so that it would simple be:

val darkBackground = position % 2 == 1

from the onBind function

Preselected Items

Good day. Tell me if it is possible to somehow pre-select some elements of the list when forming the adapter elements?

Selection disable other clicks

Hi,

When I set a SelectionState in a Module with selectionTrigger set to Click, it disable any other click event that could happend on the module view.

I know for sure the issue is from the SelectionState because it works properly if I set to 'false' the 'enable' property in the SelectionState config.

Is it an expected behavior, is there a workaround ?

Thanks

btw: when a SelectionState is set in a module, the onBind method of that module is never called. So the onBind method of the SelectionState must contain all of the binding. If that's the expected bahavior, please precise it in the Readme, cost me some time.

Ability to use Unique Identifier of String Type

The ability to use the Unique Identifier of Long Type can't satisfy every situation.

For example, the data which is Synced with Firebase (Realtime Database) can't have IDs Long values. Support Dynamic Type Support in Diffable

Diffable<Long> or Diffable<String>

View Binding with Kotlin 1.6.0 not working

Hey there,

as of today i tried migrating an older app and now i am required to use Kotlins Android View Binding with kotlin 1.6.0.

I followed the example in the readme but i cant make it to work.
This is how my code looks:

class DiscoveredDeviceModule(
    val context: Context,
    private val callback: DeviceModuleCallbackListener?
) : ItemModule<DiffableDevice>() {
    init {
        config {
            layoutResource = R.layout.component_discover_bt_list_item

            firstBindAnimation = AnimatorInflater.loadAnimator(
                context,
                R.animator.animator_new_bt_device_discovered
            )
        }

        onBind { item, viewBinder, _ ->
            viewBinder.bindings(ComponentDiscoverBtListItemBinding::bind).run {
                btListItemTitle.text = item.getReadableName(context.resources)
                // PushDownAnim.setPushDownAnimTo(btListItemWrapper)

                btListItemWrapper.setOnClickListener {
                    btListItemProgress.visibility = View.VISIBLE
                    callback?.onClick(item)
                }
            }
        }
    }

    interface DeviceModuleCallbackListener {
        fun onClick(device: DiffableDevice) {}
    }
}

Everytime the onBind should have been called, nothing appears in the view.
Any help?

The version i'm using is 2.1.1

Blinking elements when fragment resumes

I followed the Databinding example and noticed that everytime I leave the fragment and return to it, the elements inside oneadapter redraw. Is this expected or did I miss something?

Typo in readme

The readme docs for adding event hooks show the following example code:

val oneAdapter = OneAdapter(recyclerView)
    .attachItemModule(MessageModule()).addEventHook(MessageClickEvent())
    ...

there is a parenthese misplaced.

Correct:

val oneAdapter = OneAdapter(recyclerView)
    .attachItemModule(MessageModule().addEventHook(MessageClickEvent()))
    ...

Vertical Swipe Direction

Hi,

since RecyclerViews can be in horizontal mode (i.e. items are laid out horizontally), it would be great to have vertical swipe directions, i.e. SwipeDirection.UP and SwipeDirection.DOWN.

As a matter of fact, that would be really great for me to have right now...

Thanks for reading and keep up the great work!

Question:Paging with Room Datasource

Hi, this is more a question than an issue, related to Room Datasource+LiveData PagedList.
I want to use selectable item feature of the OneAdapter, so i am trying to change currently working RecyclerView with PagedListAdapter.
But for OneAdapter, i need to ask PagedList from Room datasource to load next items , which i could not find how can it be done. As i understand PagedListAdapter requests next loading of items automatically by calculating Item size and recyclerview viewport size. and calls pagedlist.loadAround(Int) . I am not sure about the Int value passed here, its probably the internally maintained enumerated index of current list. I could not find how can i request next page to load in viewmodel. Did anyone can direct me how to use Room Paging Datasource with OneAdapter.?

OneAdapter Impl

object OneAdapters {

    fun create(recyclerView: RecyclerView, onClick:(ModelEntity)->Unit,onCurrentBind:(Int)->Unit,loadMoreCall:(Int)->Unit) =OneAdapter(recyclerView){
        itemModules+=ExperimentModelItem(onClick,onCurrentBind)
        pagingModule=PagingModuleImpl(loadMoreCall)
    }


    internal class ExperimentModelItem(onClick: (ModelEntity) -> Unit,onCurrentBind: (Int) -> Unit) : ItemModule<ModelEntity>() {

        init {
            config {
                layoutResource = R.layout.item_tile_list
            }
            onBind { model, viewBinder, metadata ->

                viewBinder.bindings(ItemTileListBinding::bind).run {
                    onCurrentBind(metadata.position)
                    title.text = model.modelname
                    model.modified_at?.let { d ->
                        subtitle.text = "modified ${DateFormatHelper.readable(d)}"
                    }
                }
            }
            onUnbind { model, viewBinder, _ ->
            }

            eventHooks += ClickEventHook<ModelEntity>().apply {
                onClick { model, viewBinder, _ ->
                    onClick(model)
                }
            }
        }

    }
    internal class PagingModuleImpl(loadMoreCall:(Int)->Unit) : PagingModule() {
        init {
            config {
                layoutResource = R.layout.item_loading_progress// can be some spinner animation
                visibleThreshold = 0 // invoke onLoadMore 3 items before the end
            }
            onLoadMore { currentPage ->
                // place your load more logic here, like asking the ViewModel to load the next page of data.
                loadMoreCall(currentPage)
            }
        }
    }
}

Activity

private var mListMaxPosition: Int = 0
    private val mRecyclerAdapter: OneAdapter by lazy {
        OneAdapters.create(binding.explistActivityRecylerview, onClick = {
            // navigate
        },
            onCurrentBind = {
                if (it > mListMaxPosition)
                    mListMaxPosition = it 
            },
            loadMoreCall = {
                viewmodel.add(VMEvent.LoadMore(mListMaxPosition))
            })
    }

viewmodel

init{
 val factory =repo.getAllModelsFactory()
        val config = PagedList.Config.Builder()
            .setEnablePlaceholders(false) // when true, the oneadapter's internal adapter crash on validating list having null models   
            .setInitialLoadSizeHint(15)
            .setPageSize(5).build()

        val pagedListBuilder: LivePagedListBuilder<Int, ModelEntity>  = LivePagedListBuilder<Int,ModelEntity>(
            factory,
            config
            )
models=pagedListBuilder.build() // observed LiveData in activity
}
fun    onLoadMore(currentPage:Int) // called from activity, 
{
   models.value?.let {
     // it.loadAround(currentPage) // max intPosition comming from activity
    //it.loadAround(it.lastKey as Int)

   }
 
}

Problem pagination

In pagination, after adding new items, you return to the top of the list and new items are added to the bottom of the list.

Adapter stops loading data if scrolled rapidly

I am using OneAdapter along with the Paging module to load images gradually from an API. The problem is that if I scroll the list rapidly the paging stops and no more data is loaded after 3-4 pages.

I am attaching the all the necessary code that I am using below.

HomeFragment

class HomeFragment : BaseFragment() {
private val viewModel by viewModel<HomeViewModel>() // Lazy inject ViewModel
private lateinit var homeAdapter: OneAdapter

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    // Inflate the layout for this fragment
    return inflater.inflate(R.layout.fragment_home, container, false)
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    setupRecyclerView()
    observeImagesLiveData()
}

private fun setupRecyclerView() {
    rvHome.layoutManager = GridLayoutManager(context, 2)
    homeAdapter = OneAdapter()
        .attachItemModule(HomeItem(context!!))
        .attachPagingModule(HomePagingModule(viewModel))
        .attachTo(rvHome)

    homeAdapter.setItems(emptyList())
}

private fun observeImagesLiveData() {
    viewModel.getPicsumImages(1).observe(this, Observer { result ->
        when (result) {
            is Result.Loading -> {
                Timber.e("Loading")
            }

            is Result.Success<*> -> {
                val imagesList = result.data as List<PicsumPhoto>
                homeAdapter.add(imagesList)
            }

            is Result.Error -> {
                Timber.e(result.errorMessage)
            }
        }
    })
}}

ItemModule

class HomeItem(context: Context) : ItemModule<PicsumPhoto>() {

private val displayMetrics = context.resources.displayMetrics
private val columnWidth = displayMetrics.widthPixels / 2

override fun provideModuleConfig() = object : ItemModuleConfig() {
    override fun withLayoutResource() = R.layout.item_home
}

override fun onBind(model: PicsumPhoto, viewBinder: ViewBinder) {
    val mainImage: ImageView = viewBinder.findViewById(R.id.ivMainHomeItem)

    mainImage.apply {
        layoutParams.height = columnWidth
        layoutParams.width = columnWidth
        load(model.download_url)
    }

}}

PagingModule

class HomePagingModule(private val homeViewModel: HomeViewModel) : PagingModule() {

override fun provideModuleConfig() = object : PagingModuleConfig() {
    override fun withLayoutResource() = R.layout.load_more
    override fun withVisibleThreshold() = 3
}

override fun onLoadMore(currentPage: Int) {
    homeViewModel.getPicsumImages(currentPage + 1)
}}

Can't display items

Hi,

I recently discovered your API and it looks great at first look.

But I tried to implement a very basic example and impossible to get a result.

Here my files:

MainActivity

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val recycler = findViewById<RecyclerView>(R.id.recycler)

        val oneAdapter = OneAdapter()
            .attachItemModule(CardModule())
            .attachTo(recycler)

        val list = (0 until 100).map { CardModel("Card $it") }.toList()

        oneAdapter.setItems(list)


    }
}

CardModel

class CardModel(val title: String = "Title"): Diffable {

    private val id: Int = Random().nextInt()


    override fun areContentTheSame(other: Any): Boolean {
        return other is CardModel && title == other.title
    }

    override fun getUniqueIdentifier(): Long {
        return id.toLong()
    }
}

CardModule

class CardModule: ItemModule<CardModel>() {

    override fun onBind(model: CardModel, viewBinder: ViewBinder) {
        viewBinder.findViewById<TextView>(R.id.card_module_title).text = model.title
    }

    override fun provideModuleConfig(): ItemModuleConfig = object: ItemModuleConfig() {
        override fun withLayoutResource(): Int = R.layout.card_module
    }

}

card_module.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <TextView
        android:id="@+id/card_module_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

activity_main.xml

<androidx.constraintlayout.widget.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler"
        android:layout_width="match_parent"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_height="0dp" />

</androidx.constraintlayout.widget.ConstraintLayout>

There is no crash nor explicit error.
My MainActivity just stay perfectly empty.

Is there something I misunderstood ?

Again: IllegalStateException: Two different ViewHolders have the same stable ID....

Hi,

I appear to have the same problem again that I have had numerous times before, plus an additional but maybe related problem. Skip to the bottom to see a summary.

Exception:

2020-07-21 22:02:09.269 8841-8841/de.mariushubatschek.virtuellelehrpfade E/AndroidRuntime: FATAL EXCEPTION: main
    Process: de.mariushubatschek.virtuellelehrpfade, PID: 8841
    java.lang.IllegalStateException: Two different ViewHolders have the same stable ID. Stable IDs in your adapter MUST BE unique and SHOULD NOT change.
     ViewHolder 1:ViewHolder{ee6663e position=8 id=-1687197900, oldPos=-1, pLpos:-1 not recyclable(1)} 
     View Holder 2:ViewHolder{d9b71cb position=5 id=-1687197900, oldPos=-1, pLpos:-1} androidx.recyclerview.widget.RecyclerView{c4902e4 VFED..... ......ID 0,0-733,100 #7f080130 app:id/photoRecyclerView}, adapter:com.idanatz.oneadapter.internal.InternalAdapter@a4fe34d, layout:androidx.recyclerview.widget.LinearLayoutManager@5d36e02, context:de.mariushubatschek.virtuellelehrpfade.MainActivity@d9a6051
        at androidx.recyclerview.widget.RecyclerView.handleMissingPreInfoForChangeError(RecyclerView.java:4268)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep3(RecyclerView.java:4192)
        at androidx.recyclerview.widget.RecyclerView.dispatchLayout(RecyclerView.java:3862)
        at androidx.recyclerview.widget.RecyclerView.onLayout(RecyclerView.java:4404)
        at android.view.View.layout(View.java:20672)
        at android.view.ViewGroup.layout(ViewGroup.java:6194)
        at androidx.constraintlayout.widget.ConstraintLayout.onLayout(ConstraintLayout.java:1915)
        at android.view.View.layout(View.java:20672)
        at android.view.ViewGroup.layout(ViewGroup.java:6194)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:20672)
        at android.view.ViewGroup.layout(ViewGroup.java:6194)
        at androidx.constraintlayout.widget.ConstraintLayout.onLayout(ConstraintLayout.java:1915)
        at android.view.View.layout(View.java:20672)
        at android.view.ViewGroup.layout(ViewGroup.java:6194)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:20672)
        at android.view.ViewGroup.layout(ViewGroup.java:6194)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:20672)
        at android.view.ViewGroup.layout(ViewGroup.java:6194)
        at androidx.constraintlayout.widget.ConstraintLayout.onLayout(ConstraintLayout.java:1915)
        at android.view.View.layout(View.java:20672)
        at android.view.ViewGroup.layout(ViewGroup.java:6194)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:20672)
        at android.view.ViewGroup.layout(ViewGroup.java:6194)
        at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1812)
        at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1656)
        at android.widget.LinearLayout.onLayout(LinearLayout.java:1565)
        at android.view.View.layout(View.java:20672)
        at android.view.ViewGroup.layout(ViewGroup.java:6194)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at android.view.View.layout(View.java:20672)
        at android.view.ViewGroup.layout(ViewGroup.java:6194)
        at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1812)
        at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1656)
        at android.widget.LinearLayout.onLayout(LinearLayout.java:1565)
        at android.view.View.layout(View.java:20672)
        at android.view.ViewGroup.layout(ViewGroup.java:6194)
        at android.widget.FrameLayout.layoutChildren(FrameLayout.java:323)
        at android.widget.FrameLayout.onLayout(FrameLayout.java:261)
        at com.android.internal.policy.DecorView.onLayout(DecorView.java:753)
        at android.view.View.layout(View.java:20672)
        at android.view.ViewGroup.layout(ViewGroup.java:6194)
        at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2792)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2319)
2020-07-21 22:02:09.269 8841-8841/de.mariushubatschek.virtuellelehrpfade E/AndroidRuntime:     at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1460)
        at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7183)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:949)
        at android.view.Choreographer.doCallbacks(Choreographer.java:761)
        at android.view.Choreographer.doFrame(Choreographer.java:696)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:935)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

What did I do?

I added 4 items to a RecyclerView backed with a OneAdapter.

How do I setup the RecyclerView and OneAdapter in question?

In the Fragment:

val photoRecyclerView = view.findViewById<RecyclerView>(R.id.photoRecyclerView)
val layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
photoRecyclerView.layoutManager = layoutManager
val snapHelper = LinearSnapHelper()
snapHelper.attachToRecyclerView(photoRecyclerView)
photosOneAdapter = OneAdapter(photoRecyclerView)
    photosOneAdapter
            .attachItemModule(PhotoItemModule(requireContext()))
            .attachEmptinessModule(VoiceOverEmptinessModule())

PhotoItemModule:

class PhotoItemModule (val context: Context) : ItemModule<Photo>() {

    override fun onBind(item: Item<Photo>, viewBinder: ViewBinder) {
        val imageView = viewBinder.findViewById<ImageView>(R.id.imageView)
        val imageUri = FileStorage.getFileUri(context, item.model.imagePath)
        Glide.with(context).load(imageUri).thumbnail(0.2f).override(200,100).fitCenter().diskCacheStrategy(DiskCacheStrategy.ALL).into(imageView)
    }

    override fun provideModuleConfig() = object : ItemModuleConfig() {
        override fun withLayoutResource() = R.layout.photo_item
    }

}

VoiceOverEmptinessModule:

class VoiceOverEmptinessModule : EmptinessModule() {
    override fun provideModuleConfig() = object : EmptinessModuleConfig() {
        override fun withLayoutResource() = R.layout.empty_recycler
    }
}

The item:

public class Photo implements Diffable {

    private static volatile int currentId = 0;

    private static final Object lock = new Object();

    private long id;

    private String imagePath;

    public Photo() {
        //TODO: Do this differently in production?
        synchronized (lock) {
            id = ++currentId;
            Timber.e("id is %d", id);
        }
    }

    public void setImagePath(String imagePath) {
        this.imagePath = imagePath;
    }

    public String getImagePath() {
        return imagePath;
    }

    public void setId(long id) {
        this.id = id;
    }

    public long getId() {
        return id;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Photo photo = (Photo) o;
        return id == photo.id &&
                Objects.equals(imagePath, photo.imagePath);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, imagePath);
    }

    @Override
    public boolean areContentTheSame(@NotNull Object o) {
        if (!(o instanceof Photo)) {
            return false;
        }
        Photo other = (Photo) o;
        return other.id == id && other.imagePath.equals(imagePath);
    }

    @Override
    public long getUniqueIdentifier() {
        return id;
    }
}

How do I add items to the adapter?

In the Fragment:

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        createMarkerDialogViewModel.photoListLiveData.observe(viewLifecycleOwner, Observer {
            photosOneAdapter.clear() //Why is this here? See point number 1 in the questions section
            photosOneAdapter.add(it)
            Timber.e("item count is ${photosOneAdapter.itemCount} while size is ${it.size}")
        })
    }

Here, createMarkerDialogViewModel is a ViewModel and photoListLiveData is a LiveData.

What do I see on the screen before the app crashes?

The following screenshot was taken after the third item was inserted. NOTE that each pair of the picture and the "a>z"-Image consitutes one item, but we count at least five pairs, i.e. at least 5 items:
Screenshot_1595362863

My questions

  1. Why does the photosOneAdapter.clear() call not seem to work?
  2. Why are there at least 5 items visible after adding only 3?
  3. Why does that nasty exception occur? Am I doing anything wrong?

If anything is unclear or I forgot something, notify me and I'll provide the necessary information. Since this is part of a larger project at uni I can't really show the whole source, but I'll do my best to help.

Can we call next page with Paging Module to load without scrolling

Hi @ironsrc,

Thanks for the library. Have been using it quite a number of my projects but have recently ran into a problem that the API response has only 10 items and the UI doesn't cover whole page and due to that the scroll event of recyclerview is not called.

Is there any way or function can make the Paging module load the next page without scrolling.

Any help would be appreciated.

SetItems very slow

Disclaimer: I measured the execution time of this function by displaying timestamp just before and just after call. Apparently, it only takes 1ms to execute. If this function does not use different threads, the problem may not come from it.

I am trying to display some objects but it seems to be taking much longer than expected. The GUI freezes for 6~7s so I am sure it's a process executed on the Main Thread.

Here my Diffable :

class ExpansionDiffable(val expansion: Expansion): Diffable {

    override fun areContentTheSame(other: Any): Boolean {
        return other is ExpansionDiffable
                && other.expansion.count == expansion.count
                && other.expansion.countOwned == expansion.countOwned
                && other.expansion.price == expansion.price
                && other.expansion.priceOwned == expansion.priceOwned
                && other.expansion.body == expansion.body
    }

    override fun getUniqueIdentifier(): Long {
        return expansion.idExpansion.toLong()
    }
} 

And here my Module

class ExpansionModule: ItemModule<ExpansionDiffable>() {
    override fun onBind(model: ExpansionDiffable, viewBinder: ViewBinder) {
        val name: TextView = viewBinder.findViewById(R.id.name)
        val progress: CircleProgressView = viewBinder.findViewById(R.id.progress)
        val abbreviation: TextView = viewBinder.findViewById(R.id.abbreviation)
        val count: TextView = viewBinder.findViewById(R.id.count)
        val worth: TextView = viewBinder.findViewById(R.id.worth)
        val releaseDate: TextView = viewBinder.findViewById(R.id.releaseDate)


        name.text = model.expansion.name
        progress.set(model.expansion.countRatio)
        abbreviation.text = model.expansion.abbreviation
        releaseDate.text = model.expansion.releaseDateLimited

        if (!model.expansion.isReleased)
            releaseDate.textColor = context.getColor(R.color.red_A200)
        else
            releaseDate.textColor = context.getColor(R.color.md_black_1000)

        count.text = "${model.expansion.countOwned}/${model.expansion.count}"
        worth.text = model.expansion.priceOwned.toPriceString()
    }

    override fun provideModuleConfig(): ItemModuleConfig = object: ItemModuleConfig() {
        override fun withLayoutResource(): Int = R.layout.expansion_module
    }
}

For information, there are around 500 Expansions to display.
Do you think that the slowdown observed could come from your library?

You can't use interface as M : Diffable in intem module

Because of line 12 in com.idanatz.oneadapter.internal.utils in generic.kt you can't use ItemModule with interfaces as in

class MyModule() : ItemModule<SomeInterface>

SomeInterface being

interface SomeInterface { ... }

It causes crash.
It's because you are using
if (className.startWith("class ")) { }
And class name for interface starts with "interface "

You can use abstract class tho since its class name starts with "class " but it simply will do nothing since you can have object with class name of abstract class, and thats how library indentifies types

Also im certain that what you are implementing here is just
type.typeName

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.