Giter Site home page Giter Site logo

mosby-conductor's Introduction

Mosby - Conductor

Plugin for using Mosby with Conductor, a small, yet full-featured framework that allows building View-based Android applications.

Dependencies

Build Status

For Conductor 2.x with Mosby 3.x use:

dependencies {
    compile 'com.hannesdorfmann.mosby3:mvp-conductor:3.1.0'
    // or
    compile 'com.hannesdorfmann.mosby3:viewstate-conductor:3.1.0' // optional viewstate feature
    // or
    compile 'com.hannesdorfmann.mosby3:mvi-conductor:3.1.0' // Model-View-Intent
}

Snapshot

Latest snapshot (from master branch):

dependencies {
    compile 'com.hannesdorfmann.mosby3:mvi-conductor:3.1.1-SNAPSHOT' // Model-View-Intent
    // or
    compile 'com.hannesdorfmann.mosby3:mvp-conductor:3.1.1-SNAPSHOT'
    // or
    compile 'com.hannesdorfmann.mosby3:viewstate-conductor:3.1.1-SNAPSHOT' // optional viewstate feature

}

You also have to add the url to the snapshot repository:

allprojects {
  repositories {
    maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
  }
}

Usage

Extend your own Conductor Controller from MvpController or from MvpViewStateController if you want to use ViewState feature or from or MviController if you want to use the Model-View-Intent feature.

There are also two base LCE (Loading-Content-Error) Controllers you can extend from: MvpLceController and MvpLceViewStateController.

If you don't want to extend from one of the base controller classes shown above, you can always bring in Mosby easily in any Conductor controller:

class MyController extends Controller
                  implements MvpView, MvpConductorDelegateCallback<V, P> {

  // Initializer block (will be copied into constructor)
  {
    addLifecycleListener(new MvpConductorLifecycleListener<V, P>(this);
  }

  // implement all methods from  MvpConductorDelegateCallback like createPresenter() etc.
  ...

}

If you need ViewState support simply use MvpViewStateConductorLifecycleListener and MvpViewStateConductorDelegateCallback. Do the same for Model-View-Intent but use MviConductorLifecycleListener and MviConductorDelegateCallback.

Lifecycle

Presenter will be created right after Controller.onCreateView() but before Controller.onAttach(). So in onAttach() presenter is ready to be used. View will be detached from Presenter in Controller.onDestroyView() by calling presenter.detachView(true) (true if view is just detached temporarily i.e. screen orientation change, false if view is detached permanently because Controller will be destroyed)

Example

There is a nice external repository that shows how to use Mosby-Conductor. All credit goes to James Shvarts.

This repository contains a simple TO DO List app which is still work in progress.

License

Copyright 2016 Hannes Dorfmann

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

mosby-conductor's People

Contributors

ersin-ertan avatar friederbluemle avatar jshvarts avatar mflisar avatar sockeqwe avatar stefma avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mosby-conductor's Issues

Separate LCE classes into a separate module

Currently when using mvp-conductor an LCE classes automatically add dependencies to mosby's LCE and ViewState modules:

+--- com.hannesdorfmann.mosby3:mvp-conductor:3.0.0@aar
|    \--- com.hannesdorfmann.mosby3:mvp-lce:3.0.0@aar
|         \--- com.hannesdorfmann.mosby3:viewstate:3.0.0@aar

In my projects I do not use those modules, because I provide my own LCE implementations. But currently I still have these two additional dependencies which I do not even use...

It would be great to have mvp-conductor-lce or something like this, so that there can be more fine grained tuning.

Are you planning on doing something like this or do you oppose these changes?
I might try to come up with PR if this is acceptable and if you didn't already start this.

How to handle ViewPager with new conductor version?

Hi There,
Seems like ControllerPagerAdapter is deprecated. But if I put the new implementation of the conductor view pager into my build gradle(implementation 'com.bluelinelabs:conductor-viewpager:3.0.0-rc5') then all my controller that extends RestoreViewOnCreateMviController are screaming the following:

Cannot access 'com.bluelinelabs.conductor.RestoreViewOnCreateController' which is a supertype of 'com....controllers.homeadmin.HomeAdminController'. Check your module classpath for missing or conflicting dependencies

Does it mean i will have to change all my controllers to extends Controller and implements
MvpView, MviConductorDelegateCallback<V, P> to be able to use the latest conductor version?

NPE with Activity#isChangingConfigurations

When the app is stopped and restarted quickly, I intermittently get into this state:

Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.app.Activity.isChangingConfigurations()' on a null object reference
       at com.hannesdorfmann.mosby3.mvp.conductor.delegate.MvpConductorLifecycleListener.preDestroyView(MvpConductorLifecycleListener.java:73)
       at com.bluelinelabs.conductor.Controller.removeViewReference(Controller.java:898)
       at com.bluelinelabs.conductor.Controller.detach(Controller.java:886)
       at com.bluelinelabs.conductor.Controller$8.onDetached(Controller.java:965)
       at com.bluelinelabs.conductor.internal.ViewAttachHandler.reportDetached(ViewAttachHandler.java:103)
       at com.bluelinelabs.conductor.internal.ViewAttachHandler.onViewDetachedFromWindow(ViewAttachHandler.java:58)
       at android.view.View.dispatchDetachedFromWindow(View.java:16782)
       at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3429)
       at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3421)
       at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3421)
       at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3421)
       at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3421)
       at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3421)
       at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3421)
       at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3421)
       at android.view.ViewRootImpl.dispatchDetachedFromWindow(ViewRootImpl.java:3718)
       at android.view.ViewRootImpl.doDie(ViewRootImpl.java:6691)
       at android.view.ViewRootImpl.die(ViewRootImpl.java:6668)
       at android.view.WindowManagerGlobal.removeViewLocked(WindowManagerGlobal.java:476)
       at android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java:414)
       at android.view.WindowManagerImpl.removeViewImmediate(WindowManagerImpl.java:128)
       at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:4683)
       at android.app.ActivityThread.-wrap7(ActivityThread.java)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1703)
       at android.os.Handler.dispatchMessage(Handler.java:102)
       at android.os.Looper.loop(Looper.java:154)
       at android.app.ActivityThread.main(ActivityThread.java:6776)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)

