20120308 droid4me-paug presentation


Published on

Published in: Technology, Education
  • Be the first to comment

  • Be the first to like this

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

20120308 droid4me-paug presentation

  1. 1. ANDROID FRAMEWORKPAUG Presentation - March, 8th 2012
  2. 2. Agenda● Context● Getting started● Overview ○ Project design principles ○ Major components● Focus on... ○ BitmapDownloader ○ ActivityController / Redirector / Interceptor● Roadmap● Questions and answers
  3. 3. Context Where does this framework project comes from● The droid4me framework project was started in early 2008 ○ for internal usage initially ○ tested against multiple applications ○ released open-source LGPL in 2010● It is compatible with Android v1.6+ ; works with Android v3+ and the Android Support Package● It is a framework, but also exposes components● Released as a stand-alone .jar library● Composed of about 16k lines of code● Used in several industrial Android applications
  4. 4. Getting started If you want to give it a try...1. Download the source code, compile it (via Ant)2. Read the documentation3. Add the .jar to the classpath4. Derive from the SmartApplication and implement the methods5. Derive from the Smartable Activities and Fragment, and implement the methods6. Discover and use the components7. Have fun!
  5. 5. Overview Project design principles● It was designed to be as much extensible as possible ○ you do not necessarily need to derive from the provided Activity, Fragment and Application classes ○ you can turn any Activity or Fragment "droid4me-ready" through the Droid4mizer component● It was designed to expose components as much as possible independent ○ most of the components are stand-alone and may be used outside of the framework context ○ but put all together in an application makes Android application development much expressive, more reliable and faster● Its ambition is to be industrialized and re-usable ○ the same framework should be re-used on multiple applications
  6. 6. Overview Major components● SmartApplication● LifeCyle / Smartable / Smarted / Droid4mizer● ActivityController / Interceptor / Redirector / ExceptionHandler● Logger● BroadcastListenerProvider/BroadcastListener● SmartCommands● BusinessViewWrapper / BusinessViewHolder● MenuHandler● BitmapDownloader● Persistence● WebServiceCaller● TokenKeeper
  7. 7. Focus on... Two interesting featuresThere are several facets of the framework,involving numerous concepts, but we wanted tofocus on:● The BitmapDownloader: a widget bitmap download and binding independent module, which is worth to be shown● The ActivityController: a component tightly used in the framework, which helps developing more robust applications, and which attempts to provide Aspect Oriented Programming (AOP)
  8. 8. BitmapDownloader OverviewThe BitmapDownloader is a reliable low-latency,high performance component which downloads,caches and binds bitmaps to Android widgets in anextensible way ● uses two tunable worker threads pools ● works with cache memory water mark levels ● integrates easily to cache persistence ● optimizes the bitmap downloads ● multi-instances ● enables to pre-load bitmaps ● re-usable download and binding policies ● unitary tested
  9. 9. BitmapDownloader Questions● How does your current implementation behave when the cache memory increases?● What happens when the end-user insanely scrolls up and down on a ListView holding ImageViews? ○ Is the same bitmap re-downloaded several times? ○ Does the widget display a previous bound bitmap? ○ Do the widget bitmaps flicker?● What happens if the bitmap URL is wrong/null, or the bitmap cannot be downloaded?● Does your current implementation take the already downloaded bitmap from a persistence cache? Does it save the downloaded bitmaps to such cache?
  10. 10. BitmapDownloader Design: the BitmapDownloader APIBitmapDownloader.getInstance(N).get( View view, String bitmapUid, Object imageSpecs, Handler handler, Instructions instructions) ● N is the instance ● view is the widget (not necessarily an ImageView) ● bitmapUid is the UID which enables to compute the bitmap URL ● imageSpecs is a free (untyped) optional (may be null) placeholder for providing additional context information, which will be provided during the workflow ● handler is used to run some code on the UI ● instructions is the interface which exposes callbacks which will be requested during the overall command workflow (pull strategy)
  11. 11. BitmapDownloader Design: the Instructions interface (1/2)The Instructions interface is responsible for answering about the downloadand binding strategy. It is responsible for performing unitary tasks directed bythe BitmapDownloader, which passes the bitmapUid and imageSpecs tomost callbacks, and consume events. Here are some key callbacks:interface Instructions{ String computeUrl(String bitmapUid, Object imageSpecs); boolean hasTemporaryBitmap(String bitmapUid, Object imageSpecs); void onBindTemporaryBitmap(ViewClass view, String bitmapUid, Object imageSpecs); InputStream getInputStream(String bitmapUid, Object imageSpecs, String url,InputStreamDownloadInstructor instructor) throws IOException; InputStream downloadInputStream(String bitmapUid, Object imageSpecs, String url)throws IOException; InputStream onInputStreamDownloaded(String bitmapUid, Object imageSpecs, Stringurl, InputStream inputStream); void onBitmapReady(boolean allright, ViewClass view, BitmapClass bitmap, StringbitmapUid, Object imageSpecs);}
  12. 12. BitmapDownloader Design: the Instructions interface (2/2)The Instructions will typically be requested (the list below is not comprehensive): ● for indicating if a temporary bitmap should be bound while the target bitmap is being loaded ● for computing the bitmap URL if it needs to be downloaded or take from a persistence cache ○ the logic of computing the URL is shifted in a central place ● for attempting to extract the requested bitmap from a persistence cache ○ you may use your own persistence library● for downloading the bitmap bytes if necessary ○ you may fine-tune the time-outs, "User-Agent" HTTP header● for storing the downloaded bitmap into the persistence cache if any ○ use your own persistence library, or the droid4me Persistence component● for converting the downloaded bytes into a bitmap (which is done through the BitmapFactory by default) ○ you may apply bitmap transformations (water marks, reflection effects ...) ● for binding the bitmap to the widget ○ you may apply animationsThe same Instructions implementation object may be a singleton and re-use throughout the application!
  13. 13. BitmapDownloader Design: recapFor binding a bitmap corresponding to a URL with theBitmapDownloader, you need to:1. decide what instance to use2. define an Instructions implementation that will be requested at runtime3. invoke the BitmapDownloader.get() method, provide the widget, the bitmap UID, an optional context, and the Instructions implementation4. let the BitmapDownloader do the work and invoke the provided Instructions by triggering finely tuned methods/callbacks/events
  14. 14. BitmapDownloader Architecture: how does it work inside?Each BitmapDownloader.get() request generates acommand1. this "pre" command is provided to a first LIFO worker threads pool, responsible for: ○ checking if the bitmap should be extracted from the .apk ○ searching in the memory cache if the bitmap is available and binding it ○ binding a temporary bitmap to the widget if applicable2. if the "pre" command execution did not complete with a final binding, a "download" command is created and submitted to a second LIFO worker threads pool, responsible for: ○ asking the bitmap from the persistence cache ○ downloading the bitmap bytes if necessary and provide it to the persistence cache ○ binding the downloaded bitmap to the widget
  15. 15. BitmapDownloader Why it is efficient and low-latencyThe BitmapDownloader ensures various contracts, whichmakes it efficient and low-latency:● the bytes of a bitmap are never downloaded twice, even between BitmapDownloader instances● a command is always executed in LIFO mode, and all pending commands attached to the same widget are cancelled● the memory cache is always requested first● the memory consumption is monitored and its allocation limits are respected for each instance independently: whenever a high water mark level is reached, a clean-up process is run, and the most frequently accessed bitmaps are kept in memory (this policy should be customizable in the future)● if a OutOfMemoryException may arise, it is caught and the cache is cleaned-up
  16. 16. BitmapDownloader Why it is extensibleThe BitmapDownloader works with the Instructionsinterface, which is by nature extensible:● the persistence cache interaction is totally at your control. However, you may use the droid4me Persistence component on that purpose ;● the bitmap bytes download process is totally customizable: you may use an HttpClient, for instance. One of the provided implementation uses the URLConnection● you do not necessarily need to use an ImageView, but only View- derived widgets● you may use it to pre-load bitmaps through the BitmapDownloader.get() alternate method form (with a null widget argument), which controls the internal commands threading
  17. 17. BitmapDownloader Fine tuningThe BitmapDownloader can be fine-tuned: ● set it before using it, typically in the Application.onCreate() methoddecide how many instances to use (BitmapDownloader.INSTANCES_COUNTvariable)● for each instance, decide the water mark levels (BitmapDownloader. MAX_MEMORY_IN_BYTES and BitmapDownloader. LOW_LEVEL_MEMORY_WATER_MARK_IN_BYTES variables)● you can dynamically indicate if no Internet connection if available through the BitmapDownloader.setConnected() method, which prevents from battery and CPU waste● for advanced tweaking, decide how many core threads to allocate in each threads pool (BitmapDownloader.setPreThreadPoolSize() and BitmapDownloader.setDownloadThreadPoolSize() methods)
  18. 18. ActivityController OverviewThe ActivityController is a centralcomponent responsible for:● handling Activity/Fragment exceptions● redirecting an Activity instances like a controller● triggering Activity/Fragment instances life cycle events
  19. 19. ActivityController Questions● How do you handle connectivity issue problems in your code? Recurring exceptions?● How many times do you check that some screen has actually been displayed before another?● How do you integrate the analytics SDK?● How do provide objects to Activity/Fragment instances which have no common inheritance?
  20. 20. ActivityController Design● An Android Context-independent singleton available through the ActivityController.getInstance() method● Enables to register: ○ an ExceptionHandler interface, responsible for handling exceptions ○ a Redirector interface, responsible for ensuring complex Activity workflowsan Interceptor interface, which exposescallbacks triggered duringActivity/Fragment entities life cycle events
  21. 21. ActivityController The ExceptionHandler API● The ExceptionHandler interface exposes onXXXException() callback methods, which will be triggered when an exception occurs in the managed part of the framework ○ All those methods take the originating Activity and the Fragment (null if not applicable) as an argument ○ They obviously take the exception as an argument and return a boolean which states whether the exception has actually been handled● The ActivityController exposes a handleException() method which dispatches the exception to the right onXXXException() callback The SmartCommands worker threads pool invokes it when a background issues an exception
  22. 22. ActivityController The Redirector APIThe Redirector interface exposes a single callbackmethod, and behaves like a controller: Intent getRedirection(Activity activity)● This method is invoked during the Activity.onCreate() execution via the ActivityController.needsRedirection() method, which asks the Redirector (if not null) whether another Activity should be started instead● The Redirector.getRedirection() method is invoked with the currently started activity, and if it returns a non-null Intent, it is used to start another Activity, which is passed the initial Activity Intent● Once finished, the redirected Activity can resume the initial Activity by invoking the ActivityController.extractCallingIntent()This eases the writing of workflows, without having to codethe logic on each Activity. The concept is re-usable.
  23. 23. ActivityController The Interceptor APIThe Interceptor interface exposes a single callbackmethod:void onLifeCycleEvent(Activity activity, Object component, ActivityController.Interceptor.InterceptorEvent event)● This method is invoked at every life cycle key event of an Activity / Fragment entity, with the hosting activity, the Fragment component (null if the event belongs to an Activity), and the event (an enumerated type) as arguments● This method is invoked from the ActivityController. onLifeCycleEvent() method, which delegates the execution to the Interceptor if not nullThis component enables to handle Activity/Fragmententity events is a very centralized way, a bit like in AOP
  24. 24. ActivityController InitializationThe framework offers a SmartApplication abstractclass inherited from the Android legacy Applicationclass, which offers to register in one point theActivityController aggregate.● Either inherit from this SmartApplication and implement/override: ○ getExceptionHandler(): registers the ExceptionHandler ; a DefaultExceptionHandler is already returned by default ○ getActivityRedirector(): registers the Redirector ○ getActivityInterceptor(): registers the Interceptor● Or register those ActivityController components yourself before any Activity is displayed!
  25. 25. ActivityController Recap and use casesThe ActivityController is a central component which offers some key featureslike exception handling, screen workflows management and life cycle events ina very centralized way through 3 interfaces:● the ExceptionHandler which lets you react to exceptions in an industrialize way. Typical use cases: => Alert dialog boxes, toasts, logging of errors through analytics or error reporting libraries like ACRA● the Redirector which lets you handle Activity workflows. Typical use cases: => splash screens, authentication / registration forms● the Interceptor which lets you react to life cycle events. Typical use cases: => integrating analytics => transmit, extract data (through the Smarted.get/setAggregate() API) without imposing inheritance => invoke Activity/Fragment methods in a transversal way
  26. 26. Roadmap Evolution thoughts● More documentation● Define a better project governance● Integrate the library to a software factory● Propose optionally to split the framework into separate libraries ○ a core.jar ○ a .jar for each major component● Provide more opening entry points● Clean up some contracts● Provide a getting started / demonstrator application● Use a visitor pattern to the ActivityController Redirector and Interceptor components● Review the MenuHandler component
  27. 27. Thank you!Questions and answers? http://droid4me.googlecode.com/ Twitter : dr0id4me