0
A Unified Approach to Callbacks in Android           Matt Brenner – UnME2, Inc.               mbrenner@unme2.com          ...
Background KnowledgeThis talk will include discussion of,   threads   Interfaces   callbacks   Observer Design Patternand ...
A Unified Approach to Callbacks in AndroidIn Java, callbacks commonly occur within processes:   between threads   to decou...
“Worker Thread” Callbackpublic Interface Requester {          public void complete ( );                               Requ...
“Domain-to-Interface” Callback (Observer Pattern)                                                                        O...
Android Makes Extensive Use IntentsIntents are used:    for inter-process and inter-Activity comms   to invoke Activities ...
Activity Callback(Calling Activity)public class AnActiviy extends Activity {          static private final int            ...
Activity Callback(Called Activity)public class ActivityGetyesno extends Activity {          ...          protected void on...
A Bit of a Mess  Multiple callbacks in various forms lead to:     interface “clutter”     multiple callback forms in a sin...
Event Consumer         Activity                        SuperActivity «abstract»                                           ...
Using the Event Consumer PatternLets see how to use Event Consumer for callbacks:    from a worker-thread    from domain t...
Event Consumer: “Worker Thread” CallbackOld Version (caller)New Version (caller)                               NewVersion ...
Event Consumer: “Domain-to-Interface” CallbackNew Version                                          Old Versionpublic class...
Event Consumer: Intent CallbackNew Version (Calling Activity)                         Old Version (Calling Activity)public...
Event Consumer: Intent CallbackNew Version (Called                             Old Version (Called Activity)Activity) Acti...
Helper Class for Intent Callbacks: LauncherLauncher encapsulates the gory details of creating and firing Intents     many ...
public class AnActiviy extends SuperActivity {                                            static private final int        ...
An Unsatisfying AspectI commonly apply Eventconsumer to Activities:   extend Superactivity   implemement event methodIt is...
Event Consumer         Activity                        SuperActivity «abstract»                                           ...
Upcoming SlideShare
Loading in...5
×

Mattbrenner

608

Published on

Published in: Technology, Business
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
608
On Slideshare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
14
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Transcript of "Mattbrenner"

  1. 1. A Unified Approach to Callbacks in Android Matt Brenner – UnME2, Inc. mbrenner@unme2.com Droidcon Berlin 2013
  2. 2. Background KnowledgeThis talk will include discussion of, threads Interfaces callbacks Observer Design Patternand make extensive use of UML.Dont worry, well “fill in” all gaps along the way!
  3. 3. A Unified Approach to Callbacks in AndroidIn Java, callbacks commonly occur within processes: between threads to decouple domain / interface (e.g. Observer)
  4. 4. “Worker Thread” Callbackpublic Interface Requester { public void complete ( ); Requester} «interface»public class Mainclass implements Requester { + complete( ) : void ... public void dosomething (...) { ... (new Worker (this)).start (); } Mainclass public void complete ( ) { + dosomething (...) : void ... + complete( ) : void } ...}public class Worker extends Thread { private Requester requester_; Thread ... public Worker (Requester requester) { requester_ = requester } ... public void run( ) { Worker ... requester_.complete ( ); + Worker (requester : Requester) } + run ( ) : void} ...
  5. 5. “Domain-to-Interface” Callback (Observer Pattern) Observerpublic class Widget implements Observer { «interface» ... public Widget (Domainthing thing) { + update (:Observable, data : Object) : void ... thing.addObserver (this); } public void update (Observable obs, Object Widgetdata) { ... + Widget (:Domainthing) } + update (:Observable, data : Object) : void} ...public class Domainthing extends Observable { Observable ... private void domainchange (Object data ) { + addObserver (:Observer) : void + setChanged ( ) : void ... setChanged ( ); + notifyObservers (:Object) : void notifyObservers (data); }} Domainthing
  6. 6. Android Makes Extensive Use IntentsIntents are used: for inter-process and inter-Activity comms to invoke Activities (passing params) to callback from one Activity to another (return a result)
  7. 7. Activity Callback(Calling Activity)public class AnActiviy extends Activity { static private final int GOTYESNO = 1, ... public void askyesno( ) { Intent intent; ... intent = new Intent (this, ActivityGetyesno.class); intent.putExtra (“title”, R.string.delete_all_title); intent.putExtra (“msg”, R.string.delete_all_msg); startActivityForResult (intent, GOTYESNO); } protected void onActivityResult (int id, int result, Intent data) { if (id == GOTYESNO) { if (data.hasExtra (“RESULT”)) { result = data.getExtras( ).getString(“RESULT”); if (result.equals (“yes”)) { ... } } } } ...}
  8. 8. Activity Callback(Called Activity)public class ActivityGetyesno extends Activity { ... protected void onCreate (Bundle bundle) { super.onCreate (bundle); String title, message; title = message = null; Bundle params = getIntent ( ).getExtras( ); if (params != null) { title = params.getString (“title”); message = params.getString(“msg”); } ... } public void clickno (View view) { done (“no”); } public void clickyes (View view) { done (“yes”); } private void done (String result) { Intent intent = new Intent ( ); intent.putExtra (“RESULT”, result); setResult (Activity.RESULT_OK, intent); finish ( ); }
  9. 9. A Bit of a Mess Multiple callbacks in various forms lead to: interface “clutter” multiple callback forms in a single class Intent syntax is klunky and repetitiousNew design pattern to the rescue: Event Consumer (Brenner)
  10. 10. Event Consumer Activity SuperActivity «abstract» Eventconsumer «interface»+ event (eventid : int) : void+ event (eventid : int, data : Object) : void + event (eventid : int) : void+ event (eventid : int, data : Object, resultcode : int) : void + event (eventid : int, data : Object+ onActivityResult (eventid : int, resultcode : int, intent : Intent) : void# abort ( ) : void# done (response : int) : void# done (response : String) : void# getparamstring ( ) : String# getresult ( ) : int# getresultstring ( ) : String# isabort ( ) : boolean# isuccess ( ) : boolean# isyes ( ) : boolean AnActivity + func ( ) : void + event (eventid : int, data : Object) : void DialogActivity «abstract»+ onCreate (bundle: Bundle, layout : int) : void+ event (eventid : int, data : Object) : void+ getitlefield ( ) : TextView+ getmsgfield ( ) : TextView+ onBackPressed ( ) : void ActivityGetyesnodialog + onCreate (bundle : Bundle) : void + clickno (View view) : void + clickyes (View view) : void
  11. 11. Using the Event Consumer PatternLets see how to use Event Consumer for callbacks: from a worker-thread from domain to interface between Intents
  12. 12. Event Consumer: “Worker Thread” CallbackOld Version (caller)New Version (caller) NewVersion (worker) Old Version (worker) Interface Requester {public class Mainclass public class Worker extends Thread { public void complete ( ); implements Eventconsumer Requester private int requester_; eventid_;}{ ... static private final int COMPLETE = 1; privateWorker (Requester requeseter) { public Eventconsumer caller_;public class Mainclass implements Requester { ... requester_ = requeseter; ... } public Worker (Eventconsumer caller, int eventid) { public void dosomething (...) { ... caller_ = caller; ... (new Worker (this, COMPLETE)).start ( public void run( = {eventid; eventid_ )); (new Worker (this).start (); } ... } requester_.complete( ); } public void run ( ) { public void complete ( ) { } ... ... public void event (int eventid, Object data) { caller_.event (eventid_); } switch (eventid) { }} case COMPLETE: } ... break; } }}
  13. 13. Event Consumer: “Domain-to-Interface” CallbackNew Version Old Versionpublic class Widget Old Version public class Widget implements Observer { implements Eventconsumer ... public class Domainthing extends Observable {{ ... static private final int UPDATE = 1; private void domainchange (Object data ) { ... ... public Widget (Domainthing thing) { setChanged ( ); public void observe (Domainthing thing) { ... notifyObservers (data); thing.addobserver (this, UPDATE); thing.addObserver (this); } } } } public void event (int eventid, Object data) { public void update (Observable obs, Object data) { switch (eventid) { ... case UPDATE: } ... New Version } break; public class Domainthing { } private int eventid_; } private Eventconsumer observer_;} ... public void addobserver (Eventconsumer obs, int eventid) { observer_ = obs; eventid_ = eventid; } private void domainchange (Object data) { ... observer_.event (eventid, data); } }
  14. 14. Event Consumer: Intent CallbackNew Version (Calling Activity) Old Version (Calling Activity)public class AnActiviy extends SuperActivity { public class AnActiviy extends Activity { static private final int GOTYESNO = 1; static private final int GOTYESNO = 1, ... ... public void askyesno( ) { public void askyesno( ) { Launcher launcher; Intent intent; ... ... lancher = new Launcher (this, GOTYESNO, intent = new Intent (this, ActivityGetyesno.class); R.string.delete_all_title, intent.putExtra (“title”, R.string.delete_all_title);R.string.delete_all_msg); intent.putExtra (“msg”, R.string.delete_all_msg); startActivityForResult (intent, GOTYESNO); launcher.launch (ActivityGetyesno.class); ... } } protected void onActivityResult (int id, int result,Intent data) public void event (int eventid, Object data) { { switch (eventid) { if (id == GOTYESNO) { case GOTYESNO: if (data.hasExtra (“RESULT”)) { if (isyes()) { result = data.getExtras( ).getString ... (“RESULT”); } if (result.equals (“yes”)) { break; ... } } } }} } } }
  15. 15. Event Consumer: Intent CallbackNew Version (Called Old Version (Called Activity)Activity) ActivityGetyesnopublic class public class ActivityGetyesno extends Activity { extends DialogActivity ...{ protected void onCreate (Bundle bundle) { public void onCreate (Bundle bundle) { super.onCreate (bundle); super.onCreate (bundle,R.layout.dialog_yesno); String title, message; ... } title = message = null; Bundle params = getIntent ( public void clickno (View view) { ).getExtras ( ); done (NO); if (params != null) { } title = params.getString (“title”); public void clickyes (View view) { message = done (YES); params.getString (“msg”); } }} ... } public void clickno (View view) { done (“no”); } public void clickyes (View view) { done (“yes”); } private void done (String result) { Intent intent = new Intent ( ); intent.putExtra (“RESULT”, result); setResult (Activity.RESULT_OK, intent);
  16. 16. Helper Class for Intent Callbacks: LauncherLauncher encapsulates the gory details of creating and firing Intents many convenient constructors manages parameters passing creates Intent launch method invokes: startActivity (...) or startActivityForResult (...) Launcher + Launcher (: Activity, eventid : int) + Launcher (: Activity, param : String) + Launcher (: Activity, eventid : int, param : String) + Launcher (: Activity, title : int, msg : int) + Launcher (: Activity, title : String, msg : String) + Launcher (: Activity, eventid : int, title : int, msg : int) + Launcher (: Activity, eventid : int, title : int, msg : int, list : String[ ]) + Launch (cls : Class<?>) : void + setgravity (gravity : int) : void + setmaxdigits (: int) : vod + setmindigits (: int) : void + setmultiline( ) : void + setparam (key : String, value : String) : void + trapabort( ) : void
  17. 17. public class AnActiviy extends SuperActivity { static private final int COMPLETE = 1, UPDATE = 2,Voila! A Unified Approach to Callbacks: GOTYESNO = 3; ... Worker Thread public void dosomething (...) { Domain-to-Interface (new Worker (this, COMPLETE)).start ( ); } Intent-to-Intent public void observe (Domainthing thing) { thing.addobserver (this, UPDATE); } public void asktyesno( ) { Launcher launcher; ... lancher = new Launcher (this, GOTYESNO, R.string.delete_all_title, R.string.delete_all_msg); launcher.launch (ActivityGetyesnodialog.class); } public void event (int eventid, Object data) { switch (eventid) { case COMPLETE: // thread-to- thread callbackevent ... break; case UPDATE: // domain-to-interface callback event ... break; case GOTYESNO: // intent-to-intent callback event if (isyes()) { ... } break; } } }
  18. 18. An Unsatisfying AspectI commonly apply Eventconsumer to Activities: extend Superactivity implemement event methodIt is natural to apply it to ListActivity too: create SuperListActivity must duplicate (or delegate) methods similar to those in SuperActivity
  19. 19. Event Consumer Activity SuperActivity «abstract» Eventconsumer «interface»+ event (eventid : int) : void+ event (eventid : int, data : Object) : void + event (eventid : int) : void+ event (eventid : int, data : Object, resultcode : int) : void + event (eventid : int, data : Object+ onActivityResult (eventid : int, resultcode : int, intent : Intent) : void# abort ( ) : void# done (response : int) : void# done (response : String) : void# getparamstring ( ) : String# getresult ( ) : int# getresultstring ( ) : String# isabort ( ) : boolean# isuccess ( ) : boolean# isyes ( ) : boolean AnActivity + func ( ) : void + event (eventid : int, data : Object) : void DialogActivity «abstract»+ onCreate (bundle: Bundle, layout : int) : void+ event (eventid : int, data : Object) : void+ getitlefield ( ) : TextView+ getmsgfield ( ) : TextView+ onBackPressed ( ) : void ActivityGetyesnodialog + onCreate (bundle : Bundle) : void + clickno (View view) : void + clickyes (View view) : void
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×