doridori / Pilot

An android.* decoupled application stack for Android
Apache License 2.0
116 stars 9 forks source link

Fragment Support #17

Open doridori opened 9 years ago

doridori commented 9 years ago

Currently only supports View based architectures and old school dialogs. Would be good to extend support to Fragments and FragmentDialogs. Due to the SRP #14 refactors UITypeHandlers can now be registered for differnt UI types (i.e. Views, Dialogs, Fragments etc), this leaves the challenges around...

1.Working out where in the Fragments lifecycle is safe to start using the Presenter. 2.Working out where in the DialogFragments lifecycle is safe to start using the Presenter. This has an extra constraint due to where onCreateDialog() is called 3.An example of how to align the foregound view for an Activity that used both a UIViewTypeHandler and a UIFragmentTypeHandler

Ideally Fragments onCreateView would have access to the Presenter so any views can be initialised with frame based data. This needs to be true for

a) newly placed fragments b) fragments that have been recreated after a config-change

Need to keep in in mind the horror that is http://staticfree.info/~steve/complete_android_fragment_lifecycle.png. Ideally would not use fragments at all but sometimes one needs to (say a 3rd party lib that supplied part of its SDK pre-bundled as a fragment)

On Fragment recreation - cant really reliably push the Presenter to the Fragment before onCreateView is called, as this is called as a result of Activity.setContentView, inside of which is also the fragment recreation step.

(http://grepcode.com/file_/repository.grepcode.com/java/ext/com.google.android/android/5.1.1_r1/com/android/internal/policy/impl/PhoneWindow.java/?v=source) delegates to https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/transition/Scene.java delegates to https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/view/LayoutInflater.java

May resort to Fragments needing to operate on a Pull fashion instead of Push (Views have their presenters pushed to them on creation). inside Fragment.onCreateView and FragmentDialog.onCreateDialog the first call could grab the corresponding Presenter from the hosting Activitys PilotStack. It would also need to cope with the event that the frame is no longer top of the pilot stack, in which case the fragment should dismiss itself asap.

Beginning to think to not bother - an arbritrary fragment can be shown using the GenericUITypeHandler and handled manually...

EDIT: maybe we dont have to worry about fragment recreation if the UIFragmentTypeManager is just using the FragmentTransaction.replace() method anyway. If fragment state restoration is handled in the same was as Views may should still restore fragment test, Test!

Just done some testing - if we use replace with the same fragment the state is not saved by default - if not using replace then the presenter is after onCreateView...

Think will need to just pull the presenter (if not already set) and if its not the top of the stack then it will auto be switched out by the top of stack callback that will follow the root Activitys.setContentView call. Then all need to do is ensure what ever UITypeHandlers that are being used will clear each other / take priority.

Was thinking a Fragment can pull from the top of the stack using its @Presenter annotation to declare what presenter its interested in. If the top of the stack is a different presenter/frame null will be passed. This can be ignored and the fragment would build no UI in this case - as its about to be switched out anyway (it no longer represents the top of the stack). This wont work at current as after process death we may have some fragments recreated but the PilotLifeCycleManager has its onCreateDelegate called after Activity.setContentView. This is intentional as we need to pass the PilotSyncer in here, which can reference part of the UI (see UITypeViewDisplayer). If going this route would need to ensure that the PilotStack was already accessible by the point setContentView is called. This could be done by delegating two calls to PilotLifecycleDelegate inside Activity.onCreate, one before setContentView which just uses the savedStateBundle to restore the stack, and one after that passes the ui hooked up PilotSyncer

Will create a new branch for this as while simple fragment usage is handy - Its not the primary use-case for this lib.

doridori commented 9 years ago

Have removed the WIP fragment support as its not primary use-case and don't want to be distracted from that at present. Best to do a few things well...

811356e61ec3ccae1600e38657b3391d5f7cb79b

doridori commented 8 years ago

Support lib 24 has some changes around Fragment recreation and consistantly being inside an Activities super.onCreate() https://youtu.be/k3IT-IJ0J98?t=906

doridori commented 8 years ago

Maybe it does not matter so much that the Fragments Presenter would be pushed after its view is created. Could follow the same approach as https://github.com/googlesamples/android-architecture/blob/todo-mvp/todoapp/app/src/main/java/com/example/android/architecture/blueprints/todoapp/addedittask/AddEditTaskActivity.java.

As long as the rendered UI is hidden until the ViewState is accessable I dont see a problem.

Not sure if this breaks UI widget state restoration though...

doridori commented 7 years ago

Can still create the view in onCreateView and when the State is pushed, the Presentatation layer can be created, and the view can start being manipulated.