Nucleus is an Android library, which utilizes the Model-View-Presenter pattern to properly connect background tasks with visual parts of an application.

Last update: Jun 1, 2022

Nucleus

Deprecation notice

Nucleus is not under develpment anymore. It turns out that Redux architecture scales way better than MVP/MVI/MVVM/MVxxx and I do not see further development of Nucleus valuable.

I recommend considering ReKotlin as a simple Redux implementation.

Info

Android Arsenal Maven Central

Nucleus is a simple Android library, which utilizes the Model-View-Presenter pattern to properly connect background tasks with visual parts of an application.

MVP introduction article

Wiki

Introduction

Some time has passed since Model-View-Presenter and RxJava completely superseded Loader and AsyncTask in our applications.

But there are still some defects in our applications even when using such advanced technologies:

  • An application is unable to continue a background task execution after a configuration change.
  • An application does not automatically restart a background task after a process restart.

While most applications work without such capabilities, their absence is an obvious bug that just sits there and waits for a user who pressed "Login" button while being in a subway and switched to another application because his network connection was too slow. Bugs that almost any application produce in such cases are numerous.

Android docs are covering such problems very briefly, take a look at: Processes and Threads - 4. Background process "If an activity implements its lifecycle methods correctly, and saves its current state, killing its process will not have a visible effect on the user experience, because when the user navigates back to the activity, the activity restores all of its visible state."

This is not true - there WILL be a visible effect because we're not restoring background tasks. The application will restore it's visual state, but it will forget what it is doing. So, if an application restores a progress bar, but does not restore the background task itself - a user will see the usual "progress bar forever" bug.

Nucleus' main features

  • In case of configuration change Nucleus automatically re-attaches all running background tasks to the new View. The application will not forget what it is doing.

  • In case of process restart Nucleus automatically restarts background tasks. Even when running on a low memory device or waiting for a long running background task completion, the application is still reliable.

  • The entire library has been built keeping The Kiss Principle in mind. Anyone can read and understand it easily.

  • The library does not depend on Dagger, you don't need to write a whole class just to inject a presenter. One annotation is all you need. Despite presenters are instantiated without Dagger, their dependencies can still be injected.

  • Presenter in Nucleus is an external class that does not depend on View, this automatically prevents any troubles that are connected with activity context leaks.

History

At the moment of the first release, the library main idea was to be the simplest possible MVP implementation.

A couple of months later, I finally realized that RxJava has became the tool number one for smart background threads handling, so RxPresenter appeared. Since that moment, the main focus shifted in the direction of RxJava support.

The correct lifecycle handling was something that seemed obvious to me from the beginning, so I did not make an accent on this feature in the library description. However, since those times, more MVP libraries appeared, now I need to differentiate Nucleus from other implementations. The library description became: "Nucleus is a simple Android library, which utilizes the Model-View-Presenter pattern to properly connect background tasks with visual parts of an application."

Include this library:

dependencies {
    compile 'info.android15.nucleus:nucleus:6.0.0'
}

For additional view classes NucleusSupportFragment, NucleusFragmentActivity include:

dependencies {
    compile 'info.android15.nucleus:nucleus-support-v4:6.0.0'
}

For additional view class NucleusAppCompatActivity include:

dependencies {
    compile 'info.android15.nucleus:nucleus-support-v7:6.0.0'
}

ProGuard config:

-keepclassmembers class * extends nucleus.presenter.Presenter {
    <init>();
}

For RxJava 2:

dependencies {
    compile 'info.android15.nucleus5:nucleus:7.0.0'
}

For additional view classes NucleusSupportFragment, NucleusFragmentActivity include:

dependencies {
    compile 'info.android15.nucleus5:nucleus-support-v4:7.0.0'
}

For additional view class NucleusAppCompatActivity include:

dependencies {
    compile 'info.android15.nucleus5:nucleus-support-v7:7.0.0'
}

Hint: you can just copy/paste those classes code into ANY View class to keep your View classes hierarchy as you like to.

ProGuard config:

-keepclassmembers class * extends nucleus5.presenter.Presenter {
    <init>();
}

