nucleus icon indicating copy to clipboard operation
nucleus copied to clipboard

Q/A (was: Some doubts)

Open mheras opened this issue 9 years ago • 64 comments

Hi!

I'm working on an app I want to use Nucleus for MVP+Rx.

I have some doubts, and I couldn't find any solution in the documentation/wiki. Could you please help me?:

  1. How can I use two instances of the same view, and make each of them have their own instances of their presenters? Is it possible by telling the PresenterStorage with ID to use? Or by any other way?

  2. Why is the presenter being destroyed and pointed to null in the onPause method instead of doing so in onDestroy? The documentation seems to be out of date. What if I want to stack several activities of the same type, and want them to keep their presenters while not destroyed by the system? Is that working because you pass isFinishing() to the delegate?

  3. I think we need more documentation about the restartable* methods in RxPresenter. I know that it is documented in the code with Javadoc, but I think it would be great to add some explanation in the wiki. Something like the deliver* methods documentation (btw, some of them seem to be out of date since you released version 2.0.1).

Thank you very much. Your library is great. Cheers, M.

mheras avatar Sep 12 '15 04:09 mheras

Hi!

  1. This is the default Nucleus behaviour.
  2. Presenters get destroyed on pause because it is simpler. Note that they get destroyed only during the latest onPause. All activities happen between onResume onPause so this is ok.
  3. Yes, the documentation could be better. I'm not going to improve it right now because I'm busy on another project, but. The library is very simple, so reading its code should be as easy as reading docs.

konmik avatar Sep 12 '15 08:09 konmik

@konmik Thanks for your response! I have another one:

  1. I'm trying to find the destroyPresenter method on NucleusLayout. Is it somewhere else now?

mheras avatar Sep 23 '15 17:09 mheras

@konmik Something like ((ViewWithPresenter)myView).getPresenter().destroy();?

mheras avatar Sep 23 '15 17:09 mheras

Yes, this is how it should work now.

I use this method for fragments as well: https://github.com/konmik/nucleus/blob/master/nucleus-example-with-fragments/src/main/java/nucleus/example/main/MainActivity.java#L19

konmik avatar Sep 23 '15 18:09 konmik

@konmik Great! Yet another question for you:

I need the deliver and deliverLatest functionalities (actually the restartable* alternatives) that are explained in your MVP Introduction, but I cannot find them in the latest version of the library. Did you move them to another place?

I'm trying to achieve a paginated list (with a RecyclerView), but every time the view is taken by the presenter, the latest response is getting appended to the list (because I'm using restartableLatestCache). I think something similar to deliver will help me with this use case.

As always, thank you for your time.

P.S.: Please let me know if you don't feel comfortable with this issue being treated as a Q/A thread :)

mheras avatar Sep 25 '15 04:09 mheras

I think that paging should deserve a wiki page: https://github.com/konmik/nucleus/wiki/Paging-example

deliver and deliverLatest has been superseded by deliverLatestCache, deliverFirst and deliverReplay.

konmik avatar Sep 25 '15 07:09 konmik

Hey, just wanted to pop in and ask a question. I have used the deliver() transformer before. Coming into v2.0.1, I had to settle for deliverReplay(). I am observing that myObservable.compose(deliverReplay()) is emitting source observable's onError events as onNext events. Any insights into this if this is not a bug but a feature?

theManikJindal avatar Oct 03 '15 21:10 theManikJindal

Sure, this is not a bug.

When we construct a connection we don't want to create it every time we request something - we want our connections to be reused. This is why all events come in the materialized state and this is why we use split at the end of a chain.

konmik avatar Oct 03 '15 21:10 konmik

I also have some doubts when subscribing in onTakeView method. All the examples I've seen here use onCreate, but what if you need some data from the view to make a request? (for example, an id from an activity's intent), and surviving screen rotation?

At the moment, I'm following this pattern https://gist.github.com/inorichi/158fa261f8ef7d3e7dde

