All Projects → stanmots → RxDiffUtil

stanmots / RxDiffUtil

Licence: MIT License
A lightweight Rx wrapper around DiffUtil with Activity lifecycle support (Deprecated)

Programming Languages

java
68154 projects - #9 most used programming language
shell
77523 projects

Projects that are alternatives of or similar to RxDiffUtil

RxPagination
Implement pagination in just few lines with RxPagination
Stars: ✭ 20 (-33.33%)
Mutual labels:  recyclerview, rxjava2
Androidproject
Android 技术中台,但愿人长久,搬砖不再有
Stars: ✭ 4,398 (+14560%)
Mutual labels:  recyclerview, rxjava2
CarouselGifViewer
Efficiently display a list of GIFs in a carousel (RecyclerView).
Stars: ✭ 33 (+10%)
Mutual labels:  recyclerview, rxjava2
Featureadapter
FeatureAdapter (FA) is an Android Library providing an optimized way to display complex screens on Android.
Stars: ✭ 112 (+273.33%)
Mutual labels:  recyclerview, rxjava2
Android-Code-Demos
📦 Android learning code demos.
Stars: ✭ 41 (+36.67%)
Mutual labels:  recyclerview, rxjava2
Pursuit-Core-Android
Pursuit Core Android
Stars: ✭ 45 (+50%)
Mutual labels:  recyclerview, rxjava2
Base Mvvm
App built to showcase basic Android View components like ViewPager, RecyclerView(homogeneous and heterogeneous items), NavigationDrawer, Animated Vector Drawables, Collapsing Toolbar Layout etc. housed in a MVVM architecture
Stars: ✭ 18 (-40%)
Mutual labels:  recyclerview, rxjava2
Android
Step by step guide for various components in android
Stars: ✭ 32 (+6.67%)
Mutual labels:  recyclerview, rxjava2
codeKK-Android
http://p.codekk.com/
Stars: ✭ 29 (-3.33%)
Mutual labels:  recyclerview, rxjava2
FastScroll-RecyclerView
ReyclerView with fast scrolling and scroll popups
Stars: ✭ 37 (+23.33%)
Mutual labels:  recyclerview
Football-App
⚽ Football App using MVVM, LiveData, RxJava2, DI, Room, Repository Patern
Stars: ✭ 17 (-43.33%)
Mutual labels:  rxjava2
SlideTable
可以滑动 以表格形式展示数据
Stars: ✭ 14 (-53.33%)
Mutual labels:  recyclerview
devbricksx-android
DevBricksX provides plenty of useful classes that will be used in daily Android development.
Stars: ✭ 22 (-26.67%)
Mutual labels:  recyclerview
react-native-nlist
原生Listview Native lListView react-native encapsulation Memory recovery reusing High performance
Stars: ✭ 60 (+100%)
Mutual labels:  recyclerview
android-live-broadcasts
Live broadcast receiver library for Android
Stars: ✭ 19 (-36.67%)
Mutual labels:  rxjava2
LifecycleCells
An Android library that provides a Lifecycle to any ViewHolder through the implementation of the LifecycleOwner interface, allowing it to interact with a Lifecycle-Aware Component.
Stars: ✭ 19 (-36.67%)
Mutual labels:  recyclerview
kandy
Sweet Android libraries written in Kotlin
Stars: ✭ 19 (-36.67%)
Mutual labels:  recyclerview
android-tableview-kotlin
Android's missing TableView component.
Stars: ✭ 40 (+33.33%)
Mutual labels:  recyclerview
Android-RecyclerViewHelper
RecyclerView的工具类,更方便的实现Adapter,item点击事件,更快的实现加载提示,分页加载。
Stars: ✭ 31 (+3.33%)
Mutual labels:  recyclerview
ErisCasper.java
Java library for making Discord bots
Stars: ✭ 15 (-50%)
Mutual labels:  rxjava2

Warning: No Longer Maintained.

RxDiffUtil

Build Status codecov license Download Maven Central

RxDiffUtil is a lightweight Rx wrapper around DiffUtil from Android support library.

Under the hood it automates a lot of things, such as background processing of multiple calculateDiff operations, binding to Activity lifecycle (AppCompatActivity is also supported), automatic RecyclerView.Adapter updating etc.

The library is fully compatible with RxJava2. It's very flexible - you can configure it very easily to suit your needs. 🤘🎉


Requirements

  • minSdkVersion: 14

Dependency

  • Gradle
compile 'io.github.storix:rxdiffutil:0.3.2'
  • Maven
<dependency>
  <groupId>io.github.storix</groupId>
  <artifactId>rxdiffutil</artifactId>
  <version>0.3.2</version>
  <type>pom</type>
</dependency>
  • Ivy
<dependency org='io.github.storix' name='rxdiffutil' rev='0.3.2'>
  <artifact name='rxdiffutil' ext='pom' ></artifact>
</dependency>

What is this all about?

Using RecyclerView (and RecyclerView.Adapter as a consequence) we often encounter situations when we need to make a lot of changes to the data source and then notify somehow our adapter in the most efficient way 📈.

The Android developers can use the following methods to notify the adapter about the underlying model changes:

Method Description
notifyItemChanged(int pos) Notify that item at position has changed.
notifyItemInserted(int pos) Notify that item reflected at position has been newly inserted.
notifyItemRemoved(int pos) Notify that items previously located at position has been removed from the data set.
`notifyDataSetChanged()` | Notify that the dataset has changed. Use only as last resort.