I don't think there is much I can do since it seems to be internal to the library. Could you please investigate?

Fatal Exception: java.lang.NullPointerException ViewState from getViewState() is null

com.hannesdorfmann.mosby3.conductor.viewstate.delegate.MvpViewStateConductorLifecycleListener.onSaveViewState (MvpViewStateConductorLifecycleListener.java:74)
com.bluelinelabs.conductor.Controller.saveViewState (Controller.java:1143)
com.bluelinelabs.conductor.Controller.saveInstanceState (Controller.java:1165)
com.bluelinelabs.conductor.RouterTransaction.saveInstanceState (RouterTransaction.java:124)
com.bluelinelabs.conductor.Backstack.saveInstanceState (Backstack.java:102)
com.bluelinelabs.conductor.Router.saveInstanceState (Router.java:632)
com.bluelinelabs.conductor.ControllerHostedRouter.saveInstanceState (ControllerHostedRouter.java:192)
com.bluelinelabs.conductor.Controller.saveInstanceState (Controller.java:1188)
com.bluelinelabs.conductor.RouterTransaction.saveInstanceState (RouterTransaction.java:124)
com.bluelinelabs.conductor.Backstack.saveInstanceState (Backstack.java:102)
com.bluelinelabs.conductor.Router.saveInstanceState (Router.java:632)
com.bluelinelabs.conductor.ActivityHostedRouter.saveInstanceState (ActivityHostedRouter.java:42)
com.bluelinelabs.conductor.internal.LifecycleHandler.onActivitySaveInstanceState (LifecycleHandler.java:378)

attachView() is not getting called after launch with locked orientation

I'm using a usual stuff in Activity.onCreate():

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    val container = findViewById(R.id.controller_content) as ViewGroup
    conductorRouter = Conductor.attachRouter(this, container, savedInstanceState)
    Timber.e("onCreate, has root controller: ${conductorRouter.hasRootController()}")
    requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
    if (!conductorRouter.hasRootController()) {
      conductorRouter.setRoot(RouterTransaction.with(MyController()))
    }
  }

