Slide 1

Slide 1 text

Single Activity Architecture a personal opinion @ChenNevin

Slide 2

Slide 2 text

Current 1. Multiple activities 2. One activity, multiple fragments 3. One activity, no fragment , multiple custom views 4. Sample app : https://github.com/cnevinc/noFragment

Slide 3

Slide 3 text

Multiple Activities 1. Create new activity takes time 2. Hard to reuse the view Activity A Activity C Activity B Activity D

Slide 4

Slide 4 text

Activity A Multiple fragments 1. Error-prone support library. 2. Complex life cycle in FragmentManager. 3. Nested fragment is only supported via code , can’t be inflated from xml. Fragment A Fragment C Fragment B Fragment D

Slide 5

Slide 5 text

Multiple views Pros 1. Easy to reuse 2. No support lib or FragmentManager Cons 1. Knowledge about custom view lifecycle (2 methods) 2. Have to handle backpressed event manually ( 1 methods) 3. Have to handle in/out animation manually

Slide 6

Slide 6 text

Custom View Lifecycle onFinishInflate 1. Setup / bind view @onFinishInflate 2. Clean resource after @onDetachedFromWindow constructor onFinishInflate onAttachedToWindow onMeasured onLayout onDraw onDetachedFromWindow

Slide 7

Slide 7 text

Custom View - xml 
 
 
 
 
 
 
 
 


Slide 8

Slide 8 text

Custom View - Definition public class InfoView extends LinearLayout { 
 @Bind(R.id.avatar)ImageView avatar;
 @Bind(R.id.name) TextView name; 
 @Override protected void onFinishInflate() {
 super.onFinishInflate();
 ButterKnife.bind(this);
 setupUI();
 } 
 @Override protected void onDetachedFromWindow() {
 super.onDetachedFromWindow();
 // clean up resource here
 }
 }

Slide 9

Slide 9 text

Custom View Interface Add view Setup onBackPressed Remove view

Slide 10

Slide 10 text

Add View public static void AddMe(MainActivity host, User data) {
 InfoView v = (InfoView)host.getLayoutInflater().inflate(R.layout.info, nu ViewGroup parent =((ViewGroup)host.findViewById(android.R.id.content));
 bind(data); host.addContentView(v, p);
 } private void bind(User user) {
 this.user = user ;
 Picasso.with(getContext()).load(user.avatar).placeholder(R.drawable.ic_launcher).into(avatar name.setText(user.name);
 time.setText(user.time);
 
 }

Slide 11

Slide 11 text

Setup Backpress private void setupBackPressed() {
 this.setFocusable(true);
 this.setFocusableInTouchMode(true);
 this.requestFocus();
 this.setOnKeyListener(new OnKeyListener() {
 public boolean onKey(View v, int keyCode,KeyEvent event){
 if (keyCode == KeyEvent.KEYCODE_BACK) {
 removeFromParent();
 }
 return true;
 }
 }); }

Slide 12

Slide 12 text

Remove View public void removeFromParent() {
 ViewGroup parent = (ViewGroup) getParent(); parent.removeView(InfoView.this);
 } 


Slide 13

Slide 13 text

Animation public void removeFromParent() {
 ViewGroup parent = (ViewGroup) getParent(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
 TransitionManager.beginDelayedTransition(parent); parent.removeView(v, p);
 }

Slide 14

Slide 14 text

Animation public void removeFromParent() {
 ViewGroup parent = (ViewGroup) getParent(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
 TransitionManager.beginDelayedTransition(parent); parent.removeView(v, p);
 }

Slide 15

Slide 15 text

onSavedInstance() - In activity public ArrayList> history = new ArrayList<>(); @Override
 public void onSaveInstanceState(Bundle savedInstanceState) {
 // Save the user's current game state
 savedInstanceState.putSerializable("history", history);
 
 // Always call the superclass so it can save the view hierarchy state
 super.onSaveInstanceState(savedInstanceState);
 }
 


Slide 16

Slide 16 text

onSavedInstance() - when onCreate() if (savedInstanceState != null) {
 history = (…..)savedInstanceState.getSerializable(“history”);
 ArrayList> local = new ArrayList<>();
 local.addAll(history);
 
 for (int i = 0; i < local.size(); i++) {
 Pair node = local.get(i);
 if (node.first == InfoView.class) {
 InfoView.AddMe(this,node.second,true);
 }
 }
 local.clear();
 }
 }

Slide 17

Slide 17 text

onSavedInstance() — View.addMe public static MyView AddMe(Activity host, Object data ,boolean fromHis){ saveState(data) //…… } private void saveState(Object data) {
 MainActivity host =(MainActivity)getContext();
 host.history.add(new Pair(InfoView.class, data));
 }

Slide 18

Slide 18 text

Some links http://fragmentedpodcast.com/2015/05/ https://github.com/JakeWharton/u2020 http://jcconf.tw/schedule-2.html https://corner.squareup.com/2014/10/advocating-against-android-fragments.html Jake Wharton with Fragment (and loader) Jake Wharton with Motar and Flow

Slide 19

Slide 19 text

Thanks! @ChenNevin
 Cognos Chen