Was it Frag-Ment to be? Luke Sleeman - Freelance Android developer http://lukesleeman.com luke.sleeman@gmail.com @LukeSleeman
Was it Frag-Ment to be? • Intro - What are fragments? History • Problems with fragments - Lifecycle, Bugs, Hard to use right • Best Practises: Don't use them - Places where we might have used fragments, alternatives • Best Practises: Risk mitigation - Googles suggestions • Summary - What we learnt, key takeaways • Questions
Intro
What is a fragment? A UI control you can compose to build responsive tablet UI’s
What is a fragment? A UI control you can compose to build responsive tablet UI’s
What is a fragment? A reusable group of Views to build our ui.
What is a fragment? A reusable group of Views to build our ui.
What is a fragment? An application component with a lifecycle
What is a fragment? An application component with a lifecycle
History - Android 2.x
History - Android 3.x
History - Android 4.x
Problems
Problem - Fragments ‘sorta’ work
‘Sorta’ works is the worst kind of works
Problem - Lifecycle
Problem - Lifecycle
• Add in asynchronous fragment transactions • Child fragments • Viewpagers which cache state and lazy construct fragments … • Ultimately you have no idea what state your fragment will be in at any point in time.
Problem - Communication List Fragment ? ??? Activity ? Detail Fragment
Problems - Lifecycle & Communication private void updateTimeStamps(){ ... String format = getContext().getString(R.string…) ... } private void newDataReceived(List<> ...){ ... updateTimeStamps(); ... } private void setTimeZone(TimeZone timeZone){ ... updateTimeStamps(); ... } public void startDataRefresh(){ ... setTimeZone(TimeZone. getDefault ()); ... }
Problems - Lifecycle & Communication private void updateTimeStamps(){ ... String format = getContext().getString(R.string…) ... } private void newDataReceived(List<> ...){ ... updateTimeStamps(); ... } private void setTimeZone(TimeZone timeZone){ ... updateTimeStamps(); ... } public void startDataRefresh(){ ... setTimeZone(TimeZone. getDefault ()); ... }
Problems - Lifecycle & Communication private void updateTimeStamps(){ ... String format = getContext().getString(R.string…) ... } private void newDataReceived(List<> ...){ ... updateTimeStamps(); ... } private void setTimeZone(TimeZone timeZone){ ... updateTimeStamps(); ... } public void startDataRefresh(){ ... setTimeZone(TimeZone. getDefault ()); ... }
Problems - Lifecycle & Communication private void updateTimeStamps(){ ... String format = getContext().getString(R.string…) ... } private void newDataReceived(List<> ...){ ... updateTimeStamps(); ... } private void setTimeZone(TimeZone timeZone){ ... updateTimeStamps(); ... } public void startDataRefresh(){ ... setTimeZone(TimeZone. getDefault ()); ... }
Problems (from google) • “ Fragments are so general they become really difficult to explain to people ” • “ A lot of times, you build up a fragment transaction, commit it, and things work completely differently from how you expect ” • Even more lifecycle to manage made stuff to complicated - “ and the bugs didn’t help! ” • People think ‘they are just like views’. <fragment> tag turned out to be a bad bit of syntactic sugar.
Summary - Problems 0. They almost work! But: 1. Lifecycle makes them prone to programmer error. 2. No clear use case - Replace views? Replace activities? Tablet UIs? 3. No guarantees about what state your fragment will be in.
Best Practises 1 - Don’t use them! 2 - Mitigate the risks if you do use them
Don’t use them - Normal Screens
Don’t use them - Tablet UI’s
Don’t use them - composable parts of UI Use a ViewGroup! (Subclass LinearLayout or FrameLayout)
Subclass ViewGroup public class UserSummaryView extends LinearLayout { private ImageView profileImage; private TextView name; private TextView title; private TextView bio; public UserSummaryView(Context context) { super(context); init(context); } public UserSummaryView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public UserSummaryView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); }
Subclass ViewGroup public class UserSummaryView extends LinearLayout { private ImageView profileImage; private TextView name; private TextView title; private TextView bio; public UserSummaryView(Context context) { super(context); init(context); } public UserSummaryView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public UserSummaryView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); }
Subclass ViewGroup public class UserSummaryView extends LinearLayout { private ImageView profileImage; private TextView name; private TextView title; private TextView bio; public UserSummaryView(Context context) { super(context); init(context); } public UserSummaryView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public UserSummaryView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); }
Subclass ViewGroup private void init(Context context){ setOrientation( VERTICAL ); LayoutInflater. from (context).inflate( R.layout. view_user_summary , this); profileImage = (ImageView)findViewById(R.id. user_summary_image ); name = (TextView)findViewById(R.id. user_summary_name ); title = (TextView)findViewById(R.id. user_summary_title ); bio = (TextView)findViewById(R.id. user_summary_bio ); } public void setUser(User user){ Picasso. with (getContext()) .load(user.getProfileImageUrl()) .into(profileImage); name.setText(user.getName()); title.setText(user.getJobTitle()); bio.setText(user.getBio()); }
Subclass ViewGroup private void init(Context context){ setOrientation( VERTICAL ); LayoutInflater. from (context).inflate( R.layout. view_user_summary , this); profileImage = (ImageView)findViewById(R.id. user_summary_image ); name = (TextView)findViewById(R.id. user_summary_name ); title = (TextView)findViewById(R.id. user_summary_title ); bio = (TextView)findViewById(R.id. user_summary_bio ); } public void setUser(User user){ Picasso. with (getContext()) .load(user.getProfileImageUrl()) .into(profileImage); name.setText(user.getName()); title.setText(user.getJobTitle()); bio.setText(user.getBio()); }
Subclass ViewGroup <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/user_summary_image" android:layout_width="match_parent" android:layout_height="256dp" tools:src="@drawable/profile_sample" android:scaleType="centerCrop" /> <TextView tools:text="Luke Sleeman" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/user_summary_name" …
Subclass ViewGroup <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <ImageView android:id="@+id/user_summary_image" android:layout_width="match_parent" android:layout_height="256dp" tools:src="@drawable/profile_sample" android:scaleType="centerCrop" /> <TextView tools:text="Luke Sleeman" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/user_summary_name" …
Recommend
More recommend