Steps to reproduce:

  1. Call setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) in Activity.onCreate()
  2. Rotate your device into a landscape mode prior to launching
  3. Launch application
  4. It launches rotated in portrait, as requested, but visually there's no controller inside

And here's why.
The following sequence of calls was observed in logs

-- launch in landscape --
MyController  D  createPresenter
   Presenter  D  attachView
-- rotated to portrait by system --
   Presenter  D  detachView retainInstance=true
MainActivity  D  onCreate, has root controller: true

And nothing after this...
That is: it seems that the first round of attach/detach was happening in the landscape mode, but then activity immediately was rotated by the system into a requested orientation - and here another onCreate happened - and that one was not followed by attach/detach

If I remove locked orientation stuff than everything goes smoothly:

-- launch in landscape --
MainActivity  D  onCreate, has root controller: false 
MyController  D  onCreateView
MyController  D  createPresenter
   Presenter  D  attachView
-- rotated to portrait by hand --
   Presenter  D  detachView true
MainActivity  D  onCreate, has root controller: true
MyController  D  onCreateView
   Presenter  D  attachView

I'm not sure if this is a bug or me doing something wrong, and if this is a bug, I'm not sure if it's mosby-conductor one or Conductor one or even an Android one :)

Code Sample in JAVA?

Thanks for the lib!

Is there a code sample on how to implement mosby with conductor in java?

Controller reference still remains after popping it, due to which I get null pointer exception when activity back pressed

