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:
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'
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>>>.** {
*;
}
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
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());
}
});
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)
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.
See the LICENSE file for details.