Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

Single Activity Architecture

Nevin
December 05, 2015

Single Activity Architecture

Avoid using fragment in android apps.
@jcconf 2015
https://github.com/cnevinc/noFragment
https://youtu.be/soQq4PWHzKc

Nevin

December 05, 2015
Tweet

More Decks by Nevin

Other Decks in Programming

Transcript

  1. 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
  2. Multiple Activities 1. Create new activity takes time 2. Hard

    to reuse the view Activity A Activity C Activity B Activity D
  3. 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
  4. 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
  5. Custom View Lifecycle onFinishInflate 1. Setup / bind view @onFinishInflate

    2. Clean resource after @onDetachedFromWindow constructor onFinishInflate onAttachedToWindow onMeasured onLayout onDraw onDetachedFromWindow
  6. Custom View - xml <?xml version="1.0" encoding="utf-8"?>
 <com.nevinchen.nofragment.ui.InfoView android:id=“@+id/info_view" …

    >
 <RelativeLayout … >
 <android.support.v7.widget.CardView … >
 <RelativeLayout … >
 <ImageView android:id=“@+id/avatar" … /> 
 <TextView android:id=“@+id/name" … /> 
 <TextView android:id=“@+id/time” … />
 </RelativeLayout> </android.support.v7.widget.CardView>

  7. 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
 }
 }
  8. 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);
 
 }
  9. 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;
 }
 }); }
  10. Remove View public void removeFromParent() {
 ViewGroup parent = (ViewGroup)

    getParent(); parent.removeView(InfoView.this);
 } 

  11. Animation public void removeFromParent() {
 ViewGroup parent = (ViewGroup) getParent();

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

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT){
 TransitionManager.beginDelayedTransition(parent); parent.removeView(v, p);
 }
  13. onSavedInstance() - In activity public ArrayList<Pair<Class, Object>> 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);
 }
 

  14. onSavedInstance() - when onCreate() if (savedInstanceState != null) {
 history

    = (…..)savedInstanceState.getSerializable(“history”);
 ArrayList<Pair<Class, Object>> local = new ArrayList<>();
 local.addAll(history);
 
 for (int i = 0; i < local.size(); i++) {
 Pair<Class, Object> node = local.get(i);
 if (node.first == InfoView.class) {
 InfoView.AddMe(this,node.second,true);
 }
 }
 local.clear();
 }
 }
  15. 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));
 }