Skip to content

Simple way to subscribe to firebase database by rxJava patterns.

License

Notifications You must be signed in to change notification settings

Link184/Respiration

Repository files navigation

Respiration

Respiration is a light library which centralizes firebase database logic. It is a join of Firebase and rxJava libraries to give you a easier and shorter implementation of Firebase library where you don't need to care about verbose ValueEventListener addiction or removal.

Library is designed to work with POJO data models which simplify the code. No more primitives, casts or HashMaps inside a business logic.

The library also can work with offline database. The same respiration api but without firebase. Is a the same functionality as firebase realtime database but without firebase services =). You can learn how to integrate offline firebase here

Gradle

Gradle:

repositories {
    jcenter()
}
 
dependencies {
    implementation 'com.link184:respiration-core:0.6.7'
    implementation 'com.link184:respiration-firebase:0.6.7'
    annotationProcessor 'com.link184:respiration-compiler:0.6.7'
    
    //firebase and rxJava dependecies
    ...
}

Note Dont forget to add play services dependency

classpath 'com.google.gms:google-services:{version}'
...
apply plugin: 'com.google.gms.google-services'

ProGuard

By using this library is assumed that you put all your models as exceptions into proguard rules.

########--------Respiration--------#########
-keepattributes Signature
-keepattributes *Annotation*
-keepclassmembers class <<<path.to.your.models>>>.** {
  *;
}

How do I use Respiration with firebase?

Usage is simple like inspiration or expiration =)

Simple use cases with Respiration's will look something like this:

// Annotate class:
@RespirationModule
public class CustomModule {
    public static final String SAMPLE_PRIVATE_CHILD = "private";

    //Configure repositories with annotations
    @FirebaseRepository(dataSnapshotType = SamplePrivateModel.class,
            isAccessPrivate = true,
            children = {SAMPLE_PRIVATE_CHILD, RespirationRepository.USER_ID},
            persistence = true)
    public FirebaseGeneralRepository samplePrivateRepository;


    @FirebaseRepository(dataSnapshotType = Vector.class)
    public FirebaseGeneralRepository myRepo2;
}

Obtain repository from generated Module by access "Respiration{ModuleName}"

//SamplePrivateRepository is generated by field name annotated with @FirebaseRepository from 
//CustomModule annotated with @RespirationModule.
SamplePrivateRepository privateRepository = RespirationCustomModule.getSamplePrivateRepository();

// Attach a subscriber to handle all data changes from firebase. SubscriberRespiration is a rxJava 
// DisposableObserver so you can dispose or reattach it anytime.
samplePrivateRepository.subscribe(new SubscriberRespiration<SamplePrivateModel>() {
            @Override
            public void onSuccess(SamplePublicModel samplePublicModel) {
                nameContainer.setVisibility(View.VISIBLE);
                Log.d(TAG, "Found my name" + samplePublicModel.getName());
            }
 
            //Optional override
            @Override
            public void onFailure(Throwable error) {
                //Some logic when fail.
                nameContainer.setVisibility(View.GONE);
                Log.e(TAG, "Fail! ", error);
            }
        });

@FirebaseRepository also works on classes. Single rule is to extend class from FirebaseGeneralRepository or FirebaseListRepository

@FirebaseRepository(dataSnapshotType = SamplePrivateModel.class,
        children = {"children1", "child2", FirebaseRepository.USER_ID, "child3"})
public class CustomRepository extends FirebaseGeneralRepository<SamplePrivateModel> {
    public CustomRepository(Configuration<SamplePrivateModel> repositoryConfig) {
        super(repositoryConfig);
    }

    public void testMethod() {
        Log.d(TAG, "testMethod: ");
    }
}

Generated object can be accessed by generated {AnnotatedClassName}Builder class

CustomRepository customRepository = CustomRepositoryBuilder.getInstance();
customRepository.testMethod();

Also you can avoid annotation processing. INSTRUCTIONS

What about firebase arrays

With ListRepository you can easily wrap firebase Map<String, T> to List

//Get our list from generated sources, and perviosuly declared into our respiration module. 
SamplePrivateListRepository listRepository = RespirationCustomModule.getSamplePrivateListRepository();
  
listRepositorySubscriber = new SingleSubscriberRespiration<List<SampleFriendModel>>() {
            @Override
            public void onSuccess(List<SampleFriendModel> dataSnapShot) {
                for (SampleFriendModel friend : dataSnapShot) {
                    Log.d(TAG, "onSuccess: " + friend.toString());
                }
            }
        };

listRepository.subscribeToList(listRepositorySubscriber);
//Also you can subscribe to specific item from list
listRepository.subscribeToItem("someKey", listRepositorySubscriber);
// Or you can get all elements consecutively
listRepository.subscribe(new ListSubscriberRespiration<SampleFriendModel>() {
            @Override
            public void onSuccess(String key, SampleFriendModel value) {
                Log.e(TAG, "onSuccess: " + key + " " + value.toString());
            }
        });

Unleash all reactive power

If you need more specific behavior you can easily extend a respiration repository or just call asObservable() method.

myRepository.asObservale()
        .map(this::mapToRealmObject)
        .filter(FilterUtils::removeOutdatedSamples)
        .subscribe(...);

For list repository you can use asListObservable()

Don't forget to subscribe/unsubscribe according to android lifecycle.

@Override
    protected void onResume() {
        super.onResume();
        SubscriberFirebase subscriber = new SubscriberFirebase<Model>() { ... };
        privateRepository.subscribe(subscriber);
    }
 
    @Override
    protected void onPause() {
        subscriber.dispose();
        super.onPause();
    }

Also you can use SingleSubscriberFirebase class to obtain a value just once without subscription to data changes.

If you got to use firebase authentication user id as children in firebase database reference then use RespirationRepository.USER_ID instead firebase user id. That approach will permit you to avoid problems with firebase authentication changes. Example:

//Incorrect
String firebaseUserId = FirebaseAuth.getInstance().getCurrentUser().getUserId();
@FirebaseRepository(dataSnapshotType = SamplePrivateModel.class,
            isAccessPrivate = true,
            children = {SAMPLE_PRIVATE_CHILD, firebaseUserId},
            persistence = true)
            
//Correct
@FirebaseRepository(dataSnapshotType = SamplePrivateModel.class,
            isAccessPrivate = true,
            children = {SAMPLE_PRIVATE_CHILD, FirebaseRepository.USER_ID},
            persistence = true)

Sample

For more details you can clone and assemble a sample project from this github repository. Here is a database structure dump from sample project DATABASE_JSON. Import it into your project and enjoy the library.

License

See the LICENSE file for details.

About

Simple way to subscribe to firebase database by rxJava patterns.

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published

Languages