Note: check out this amazing tutorial to know more about RecyclerView configuration.

Ok, cool. Imagine we have inserted a new item at the beginning of our model list, we must then notify the adapter as follows:

// Notify the adapter that an item was inserted at position 0
adapter.notifyItemInserted(0)

And then we've removed some item in the middle. And then changed 50 scattered items. This becomes not cool very quickly 😓. Especially taking into account that our lists can be pretty large.

Of course, we could just call notifyDataSetChanged(). However, it's NOT recommended to do that. notifyDataSetChanged() eliminates the ability to perform animation sequences to showcase what changed.

Fortunately, DiffUtil comes here to our rescue. This tiny tool can be used to compute the difference between the old and new list and notify the adapter with one line of code:

 // calls adapter's proper notify methods after diffResult is computed
diffResult.dispatchUpdatesTo(adapter);

It seems that DiffUtil completely solves the problem of the efficient adapter updating. But, there is one catch. This helpful utility still involves some boilerplate code:

  • Firstly, we must implement a class that implements the DiffUtil.Callback required methods. And if we have multiple recycler views this step should be repeated.

  • As stated in the documentation:

If the lists are large, this operation may take significant time so you are advised to run this on a background thread, get the DiffUtil.DiffResult then apply it on the RecyclerView on the main thread.

  • We must ensure that the adapter is notified right after the data source is updated. Here is the quote from the docs:

Note that the RecyclerView requires you to dispatch adapter updates immediately when you change the data (you cannot defer notify* calls).

  • Also take into account that there is no way by default to cancel calculateDiff operation. So we must provide some other way to discard DiffUtil.DiffResult when we do not need it (e.g., Activity has been finished).

And here is the next tool that comes to our rescue: RxDiffUtil.

Features

  • Provides Rx interface to DiffUtil
  • Automatically cancels all operations (unsubscribes all current subscriptions) when Activity has been destroyed and finished
  • Subscriptions can be bound to both android.app.Activity and android.support.v7.app.AppCompatActivity
  • Automatically configures background threads
  • Automatically updates RecyclerView.Adapter on the main thread
  • Provides the default implementation of DiffUtil.Callback which can be easily integrated with the existing code base
  • Can manage multiple RecyclerViews

Usage

1. If you want to update the adapter manually

First set the binding in your Activity's onCreate:

private DiffRequestManager mDiffRequestManager;

@Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        // The manager can be injected using Dagger
        mDiffRequestManager = RxDiffUtil
                                .bindTo(this)
                                .getDefaultManager();
                                
        mCompositeDisposable.add(mDiffRequestManager
                                .diffResults()
                                .subscribe( rxDiffResult -> {
                                     // Update your adapter here
                                     // Note: If the diff calculation was finished when the activity has been destroyed this method will be called as soon as the new activity is created
                                });                             
}

Then, when the new data has been received, call the following:

// At this point you have received the new data (possibly using some async request)
mDiffRequestManager
                   .newDiffRequestWith(diffCallback)
                   .detectMoves(true)
                   .calculate();

You can use DefaultDiffCallback as a helper to create the diff callback:

.newDiffRequestWith(new DefaultDiffCallback<>(adapter.getCurrentData(), newData))

The lists that are passed to the default callback must hold the data model which implements Identifiable interface. This interface is required to provide the proper unique identifiers of the compared items. Here is the sample implementation.

If you need to update just one RecyclerView.Adapter than that's it. When Activity is finished all resources will be disposed; when you call calculate() the previous operation is cancelled automatically; the main thread won't be blocked.

2. If you want the adapter to be updated automatically
  • The adapter must implement Swappable interface. This is required to update data source and notify adapter at the appropriate time. Here is the sample implementation.

  • Pass the adapter when creating the binding:

private DiffRequestManager<YourModelType, YourAdapterType> mDiffRequestManager;
  
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
          
    mDiffRequestManager = RxDiffUtil
                                  .bindTo(this)
                                  .with(adapter);                            
}
  • And when the new data arrived:
mDiffRequestManager
                   .newDiffRequestWith(diffCallback)
                   .updateAdapterWithNewData(newData)
                   .detectMoves(true)
                   .calculate();

updateAdapterWithNewData will notify the adapter asynchronously when the diff calculation has been finished even after the configuration change.

Activity with multiple recycler views

If you have Activity which contains multiple RecyclerViews then you must also supply unique tags for each diff calculation operation requested for different RecyclerView. This is required to correctly find and cancel a previous request and also allows to distinguish between the diff results in case you decide to merge the observables.

For example, consider there are two RecyclerViews and we need to calculate the difference for each one at the different points of our app's lifecycle. All you need to do in such situation is to attach different tags for each request:

// Configure the first adapter binding
mDiffRequestManager1 = RxDiffUtil
                                .bindTo(this)
                                .with(adapter, "ADAPTER_TAG1");  

// Configure the second adapter binding
mDiffRequestManager2 = RxDiffUtil
                                .bindTo(this)
                                .with(adapter, "ADAPTER_TAG2");

Thanks

LICENSE

MIT License

Copyright (c) 2017 Stan Mots (Storix)

See the LICENSE file for details.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].