java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.app.Activity.isChangingConfigurations()' on a null object reference
    at com.hannesdorfmann.mosby3.conductor.viewstate.delegate.MvpViewStateConductorLifecycleListener.preDestroyView(MvpViewStateConductorLifecycleListener.java:45)
    at com.bluelinelabs.conductor.Controller.removeViewReference(Controller.java:972)
    at com.bluelinelabs.conductor.Controller.detach(Controller.java:960)
    at com.bluelinelabs.conductor.Controller$7.onDetached(Controller.java:1039)
    at com.bluelinelabs.conductor.internal.ViewAttachHandler.reportDetached(ViewAttachHandler.java:103)
    at com.bluelinelabs.conductor.internal.ViewAttachHandler.onViewDetachedFromWindow(ViewAttachHandler.java:58)
    at android.view.View.dispatchDetachedFromWindow(View.java:19088)
    at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3924)
    at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3916)
    at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3916)
    at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3916)
    at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3916)
    at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3916)
    at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3916)
    at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3916)
    at android.view.ViewRootImpl.dispatchDetachedFromWindow(ViewRootImpl.java:4187)
    at android.view.ViewRootImpl.doDie(ViewRootImpl.java:7581)
    at android.view.ViewRootImpl.die(ViewRootImpl.java:7555)
    at android.view.WindowManagerGlobal.removeViewLocked(WindowManagerGlobal.java:500)
    at android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java:438)
    at android.view.WindowManagerImpl.removeViewImmediate(WindowManagerImpl.java:132)
    at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:4688)
    at android.app.ActivityThread.-wrap5(Unknown Source:0)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1794)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:7025)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:441)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1408)`

App crashes in don't keep activities mode

There is a stable crash after such steps:

  1. Open app
  2. Open CreateTask screen
  3. Hide app
  4. Open app
  5. Hide app

The reason is in MvpConductorLifecycleListener.
When there is a controller in backstack (TasksController) method postCreateView will not be invoked. So presenter equals to null. But when you press home button it invokes postDestroy method and throws NullPointerException.

com.hannesdorfmann.mosby3.conductor.sample E/AndroidRuntime: FATAL EXCEPTION: main Process: com.hannesdorfmann.mosby3.conductor.sample, PID: 1277 java.lang.RuntimeException: Unable to destroy activity {com.hannesdorfmann.mosby3.conductor.sample/com.hannesdorfmann.mosby3.conductor.sample.MainActivity}: java.lang.NullPointerException: Presenter returned from getPresenter() is null in com.hannesdorfmann.mosby3.conductor.sample.tasks.TasksController@9221574 at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:4383) at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:4401) at android.app.ActivityThread.-wrap5(Unknown Source:0) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1649) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:164) at android.app.ActivityThread.main(ActivityThread.java:6494) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807) Caused by: java.lang.NullPointerException: Presenter returned from getPresenter() is null in com.hannesdorfmann.mosby3.conductor.sample.tasks.TasksController@9221574 at com.hannesdorfmann.mosby3.mvp.conductor.delegate.MvpConductorLifecycleListener.postDestroy(MvpConductorLifecycleListener.java:81) at com.bluelinelabs.conductor.Controller.performDestroy(Controller.java:1076) at com.bluelinelabs.conductor.Controller.removeViewReference(Controller.java:972) at com.bluelinelabs.conductor.Controller.destroy(Controller.java:1097) at com.bluelinelabs.conductor.Controller.activityDestroyed(Controller.java:859) at com.bluelinelabs.conductor.Router.onActivityDestroyed(Router.java:558) at com.bluelinelabs.conductor.ActivityHostedRouter.onActivityDestroyed(ActivityHostedRouter.java:61) at com.bluelinelabs.conductor.internal.LifecycleHandler.destroyRouters(LifecycleHandler.java:209) at com.bluelinelabs.conductor.internal.LifecycleHandler.onDestroy(LifecycleHandler.java:160) at android.app.Fragment.performDestroy(Fragment.java:2768) at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1432) at android.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1557) at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1618) at android.app.FragmentManagerImpl.dispatchMoveToState(FragmentManager.java:3027) at android.app.FragmentManagerImpl.dispatchDestroy(FragmentManager.java:3007) at android.app.FragmentController.dispatchDestroy(FragmentController.java:244) at android.app.Activity.performDestroy(Activity.java:7217)

Correct way to handle subscriptions

What is the correct way to get callback about navigate back to a controller in the presenter.
If we have an attached presenter, we didn't set setRetainViewMode(RetainViewMode.RELEASE_DETACH), we don't get attachView() and detachView() in the presenter fur sure, because presenter stay in alive.
But for example I am subscribed to database change with an observer (Room) and it's very performance hungry. I would like to unsubscribe from changes during the controller isn't the current active controller, and resubscribe when we go back, but I don't want to rebuild the full UI.

I solved it with setRetainViewMode(RetainViewMode.RELEASE_DETACH) but in this case we start with a clean Controller, so we must to build the full UI again.

Do you have any idea or I just make in too complicated and this problem is easier :)

Question: How to save

I'm new to Mosby, Conductor and SQLBrite and looking at the sample app to understand everything...

In CreateTaskPresenter the function saveTask() is empty. What is the best way to save the task to the database?

I see dao: TaskDao passed in and can call dao.createTask() but what's the correct way to access the task's data?

Dependency not found

Error:Failed to resolve: com.hannesdorfmann.mosby3:mvi-conductor:3.0.0-alhpa1

Persistent state with MVI - no easy way to pass the saved State to presenter after activity died

Hi!

I'm currently trying to implement save and restore instance state with Conductor and MVI architecture, like described in Mosby MVI Part 6 - Persistent State. All went well until I faced what happens if the activity dies (example onLowMemory).

With conductor I'm able to reconstruct the backstack, but I can't prepare the presenter with the initial state, because bindIntents run in postCreate cycle, and the Controller only calls restoreInstanceState after postCreate finished. I dived into the code of the Controller class in Conductor and find a hacky workaround for it, but sadly as I said its a hack....

If you pass the last ViewState in the controller's saveInstanceState function to the Controllers original args, it will be persisted if the activity dies. So after the new Activity is created, when the Conductor lib restores the backstack, the Controller will be created with the last ViewState in its' args. With this implementation I can push the last State down to the presenter when createPresenter is called, because it's present in the Controller's constructor.

Do you have a better solution for this problem?

Thanks,
Agta

QUESTION Can I override internal dependencies?

README states that

Internal dependencies are Conductor 1.1.4 and Mosby 2.0.1

Can I simply override them in gradle by using:

compile 'com.bluelinelabs:conductor:1.1.6'
compile 'com.bluelinelabs:conductor-rxlifecycle:1.1.6'

?

Missing 3.1.1 version

I'm not sure if it was the idea to release mosby and mosby-conductor together, but this was always the case before. But now mosby is at 3.1.1 but mvi-conductor is at 3.1.0.

[Duplicate] unable to recreate the state of force stopped application

Mosby Version:
compile 'com.hannesdorfmann.mosby:viewstate-conductor:0.8.2'
Expected behavior
the controller that are added to router are recreated
Actual behavior (include a stacktrace if crash)
the saveinstancestate of the application is null when recover from force stopped application and the application reset to first controller, all the backstack is lost.
Steps to reproduce the behavior or link to a sample repository
From the root controller, go to a viewpager controller , than go to a child controller of folder details and than to another deeper controller of inner folder. when i go back to home and force kill the application from android studio, when i select the application from list of apps, the backstack is lost and the app restart from the first controller, and the saveinstancestate is null.

The demo app of conductor without mosby works well, the backstack is recreated and the saveinstancestate is not null when recreate the app state. So i'm thinking that the problem is from mosby.

Do you have any clue about this strange behavior?

Child controller presenter being detached when parent has RetainViewMode.RETAIN_DETACH

Hey @sockeqwe, I just noticed a very strange behavior where Mosby is not honoring the retainViewMode of a parent Conductor controller.

I have 2 controllers (let's call it Parent and Child for simplicity), Parent has RetainViewMode.RETAIN_DETACH applied to it and Child is nested into it, so I was expecting Mosby not to call detachView on the Child controller presenter (it's not being called on Parent, so Child was expected to behave the same way) but to my surprise the detachView method of Child controller presenter is being called when pushing a new controller to the stack. I think this shouldn't be the behavior; Children (nested) controllers should honor parent controllers retain mode, so if a parent has RetainViewMode.RETAIN_DETACH children should not call detachView either.

Furthermore detachView is only called once the first time the router pushes another controller, but when popping and pushing again its not not happening.

No Conductor(Bundle) constructor

I needed to pass some Bundle wtih arguments to MvpController and found out that I can't do that, because mosby's version implements only a default constructor with no arguments, making it impossible to pass any of them to the Conductor library.

Is this an explicit design choice or you simply didn't do it yet?

Add support for Mosby 3.0 and MVI

Hi Hannes,

I know Mosby 3 is still under development, but it would be great to have your mosby-conductor plugin with MVI support. Is this something you are planning for the near future?

Thanks!

Unable to store router's backstack.

I have an Activity inside which a Controller (CardController) inside which I have a ViewPager with Controllers as Pages which in their turn could be opened (i.e. pushed) - again - as Controller. How would I save ViewPager state and overall stack of controllers which get pushed on CardController using your ViewState concept? I get how I can save data for adapter, but I don't get how I store controller stack resulting from user's choice which controller to open?

So here's an example flow:

Activity - CardController created -> user chooses a Tab > user chooses an item inside a tab > Controller gets opened. The device is rotated. Everything is recreated.

README is incorrect in regard to a mosby-conductor mvp Presenter lifecycle

It seems like README documentation about Presenter lifecycle is incorrect.

It states that

Presenter will be destroyed in Controller.onDestroyView() except screen orientation changes

But mosby-conductor has this bit of code

  @Override public void preDestroyView(@NonNull Controller controller, @NonNull View view) {
    P presenter = getCallback().getPresenter();
    if (presenter == null) {
      throw new NullPointerException(
          "Presenter returned from getPresenter() is null in " + callback);
    }
    presenter.detachView(controller.getActivity().isChangingConfigurations());
  }

And there's nothing here which would destroy presenter. Only detachView() is getting called, even in non orientation change scenario.

In fact createPresenter() is also called only if getCallback() (which is == Controller) returns null presenter, but it will be null only for new Controllers and Controllers won't be null until they are removed from backstack or destroyed...

  @Override public void postCreateView(@NonNull Controller controller, @NonNull View view) {

    MvpConductorDelegateCallback<V, P> callback = getCallback();

    P presenter = callback.getPresenter();
    if (presenter == null) {
      presenter = callback.createPresenter();
      .......
    }
}

Or am I getting something wrong here?

Inheritance

So in conductor we would usually be using ButterKnife, and the way conductor handled the lifecycle of butterknife is by creating a class ButterKnifeController and then creating a class BaseController extending the ButterKnifeController, and then your own customized Controllers can extend the BaseController, and have all the basics handled for them all.

Now mosby + conductor, what you can do is allow your ButterKnifeController also extend the MvpController and you get MvpController functionality. However, the issue arises when you want to actually use the MvpViewStateController instead of the basic MvpController to handle states. How would you go about extending this chain so you can actually pass the Generic Types of <View, Presenter, ViewState> while extending that Base Controller.

In short:

`public abstract class BaseController extends ButterKnifeController {

}

