Most of the apps has a BaseActivity. Reusing activity codes. Inheritance? In most situations we reuse functionality. Com
Balogh Tamás
Composition over Inheritance on Android
github.com/BaloghTamas/Composition
The theory behind
The problem class TimeLogger { void log (…){...} }
//prints time
class NameLogger { void log (…){...} }
//prints classname
class TimeNameLogger extends TimeLogger,NameLogger { void log (…){...} //should print classname and time in that order }
The theory behind
Inheritance Implementation inheritance • class Some extends Other To achieve code reuse Suitable for IS-A relationship For reusing fields and state Problems • Designed for extension? • Across boundaries? • Class must evolve with the Superclass • Violates encapsulation
The theory behind
Composition ~Delegation Pattern • Delegator class compose a field of the reused class • Often using a list of delegated classes (~ similarities to Strategy Pattern)
Suitable for HAS-A relationship For extending functionality Achieving sort of multiple inheritance Problems • More boilerplate • Delegator class must evolve with composed classes
The theory behind
A possible solution … interface Logger{ void log(…){…}} class TimeLogger implements Logger { void log (…){...} //prints time } class NameLogger implements Logger{ void log (…){...} // prints classname } class TimeNameLogger{ List loggers; void log (…){...} //iterates through loggers and call log }
Composition on Android
Compose Adapters Adapter – Transforms Model item to View item, handles Recycling Delegate the transformation of a model type to an AdapterDelegate interface AdapterDelegate{ ViewHolder onCreateViewHolder (…); void onBindViewHolder (…); int getItemType(); } class DeliveriesAdapter extends BaseAdapter{ List delegates; ViewHolder onCreateViewHolder(…); //finds and calls delegate void onBindViewHolder(…); //finds and calls delegate int getItemType(); //calls the proper delegate }
Composition on Android
Compose Adapters
class ReceiveAdapter implements AdapterDelegate{ ViewHolder onCreateViewHolder(…) {...} void onBindViewHolder(…) {...} int getItemType() {…}
class SendAdapter implements AdapterDelegate{ ViewHolder onCreateViewHolder(…) {...} void onbindViewHolder(…) {...} int getItemType() {…}
Composition on Android
Compose Adapters Example: Delivery Tracking Application • • • •
List with multiple types A screen for things that I receive A screen for things that I send A screen for both
Change Request #1 • Lets add sections/headers to that list • With inheritance
CalendarDeliveryAdapter extends DeliveryAdapter
• With composition
addAdapterDelegate(new HeaderDelegate(…))
Composition on Android
Compose Adapters Change Request #2 • Display Offers just for “Send” screen. • Display Options for picking up your package only for “Receive” screen. • With inheritance OffersAdapter extends CalendarDeliveryAdapter OptionsAdapter extends CalendarDeliveryAdapter
• With composition addAdapterDelegate(new OfferDelegate(…)) addOptionDelegate(new OptionDelegate(…))
Change Request #3 • • • •
Display Offers and Options on overview screen But don’t categorize by date With inheritance - Refactor! With composition – Just add the right delegates
Composition on Android
Compose Activities Extending an Activity Even a “Hello world” requires that
Having base activity classes Most of the apps has a BaseActivity
Reusing activity codes Inheritance? In most situations we reuse functionality
Composition on Android
Compose Activities Utilize Social Libraries High depend on Activity lifecycle Base class: class SocialActivity extends AppCompatActivity MyActivity extends SocialActivity
Utilize ThemeActivity Sets the theme class ThemeActivity extends AppCompatActivity MyActivity extends ThemeActivity
What if an Activity both Social and Themed? Multiple inheritance? Code duplication?
Composition on Android
Compose Activities interface ActivityDelegate{ public void onCreate(…); //... public void onDestroy(…); } abstract class CompositeActivity extends AppCompatActivity{ List delegates public void onCreate(…){...} //iterates through delegates }
//...
and calls ...
Composition on Android
Compose Activities class SocialDelegate implements ActivityDelegate{ public void onCreate(…){...} // Social integration logic } class ThemedDelegate implements ActivityDelegate{ public void onCreate(…){...} // Theme handling logic }
Should provide activity reference for letting delegates access activity Protected fields and methods are not available Can be used for Fragments the same way
Composition on Android
Summary
Inheritance is not always the key for reuse IS-A -> Use inheritance HAS-A -> Use composition Inherit state -> Use inheritance Inherit functionality -> Use composition Multiple inheritance-> Use composition On Android • For flexible Adapter -> Compose Adapters • For multiple Activity/Fragment inheritance -> Compose Activities/Fragments
Composition on Android
References Joshua Bloch – Effective java Hannes Dorfmann - JOE'S GREAT ADAPTER HELL ESCAPE
github.com/BaloghTamas
[email protected]
The future
.. and another possible solution interface Logger { fun log() } interface TimeLogger: Logger { override fun log(){ Log.d("Time", Date().toString())} } interface NameLogger: Logger { override fun log(){ Log.d("Name",javaClass.toString())} } class NameTimeLogger: TimeLogger, NameLogger{ override fun log() { super.log() super.log() } }