nucleus
nucleus copied to clipboard
Q/A (was: Some doubts)
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?:
-
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? -
Why is the presenter being destroyed and pointed to null in the
onPause
method instead of doing so inonDestroy
? 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 passisFinishing()
to the delegate? -
I think we need more documentation about the
restartable*
methods inRxPresenter
. 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 thedeliver*
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.
Hi!
- This is the default Nucleus behaviour.
- 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.
- 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 Thanks for your response! I have another one:
- I'm trying to find the
destroyPresenter
method onNucleusLayout
. Is it somewhere else now?
@konmik Something like ((ViewWithPresenter)myView).getPresenter().destroy();
?
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 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 :)
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
.
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?
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.
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.
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);
}
This is what I was looking for. Thanks!
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 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.
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 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.
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?
@KScoder83 nothing changed. Try to re-import project or something.
I tried re-importing, but still it is not including the support libraries.
I would just copy NucleusAppCompatActivity
to your project and only include info.android15.nucleus:nucleus:2.0.5
as dependency.
@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.
Great thanks! it seems to do the trick
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?
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 .
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.
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.
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 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.
@konmic yes, you're right. But what if my presenters are stateless?
@bejibx You can't save background task arguments then, so you can't restart those tasks with Nucleus.
@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.