-
Notifications
You must be signed in to change notification settings - Fork 89
DH3 Overview
The main idea of DH3 is that navigation APIs, which are based essentially on annotated Pojos: NavigationModels. The navigation models are located in their own gradle module, distinct from the activity / service they describe.
Suppose we have M1 & M2, 2 gradle modules. Each one contains an activity and each activity wants to navigate to the other activity's module. This is a worst case scenario where 2 activity have a navigation cycle.
With DH3, both M1 & M2 have their own navigation module (resp. M1-nav & M2-nav). These modules are real gradle modules and they contain only annotated navigation model classes. The navigation models follow a naming convention that matches the activities they describe.
They will be processed via DH3 annotation processors. The processors will create:
- 1 extra binder class for each navigation model class: it knows how to map a bundle into an instance of the model.
- 1 intent builder class for each navigation model class: it will provide a fluent api to build an intent to navigate to its target activity.
M1 & M2 can now:
- use resp. M1-nav and M2-nav as dependencies. This allows them to navigate to themselves if needed but also to share their navigation API in the future apk. Hence in M1 and M2 build file, we have:
M1 or M2.dependencies {
api project(':M1-nav or M2-nav')
}
- M1 & M2 can also use the other module's navigation api as a dependency. It will enable navigation to this module:
M1 or M2.dependencies {
implementation project(':M2-nav or M1-nav')
}
At this stage M1 & M2 can already navigate to each other, using the intent builders generated by DH3. However, the code is not very elegant and we recommand creating a navigator class for each module. A navigator class is basically a class that allows a module to navigate to other modules. It is a hub to use navigation apis.
The henson gradle plugin can generate such a class:
//M1 or M2 build file
plugins {
//the order matters here
id 'com.android.application or library'
id 'dart.henson-plugin'
}
henson {
navigatorPackageName = "com.foo.module1 or module2"
}
The generated navigator offers a fluent API to navigate to all activities:
Intent intent = HensonNavigator
.gotoFooActivity(this)
.s("s")
.build();
Dart will let you map activity or service intents, and fragment arguments easily:
class MyActivity extends Activity {
@DartModel MyActivityNavigationModel navigationModel = ...;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//map the intent to the annotation navigation model field
Dart.bind(this);
}
}
class MyActivityChild extends MyActivity {
//will also work for subclasses if they have their own annotated navigation models
@DartModel MyActivityChildNavigationModel navigationModel = ...;
//no need to call bind again in subclasses
}
Note that it's the developer responsibility to initialize the navigation model. You can instantiate one directly or use your favorite DI engine for this. Dart expects the navigation model to be non null when binding it.
//in the module-navigation module:
@DartModel
class MyActivityChildNavigationModel extends MyActivityNavigationModel {
@BindExtra String s;
}
@DartModel
class MyActivityChildNavigationModel extends MyActivityNavigationModel {
@BindExtra @Nullable String t;
}
Also note that when an instance of a subclass will be created, and the call to bind is executed (in the base class's onCreate()
method), the instance of the navigation model assigned to all annotated members along the hierarchy will be the same navigation model instance of the subclass of the navigation model hierarchy. In other words, the navigation model field of all super classes will point to the same navigation model object, the navigation model created in the sub class.