GitHub

https://github.com/konmik/nucleus/
Comments
  • 1. When to destroy activity's presenter

    We need a more reliable way to detect when to destroy activity's presenter.

    Here is where the issue that started the discussion: https://github.com/konmik/nucleus/issues/42#issuecomment-204233175

    TL/DR: activity's finish() can be called some time after onPause, so this code will leak the activity's presenter: https://github.com/konmik/nucleus/blob/master/nucleus/src/main/java/nucleus/view/NucleusActivity.java#L76

    Possible solutions:

    a) Leverage retained fragments. This will solve the presenter destruction issue but we will leak background tasks sometimes.

    b) Extend PresenterLifecycleDelegate lifecycle to explicitly call onDestroy.

    c) Install system-wide lifecycle listener registerActivityLifecycleCallbacks.

    Reviewed by konmik at 2016-04-12 14:50
  • 2. RxJava2 Support

    Hello Konstantin,

    Do your long-term plans for the library include the adoption of RxJava v2? It had recently reached RC1, which means the API should be quite stable by now.

    If yes, perhaps there's sense in creating another branch of nucleus containing preparations/adaptations for the new RxJava?

    I might be able to help with some crude initial conversion if needed.

    Reviewed by Dev-iL at 2016-09-02 07:33
  • 3. Nucleus 2.0.0

    Is currently under testing.

    I hope that it will be production-ready in the middle of August.

    Want to join beta?

    compile "info.android15.nucleus:nucleus:2.0.0-beta8"
    

    Primary goals are:

    • Make RxPresenter to be completely usable without getView() - 100% done!
    • Replace OperatorSemaphore with standard RxJava operators. - 100% done!
    • Simplify internal structure: remove manager and helper. - 100% done!
    • Move all tests into unit tests to be testable without device. - 80%.

    Update: a little note about the new rx.Single. rx.Single is awesome and I'm already playing with it. However, creation of additional methods for it will cause much more confusion than advantage (I already implemented this, but dropped the implementation because it just looks bulky, imagine stranger method names like deliverSingleCache, restartableSingleCache). The right way to handle rx.Single in Nucleus is to cast it to Observable.

    Reviewed by konmik at 2015-07-16 23:01
  • 4. onRestoreInstanceState() should be called before onResume()

    Hey, thanks for the library.

    Several times I caught the exception from here:

        /**
         * {@link android.app.Activity#onCreate(Bundle)}, {@link android.app.Fragment#onCreate(Bundle)}, {@link android.view.View#onRestoreInstanceState(Parcelable)}.
         */
        public void onRestoreInstanceState(Bundle presenterState) {
            if (presenter != null)
                throw new IllegalArgumentException("onRestoreInstanceState() should be called before onResume()");
            this.bundle = ParcelFn.unmarshall(ParcelFn.marshall(presenterState));
        }
    

    The exception message seems too low-level for any library user. After some source code exploring, I found, that we can't call getPresenter() in any point before onResume(). Thus, for instance, method references like

    private SomeView.ClickListener mViewClickListener = getPresenter()::viewClicked;

    can crash the app, because getPresenter() is obviously called before onCreate.

    Also I caught the crash several times in other callbacks, probably, in FragmentStatePagerAdapter (which can call onRestoreInstanceState before or even without onCreate, sorry, I don't remember a lot of details)

    Is it reasonable to:

    1. Replace throwing exception to some warning message, leaving developer's responsibility to save/restore state?
    2. (more complex) to separate Presenter constructor and onCreate() methods, so that some time, before onCreate call, Presenter can exist without state restored?
    Reviewed by yankeppey at 2016-05-20 13:52
  • 5. Fragment might lose the presenter id

    If a fragments (PresenterLifecycleDelegates) onSaveInstanceState method gets called before the PresenterFactory is set, it will not save its presenter id in the result bundle.

    I have a NucleusSupportFragment for which I set the PresenterFactory in onActivityCreated. When I detach that fragment (without destroying the presenter) and rotate the screen once, the presenter id will be saved in the bundle . After another rotate however the presenter id will not be saved anymore because getPresenter() will not restore the Presenter without a set Factory.

    Reviewed by inv3rse at 2016-04-13 14:24
  • 6. NucleusActionBarActivity with support library 26

    Hi,

    I've recently updated my support library to version 26.0.1 which does not include the deprecated ActionBarActivity class. This causes an error while creating a release APK file saying that the NucleusActionBarActivity can't be compiled since it has unknown method references:

    Warning:nucleus.view.NucleusActionBarActivity: can't find referenced method 'boolean isChangingConfigurations()' in program class nucleus.view.NucleusActionBarActivity

    I've tried removing only this class with gradle's 'exclude', but with no success. So currently I'm adding the sources without the problematic class directly into my app sources...

    I think this class should be removed from nucleus since it extends a class that has been removed from the android support library.

    Reviewed by aralizer at 2017-08-26 11:45
  • 7. leaks when using with addView/removeView

    I'm attempting to use a NucleusLayout as the base class for my view. Because the view life cycle is not tied to the activity life cycle, Nucleus is creating a new Presenter each time addView() is used, but not destroying it when removeView() is used. Due to the way PresenterHelper and NucleusLayour are implemented I am unsure how to fix this issue without duplicating the classes in their entirety.

    Reviewed by scriptacus at 2015-04-07 18:36
  • 8. Why no delivery() method?

    Hi there! I don't understand how to implement a case where a data should be delivered without caching (like PublishSubject or EventBus event). For example, I have a UserAddedEvent event. I need to handle it in my presenter only if there is a view attached (I can skip it otherwise).

    add(userAdded()
        .compose(deliverLatestCache()) 
        .subscribe(split(View::addUser)));
    
    Reviewed by Zeliret at 2016-02-10 17:44
  • 9. Adds Presenter Factory

    This moves the logic of reflectively creating the presenter into a presenter factory, so that that functionality can be customized.

    In my case, I'm using Dagger to inject dependencies, and using a presenter factory allows me to inject the dependencies through the presenter constructor, without having to use a pseudo-singleton injector class.

    The superclasses include the default ReflectionPresenterFactory, so they have the same out of the box functionality, but by extracting that logic out of the PresenterHelper, the user is offered much more flexibility.

    Note: I'm not sure how you're handling versioning, so I changed the dependencies in the support libraries and the examples to point to the snapshot version that I made and installed locally. I didn't include that in this PR since that's a change that shouldn't go into production.

    Reviewed by rharter at 2015-05-04 21:35
  • 10. Question regarding getView() and reference the View in the presenter.

    This is simply a question, please label it as such.

    I understand getView() is deprecated. The docs comments on the method mention the following:

    /**
     * Please, use restartableXX and deliverXX methods for pushing data from RxPresenter into View.
     */
    

    What if an Android Context is needed, in cases like parsing a local .json file from assets?

    For example:

    InputStream is = getView().getAssets().open("data.json");
    

    What is the best practice for this particular case?

    Reviewed by Orbyt at 2017-06-14 21:01
  • 11. [Q] How to work with ContentProvider?

    I'm a RxJava newbie. In my opinion, Retrofit, RxJava and this library is the best practice to implement a client-server communication in Android. Retrofit and RxJava makes easily to call and handle (asynchronous) HTTP requests, Nucleus makes safety to implement the callback in the life circle of Activity or Fragment. Data could come from either remote server or local data base. In remote server side, I have an awesome Retrofit library. In local data base, I could use SQLite Database and ContentProvider. I haven't found the best way to make an asynchronous query to ContentProvider that use RxJava and implement callback with Nucleus yet. Would you mind suggesting me?

    Reviewed by hnvn at 2016-10-27 03:39
  • 12. Crashes when starting a new activity using kotlin

    I tried with extending AppCompactActivity it works. But with nucleusappcompactactivity crashes.

    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.dayanithi.supercamping/com.dayanithi.supercamping.activities.admin.AdminLoginClass}: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2760) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2821) at android.app.ActivityThread.-wrap12(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1541) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:181) at android.app.ActivityThread.main(ActivityThread.java:6295) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:793) Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference at android.content.ContextWrapper.getResources(ContextWrapper.java:86) at android.view.ContextThemeWrapper.getResourcesInternal(ContextThemeWrapper.java:127) at android.view.ContextThemeWrapper.getResources(ContextThemeWrapper.java:121) at android.support.v7.app.AppCompatActivity.getResources(AppCompatActivity.java:542) at android.view.Window.getDefaultFeatures(Window.java:1627) at android.view.Window.(Window.java:668) at com.android.internal.policy.PhoneWindow.(PhoneWindow.java:333) at com.android.internal.policy.PhoneWindow.(PhoneWindow.java:341) at android.app.Activity.attach(Activity.java:6797)

    Reviewed by dayanithi06 at 2018-06-28 09:45
  • 13. clear the delivery cache

    Is there a way to clear the delivery cache used by deliverReply etc - for example if the underlying data query has changed and we want to forget the history?

    Reviewed by maximosipov at 2018-06-10 16:31
  • 14. Confusion about restartables and the Activity lifecycle

    I'm either confused on the wording of the Javadocs, or restartable is not behaving how I would expect. I'm using restartableLatestCache, which from dissecting the Javadocs indicates that it will emit the last onNext value each time it is started, plus any new onNext values if they are emitted in the future. A restartable will re-subscribe after a "process restart". I'm unsure exactly what entails a process restart, but I assumed that meant when an activity is being recreated for whatever reason.

    However, a simple pause/resume of the activity via backgrounding the app and bringing it back to the foreground triggers the restartable to fire off its cached value without a subsequent call to start. I didn't think that would qualify as a "process restart".

    So if someone would be so kind, could you explain to me if this is working as intended, and if so, qualify what a "process restart" means so I know what behavior to expect in the future? How could I achieve a "latestCache"-like result, but only if the Activity has been re-created (destroy/create)?

    Reviewed by jrobinson3k1 at 2017-05-02 20:06
  • 15. add DeliverLatest

    Hi.

    DeliverLatest completes automatically when the source observable is done.

    In my case I have a Repository which emits data from Cache, DB and API. I can emit from Cache first, then from DB and API. It's a sequence of distinct items.

    Why I'm not using deliveryLatestCache?

    • to avoid keeping subscription to viewObservable
    • to avoid getting the last cache from observable, cause it can be incorrect (old)

    Why I'm not using deliveryFirst?

    • it will emit only first item (from Cache)

    Why I'm not using deliveryReplay?

    • the item sequence in ReplaySubject might be outdated and I want just to get the new sequence from Repository (it's already got own cache)
    Reviewed by kanat at 2017-01-14 07:52
  • 16. Active? [question]

    Hello, first thanks for great looking library, I would like to ask if you still maintain this library? Because I plan start using nucleus, but at the same time I am little curious. Most of work you did was done last year and first months of this year. So that's why I have some doubts.

    Thank you for your answer! Seidak

    Reviewed by Seidak at 2016-09-01 10:37
Related tags
Full Management is an application that helps you manage your tasks effectively. built with the latest tachs like Compose UI, Jetpack libraries, and MVVM design pattern.
Full Management is an application that helps you manage your tasks effectively. built with the latest tachs like Compose UI, Jetpack libraries, and MVVM design pattern.

Full Management is an application that helps you manage your tasks effectively. built with the latest tachs like Compose UI, Jetpack libraries, and MVVM design pattern.

Feb 20, 2022
Model-View-ViewModel architecture components for mobile (android & ios) Kotlin Multiplatform development
Model-View-ViewModel architecture components for mobile (android & ios) Kotlin Multiplatform development

Mobile Kotlin Model-View-ViewModel architecture components This is a Kotlin Multiplatform library that provides architecture components of Model-View-

Jun 19, 2022
A sample project in Kotlin to demonstrate AndroidX, MVVM, Coroutines, Hilt, Room, Data Binding, View Binding, Retrofit, Moshi, Leak Canary and Repository pattern.

This repository contains a sample project in Kotlin to demonstrate AndroidX, MVVM, Coroutines, Hilt, Room, Data Binding, View Binding, Retrofit, Moshi, Leak Canary and Repository pattern

Jun 17, 2022
Jun 9, 2022
A data-binding Presentation Model(MVVM) framework for the Android platform.

PLEASE NOTE, THIS PROJECT IS NO LONGER BEING MAINTAINED. As personal time contraints, I am currently unable to keep up. Please use official android da

Jun 6, 2022
🧬 Android DataBinding kit for notifying data changes from Model layers to UI layers on MVVM architecture.
🧬 Android DataBinding kit for notifying data changes from Model layers to UI layers on MVVM architecture.

?? Android DataBinding kit for notifying data changes from Model layers to UI layers on MVVM architecture.

Jun 24, 2022
LukohSplash is based on Android latest architectural components,Jetpack, and follows MVVM design pattern.
LukohSplash is based on Android latest architectural components,Jetpack, and follows MVVM design pattern.

?? The LukohSplash by open-source contributor, Lukoh. LukohSplash LukohSplash is based on Android latest architectural components,Jetpack, and follows

Jun 11, 2022
A simple app that consumes The GitHub APIs to display github users. The aim was to learn about different jetpack libraries, built with MVVM pattern.
A simple app that consumes The GitHub APIs to display github users. The aim was to learn about different jetpack libraries, built with MVVM pattern.

A simple app that consumes The GitHub APIs to display github users. The aim was to learn about different jetpack libraries, built with MVVM pattern.

Apr 15, 2022
📝 A demo todo/notes app which demonstrates the use of MVVM architecture, Navigation Component Library, Room Database, LiveData, Coroutines
📝 A demo todo/notes app which demonstrates the use of MVVM architecture, Navigation Component Library, Room Database, LiveData, Coroutines

?? MyNotes A demo notes/todo app which demonstrates the use of MVVM architecture, Navigation Component Library, Room Database, LiveData, Coroutines et

Jun 23, 2022
GraphQLTrial is a demo application based on modern Android application tech-stacks and MVVM architecture.

GraphQLTrial is a demo application based on modern Android application tech-stacks and MVVM architecture. App fetching data from the netw

Sep 26, 2021
A small demo application based on modern Android application technology stacks and MVVM architecture
A small demo application based on modern Android application technology stacks and MVVM architecture

Pokedex Pokedex es una pequeña aplicación de demostración basada en modernas pil

Dec 17, 2021
A simple Android Application with MVVM Architecture, Coroutine, Retrofit2

Retrofit with Coroutines and MVVM Architecture. A simple Android Application with MVVM Architecture Developed Using LiveData. MVVM Architecture. Retro

Oct 12, 2021
Currency converter Android application using MVVM architecture
Currency converter Android application using MVVM architecture

Currency Converter Currency conversion using live exchange rates. Demo Screenshots API service

Oct 31, 2021
Android MVVM Base Architecture for Enterprise Mobile Application using Architectural Components
Android MVVM Base Architecture for Enterprise Mobile Application using Architectural Components

Android MVVM Base Architecture for Enterprise Mobile Application using Architectural Components Highlights MVVM Architectural pattern Offline Support

Apr 23, 2022
Basic-MVVM-Example - Basic Android Application MVVM
Basic-MVVM-Example - Basic Android Application MVVM

Android's MVVM Architecture in Kotlin Why a simple app ? Because it's easier to

May 24, 2022
A sample application demonstrating the differences between MVVM and MVI.

MVI Case Study This is a sample application to demonstrate the differences between MVVM and MVI architecture. The sample is split into three helpful m

Jun 5, 2022
A template of a client application architecture
A template of a client application architecture

Model-View-ViewModel (ie MVVM) Model-View-ViewModel (ie MVVM) is a template of a client application architecture, proposed by John Gossman as an alter

Oct 20, 2021
Ceci est une application d'actualités de l'architecture MVVM avec Kotlin
Ceci est une application d'actualités de l'architecture MVVM avec Kotlin

MVVM-Appli Infos Ceci est une application d'actualités de l'architecture MVVM avec Kotlin utilisant des composants : Retrofit, Room, Coroutines, et Na

Nov 4, 2021