public abstract class ButterKnifeController extends MvpViewStateController {

}

public class HomeController extends BaseController<View, Presenter, ViewState>{
//How would we go about passing these generics as you are able to do it
//When you extend directly from MvpViewStateController<HomeView, HomePresenter, HomeViewState>
}`

Thank you for your time in advance.

MVI + retain view + screen rotation

I'm not sure if this is desired, but imho, if the controller has setRetainViewMode(RetainViewMode.RETAIN_DETACH), the last known state should not be reemitted again after screen rotation because the view was not destroyed but only detached and reattached and therefore, it has already rendered the last known state in this case

I know it's still in beta state and this may just not have been implemented yet, but even in this case, I wanted to document this behaviour

'unbindIntents' not called if controller is destroyed while view is detached

According to the documentation it seems that 'unbindIntents' is supposed to be called when the view detaches from the presenter for the last time and is meant to be destroyed and therefore could be used for presenter "cleanup".

However, if the controller is being destroyed while on the backstack(not the top controller), such as when calling Router::popToRoot from the top controller, then the controller is destroyed but since view is already detached 'unbindIntents' is never called prior to this presenter being "destroyed".

Conductor v2 (RC) NullPointerException

After using child Routers in my app I'm facing a strange behavior:

06-17 21:03:41.184 2717-2717/com.chaseapp.chaseapp E/AndroidRuntime: FATAL EXCEPTION: main
                                                                     Process: com.chaseapp.chaseapp, PID: 2717
                                                                     java.lang.RuntimeException: Unable to destroy activity {com.chaseapp.chaseapp/com.chaseapp.chaseapp.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.app.Activity.isChangingConfigurations()' on a null object reference
                                                                         at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3706)
                                                                         at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:3724)
                                                                         at android.app.ActivityThread.access$1400(ActivityThread.java:151)
                                                                         at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1357)
                                                                         at android.os.Handler.dispatchMessage(Handler.java:102)
                                                                         at android.os.Looper.loop(Looper.java:135)
                                                                         at android.app.ActivityThread.main(ActivityThread.java:5254)
                                                                         at java.lang.reflect.Method.invoke(Native Method)
                                                                         at java.lang.reflect.Method.invoke(Method.java:372)
                                                                         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
                                                                         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
                                                                      Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'boolean android.app.Activity.isChangingConfigurations()' on a null object reference
                                                                         at com.hannesdorfmann.mosby.mvp.conductor.delegate.MvpConductorLifecycleListener.preDestroyView(MvpConductorLifecycleListener.java:74)
                                                                         at com.hannesdorfmann.mosby.conductor.viewstate.delegate.MvpViewStateConductorLifecycleListener.preDestroyView(MvpViewStateConductorLifecycleListener.java:44)
                                                                         at com.bluelinelabs.conductor.Controller.removeViewReference(Controller.java:811)
                                                                         at com.bluelinelabs.conductor.Controller.detach(Controller.java:800)
                                                                         at com.bluelinelabs.conductor.Controller.destroy(Controller.java:916)
                                                                         at com.bluelinelabs.conductor.Controller.activityDestroyed(Controller.java:750)
                                                                         at com.bluelinelabs.conductor.Router.onActivityDestroyed(Router.java:414)
                                                                         at com.bluelinelabs.conductor.ControllerHostedRouter.onActivityDestroyed(ControllerHostedRouter.java:68)
                                                                         at com.bluelinelabs.conductor.Router.onActivityDestroyed(Router.java:417)
                                                                         at com.bluelinelabs.conductor.ActivityHostedRouter.onActivityDestroyed(ActivityHostedRouter.java:40)
                                                                         at com.bluelinelabs.conductor.internal.LifecycleHandler.destroyRouters(LifecycleHandler.java:158)
                                                                         at com.bluelinelabs.conductor.internal.LifecycleHandler.onDestroy(LifecycleHandler.java:127)
                                                                         at android.app.Fragment.performDestroy(Fragment.java:2266)
                                                                         at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1017)
                                                                         at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
                                                                         at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1049)
                                                                         at android.app.FragmentManagerImpl.dispatchDestroy(FragmentManager.java:1897)
                                                                         at android.app.Activity.performDestroy(Activity.java:6168)
                                                                         at android.app.Instrumentation.callActivityOnDestroy(Instrumentation.java:1141)
                                                                         at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3693)
                                                                         at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:3724) 
                                                                         at android.app.ActivityThread.access$1400(ActivityThread.java:151) 
                                                                         at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1357) 
                                                                         at android.os.Handler.dispatchMessage(Handler.java:102) 
                                                                         at android.os.Looper.loop(Looper.java:135) 
                                                                         at android.app.ActivityThread.main(ActivityThread.java:5254) 
                                                                         at java.lang.reflect.Method.invoke(Native Method) 
                                                                         at java.lang.reflect.Method.invoke(Method.java:372) 
                                                                         at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903) 
                                                                         at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698) 

Using Conductor v2 RC3 and mosby-conductor 0.7

Handle FragmentDialog displayed by a controller

Hey @sockeqwe, I have an use case where I need to display a FragmentDialog through a controller. I've noticed that there's a PR on the conductor repo to include a DialogController.

How would you handle such situations using mosby-conductor? I guess that following the MVP pattern the FragmentDialog shouldn't have much logic and that the logic should be handled by a presenter, but I can't seem to think of a way of having a presenter attached to it.

NPE on presenter.destroy() in MviConductorLifecycleListener postDestroy()

I found the following crasher. No repro steps unfortunately. But hopefully someone has an idea as to why it's happening:

com.hannesdorfmann.mosby3.MviConductorLifecycleListener.postDestroy (MviConductorLifecycleListener.java:133)
  com.bluelinelabs.conductor.Controller.performDestroy (Controller.java:1076)
  com.bluelinelabs.conductor.Controller.removeViewReference (Controller.java:972)
  com.bluelinelabs.conductor.Controller.destroy (Controller.java:1097)
  com.bluelinelabs.conductor.Controller.destroy (Controller.java:1082)
  com.bluelinelabs.conductor.Backstack.pop (Backstack.java:61)
  com.bluelinelabs.conductor.Backstack.popAll (Backstack.java:82)
  com.bluelinelabs.conductor.Router.destroy (Router.java:220)
  com.bluelinelabs.conductor.ControllerHostedRouter.destroy (ControllerHostedRouter.java:88)
  com.bluelinelabs.conductor.Controller.destroy (Controller.java:1093)
  com.bluelinelabs.conductor.Controller.activityDestroyed (Controller.java:859)
  com.bluelinelabs.conductor.Router.onActivityDestroyed (Router.java:558)
  com.bluelinelabs.conductor.ActivityHostedRouter.onActivityDestroyed (ActivityHostedRouter.java:61)
  com.bluelinelabs.conductor.internal.LifecycleHandler.destroyRouters (LifecycleHandler.java:209)
  com.bluelinelabs.conductor.internal.LifecycleHandler.onDestroy (LifecycleHandler.java:160)
  android.app.Fragment.performDestroy (Fragment.java:2587)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.