Is this approach the way to go? Or did I miss something? I haven't tried with restartables in this case, is it an option?

Edit: I've edited the gist to show two options. One of them for what I've said before, and the other for reacting to user input.

PD: Thank you so much for Nucleus. Before this, I was using some kind of MVP where the presenter was doing almost everything and the code flow was getting very ugly.

inorichi avatar Oct 18 '15 11:10 inorichi

Hi,

How about writing something like this? (pseudocode)

class MyActivity {
     onCreate() {
        if (savedState == null)
            getPresenter().requestData(getIntent.getExtra());
     }

class MyPresenter {

    int id;

    onCreate(state) {
        this.id = state.id;

        registerRestartable(1, () -> api.getData(id),
            MyView::onData,
            MyView::onError);
    }

    void request(int id) {
        this.id = id;
        start(1);
    }

    Bundle save() {
         return new Bundle("id" = this.id);
    }

konmik avatar Oct 18 '15 12:10 konmik

This is what I was looking for. Thanks!

inorichi avatar Oct 19 '15 01:10 inorichi

Hello. Quick question for you:

I'm trying to create a Google Now like user interface (several different CardViews inside of a RecyclerView). I'd like each CardView to have its own presenter that is responsible for loading data (from the network, DB, etc.).

It seems like the only way to detect when a view is being recycled/rebound within an RecyclerView is to override the View.onStartTemporaryDetach() and View.onFinishTemporaryDetach() callbacks. I'm considering using those to drive the PresenterDelegate.onResume() and PresenterDelegate.onPause() events.

Do you foresee any issues with that or have any other recommendations?

gautamjain avatar Nov 16 '15 17:11 gautamjain

@gautamjain Hi, forsee tons of problems with the approach because card's lifecycle will be too short and they will disappear while scrilling, so you will need to keep track of all presenters to destroy them manually on exit. You will also need to manually save/restore card's state because RecyclerView does not do that.

konmik avatar Nov 17 '15 07:11 konmik

hi i am using ur library to handle , states for a list view , for instance when the data is not loaded a load screen , and when the data (via api call ) has been received then i change the layout of the activity to something say loadedLayout , but as i get the activity instance from view().subscribe(Activity ) , i am getting a null instance for the activity , is there any work around this issue (attached code)

restartableLatestCache(REQUEST_ITEMS, new Func0<Observable<MockData>>() { @Override public Observable<MockData> call() { view().subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Action1<MainActivity>() { @Override public void call(MainActivity mainActivity) { //i get null ref of activity here mainActivity.onLoadView(); } }); return MockApp.getMockApi() .getMockData().observeOn(AndroidSchedulers.mainThread()); } }, new Action2<MainActivity, MockData>() { @Override public void call(MainActivity activity, MockData response) { activity.onItemsNext(response.employees); } }, new Action2<MainActivity, Throwable>() { @Override public void call(MainActivity activity, Throwable throwable) { activity.onNetworkError(throwable); } } );

kushaga avatar Jan 20 '16 12:01 kushaga

@kushaga Hi, you normally do not need to use view() directly, there is example you can look up into: https://github.com/konmik/nucleus/blob/master/nucleus-example/src/main/java/nucleus/example/main/MainPresenter.java

Having null from view() is absolutely normal - you get it when view gets detached (read the view() method JavaDoc). If you don't need it just use the usual RxJava filter operator.

konmik avatar Jan 30 '16 16:01 konmik

Hi! Quick question- I have included the library - compile 'info.android15.nucleus:nucleus-support-v7:2.0.5' in my gradle dependencies. But I am not able to import NucleusAppCompatActivity. Am I missing something or has something changed?

kshivaram avatar Feb 08 '16 18:02 kshivaram

@KScoder83 nothing changed. Try to re-import project or something.

konmik avatar Feb 08 '16 20:02 konmik

I tried re-importing, but still it is not including the support libraries.

nucleus

kshivaram avatar Feb 08 '16 20:02 kshivaram

I would just copy NucleusAppCompatActivity to your project and only include info.android15.nucleus:nucleus:2.0.5 as dependency.

inorichi avatar Feb 08 '16 21:02 inorichi

@KScoder83 What if you just invalidate cache and restart? I have nucleus in several projects, it does fine. You can also download the support aar and expect it - classes are there. Try to invalidate caches, if it does not help then delete .gradle folder and idea files and re-create project.

konmik avatar Feb 08 '16 21:02 konmik

Great thanks! it seems to do the trick

kshivaram avatar Feb 08 '16 22:02 kshivaram

Hi, I'm using Nucleus in my project and now trying to add Dagger 2 support to it. What I can't figure out is - do I really need to use Nucleus with Dagger 2 or I just can have pretty much same functionality with dagger 2 scope mechanism?

bejibx avatar Mar 01 '16 08:03 bejibx

Hi,I think there is no need to restart the undone job when process reboots. RxJava is just some kind of thing which can replaces the AsyncTask while it cannot replace Service. RxJava should ideally be used for short operations (a few seconds at the most.) in Android .If you need to keep threads running for long periods of time, it is highly recommended you use service.So it's not possible for the process to be killed for saving memory before the job dong by RxJava is done. We should keep long threads in the service process but not in background process.I doubt my opinion.Hope to see your reply .

duo2005duo avatar Mar 29 '16 12:03 duo2005duo

Hi @duo2005duo,

How do you solve the progress bar problem without restarting background tasks?

I don't quite get why you oppose RxJava to services. RxJava is a language extension library. Service as an Android architecting solution for synchronization and background tasks with notifications. They work together without problems.

konmik avatar Mar 29 '16 12:03 konmik

Hi @bejibx

You can use Nucleus with Dagger easily, here is an example (Dagger 1): https://github.com/konmik/nucleus/tree/master/nucleus-example-with-tests

Dagger can't restart background tasks.

konmik avatar Mar 29 '16 12:03 konmik

How about Dagger 2? I mean, the main idea of Nucleus is to keep presenters separated from Activity lifecycle by moving them to static storage. I am trying to understand Dagger 2 right now (btw thank you for your "Snorkeling with Dagger 2" article) and it seems scopes mechanism is doing just this - "In Dagger 2 scopes mechanism cares about keeping single instance of class as long as its scope exists". So I wonder do I really need to use Nucleus in my project if I'm already using Dagger 2? Or I can get same thing with only Dagger 2 scopes mechanism? The problem is I'm not so familliar with Dagger 2 so I'm really not sure.

bejibx avatar Mar 29 '16 13:03 bejibx

@bejibx the purpose of Nucleus is to reduce application complexity by restoring background tasks together with view state, and by automatical reattachment of background tasks if they're still running.

Dagger 2 can't do this. Everything you created with dagger 1 or dagger 2 will be wiped out during a process restart.

konmik avatar Mar 29 '16 13:03 konmik

@konmic yes, you're right. But what if my presenters are stateless?

bejibx avatar Mar 29 '16 13:03 bejibx

@bejibx You can't save background task arguments then, so you can't restart those tasks with Nucleus.

konmik avatar Mar 29 '16 13:03 konmik

@konmik Take downloader for example,when the user press home button in a activity with a downloading progressbar ,you have to start a foreground to push noifications to indicate the current progress and the service will keep the process going on.The process will not be killed for saving memory when there is a foreground service in the process. In my opinion,the long pieriods of task should be place in the service and you do not need to restart tasks when process reboots. I'm talking about the reboot of the process but not the recreate of the activity. In the source of Nucleus,you regist a lot of restarable task and put the startId into the ”savedInstanceState“ which make the task restart if process reboot. I think there is no need to do so becasue long pieriods of task always come with foreground service.

duo2005duo avatar Mar 30 '16 01:03 duo2005duo