Modern Android
How to ditch Activities & Fragments
@Fabien_Devos | Wealthfront
Fragments.
Android Lifecycle
https://github.com/xxv/android-lifecycle
Problem
Problems
Problems with Activities & Fragments
Solution
Solution
Opinionated
Architecture
Single Activity Architecture
Activity
View for Screen B
View for Screen A
Screens & Views
MV
C
VM
P
?
Model View Controller
Model View Controller
Model
Controller
View
Model View Presenter
Model View Presenter
Model
Presenter
View
Model View Presenter
Model
Presenter
View
The (Good Old) Onion Model - aka Layers
Model
Presenter
View
The (Good Old) Onion Model - aka Layers
Data
Screen�(Logic)
View
Separate the logic from the views
The logic lives in the screens
Views are dumb
Screens are regular Java objects
Screens are easy to test
Logic is easy to test
Screens are also injection friendly
Navigation
Goals
Magellan
The Navigator keeps track of screens and animate between their views.
Screens survive rotation, but not views
Rotation
MainActivity
View for Screen A
Navigator
Screen A
Rotation
New MainActivity
New View for Screen A
Navigator
Screen A
Navigating means pushing on the stack
Navigation
MainActivity
View for Screen A
Navigator
Screen A
Navigation
MainActivity
View for Screen A
Navigator
Screen A
Screen B
Navigation
MainActivity
View for Screen A
Navigator
Screen A
Screen B
View for Screen B
Navigation
MainActivity
Navigator
Screen A
Screen B
View for Screen B
Navigating back
MainActivity
View for Screen A
Navigator
Screen A
Magellan: Navigation
navigator.goTo(new MySimpleScreen(stuff));
Magellan: Navigation
navigator.goTo(new MySimpleScreen(stuff));
Magellan: Navigation
goTo()
Magellan: Navigation
show()
Magellan: Navigation
navigator.overrideTransition(transition);
Magellan: Navigation
Navigator
.withRoot(new HomeScreen())
.loggingEnabled(BuildConfig.DEBUG)
.build();
Magellan: Navigation
navigator.goBack();
navigator.goBackTo(screen);
navigator.replace(screen);
Magellan: Navigation
navigator.rewriteHistory((history) -> {
if (!authenticator.isUserLoggedIn()) {
history.clear();
history.push(loginScreen);
} else {
history.push(homeScreen);
}
});
Magellan: Navigation
navigator.rewriteHistory((history) -> {
if (!authenticator.isUserLoggedIn()) {
history.clear();
history.push(loginScreen);
} else {
history.push(homeScreen);
}
});
Screens have a simple lifecycle
Magellan: Screen Lifecyle
View Created
Shown
Hidden
Created
createView()
onShow()
Destroyed
onHide()
Magellan: Screens
public class MySimpleScreen extends Screen<MySimpleView> {
@Override
protected MySimpleView createView(Context context) {
return new MySimpleView(context);
}
}
Magellan: Screens
public class MySimpleScreen extends Screen<MySimpleView> {
@Override
protected MySimpleView createView(Context context) {
return new MySimpleView(context);
}
}
Magellan: Screens
public class MySimpleScreen extends Screen<MySimpleView> {
@Override
protected MySimpleView createView(Context context) {
return new MySimpleView(context);
}
}
Magellan: Screens
public class MySimpleScreen extends Screen<MySimpleView> {
@Override
protected MySimpleView createView(Context context) {
return new MySimpleView(context);
}
@Override
protected void onShow() {
getView().displayStuff(stuff);
}
}
Magellan: Screens
public class MySimpleScreen extends Screen<MySimpleView> {
@Override
protected MySimpleView createView(Context context) {
return new MySimpleView(context);
}
@Override
protected void onShow() {
getView().displayStuff(stuff);
}
@Override
public String getTitle(Context context) {
return context.getString(R.string.my_screen_title);
}
}
Magellan: Setup
public class MainActivity extends SingleActivity {� @Override� protected Navigator createNavigator() {� return Navigator.withRoot(new HomeScreen()).build();� }� @Override� protected void onCreate(Bundle savedInstanceState) {� super.onCreate(savedInstanceState);� setContentView(R.layout.main_activity);� }�}
Magellan: Setup
public class MainActivity extends SingleActivity {� @Override� protected Navigator createNavigator() {� return Navigator.withRoot(new HomeScreen()).build();� }� @Override� protected void onCreate(Bundle savedInstanceState) {� super.onCreate(savedInstanceState);� setContentView(R.layout.main_activity);� }�}
Magellan: Setup
public class MainActivity extends SingleActivity {� @Override� protected Navigator createNavigator() {� return Navigator.withRoot(new HomeScreen()).build();� }� @Override� protected void onCreate(Bundle savedInstanceState) {� super.onCreate(savedInstanceState);� setContentView(R.layout.main_activity);� }�}
Magellan: Setup
main_activity.xml:
<com.wealthfront.magellan.ScreenContainer .../>
Only two classes to know about
Open Source
v1.0
More features!
Toolbar
onNavigate(actionBarConfig)
Add-on: Rx
autoUnsubscribe(observable)
Future
Coming Soon
Questions?