20120308 droid4me-paug presentation

27
ANDROID FRAMEWORK PAUG Presentation - March, 8 th 2012

Upload: paris-android-user-group

Post on 13-Jun-2015

659 views

Category:

Technology


1 download

TRANSCRIPT

Page 1: 20120308 droid4me-paug presentation

ANDROID FRAMEWORK

PAUG Presentation - March, 8th 2012

Page 2: 20120308 droid4me-paug presentation

Agenda

● Context● Getting started● Overview

○ Project design principles○ Major components

● Focus on...○ BitmapDownloader○ ActivityController / Redirector / Interceptor

● Roadmap● Questions and answers

Page 3: 20120308 droid4me-paug presentation

Context

● 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

Where does this framework project comes from

Page 4: 20120308 droid4me-paug presentation

Getting started

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!

If you want to give it a try...

Page 5: 20120308 droid4me-paug presentation

Overview

● 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

Project design principles

Page 6: 20120308 droid4me-paug presentation

Overview

● SmartApplication● LifeCyle / Smartable / Smarted / Droid4mizer● ActivityController / Interceptor / Redirector /

ExceptionHandler● Logger● BroadcastListenerProvider/BroadcastListener● SmartCommands● BusinessViewWrapper / BusinessViewHolder● MenuHandler● BitmapDownloader● Persistence● WebServiceCaller● TokenKeeper

Major components

Page 7: 20120308 droid4me-paug presentation

Focus on...

There are several facets of the framework, involving numerous concepts, but we wanted to focus 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)

Two interesting features

Page 8: 20120308 droid4me-paug presentation

BitmapDownloader

The BitmapDownloader is a reliable low-latency, high performance component which downloads, caches and binds bitmaps to Android widgets in an extensible 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

Overview

Page 9: 20120308 droid4me-paug presentation

BitmapDownloader

● 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?

Questions

Page 10: 20120308 droid4me-paug presentation

BitmapDownloader

BitmapDownloader.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)

Design: the BitmapDownloader API

Page 11: 20120308 droid4me-paug presentation

BitmapDownloader

The Instructions interface is responsible for answering about the download and binding strategy. It is responsible for performing unitary tasks directed by the BitmapDownloader, which passes the bitmapUid and imageSpecs to most 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, String url, InputStream inputStream);

void onBitmapReady(boolean allright, ViewClass view, BitmapClass bitmap, String bitmapUid, Object imageSpecs);

}

Design: the Instructions interface (1/2)

Page 12: 20120308 droid4me-paug presentation

BitmapDownloader

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 animations

The same Instructions implementation object may be a singleton and re-use throughout the application!

Design: the Instructions interface (2/2)

Page 13: 20120308 droid4me-paug presentation

BitmapDownloader

For binding a bitmap corresponding to a URL with the BitmapDownloader, 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 implementation

4. let the BitmapDownloader do the work and invoke the provided Instructions by triggering finely tuned methods/callbacks/events

Design: recap

Page 14: 20120308 droid4me-paug presentation

BitmapDownloader

Each BitmapDownloader.get() request generates a command1. 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 applicable

2. 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

Architecture: how does it work inside?

Page 15: 20120308 droid4me-paug presentation

BitmapDownloader

The BitmapDownloader ensures various contracts, which makes 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

Why it is efficient and low-latency

Page 16: 20120308 droid4me-paug presentation

BitmapDownloader

The BitmapDownloader works with the Instructions interface, 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

Why it is extensible

Page 17: 20120308 droid4me-paug presentation

BitmapDownloader

The BitmapDownloader can be fine-tuned:● set it before using it, typically in the Application.onCreate() method

decide how many instances to use (BitmapDownloader.INSTANCES_COUNT variable)● 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)

Fine tuning

Page 18: 20120308 droid4me-paug presentation

ActivityController

The ActivityController is a central component responsible for: ● handling Activity/Fragment exceptions● redirecting an Activity instances like a

controller● triggering Activity/Fragment instances

life cycle events

Overview

Page 19: 20120308 droid4me-paug presentation

ActivityController

● 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?

Questions

Page 20: 20120308 droid4me-paug presentation

ActivityController

● 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 exposes callbacks triggered during Activity/Fragment entities life cycle events

Design

Page 21: 20120308 droid4me-paug presentation

ActivityController

● 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

The ExceptionHandler API

Page 22: 20120308 droid4me-paug presentation

ActivityController

The Redirector interface exposes a single callback method, 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 code the logic on each Activity. The concept is re-usable.

The Redirector API

Page 23: 20120308 droid4me-paug presentation

ActivityController

The Interceptor interface exposes a single callback method: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 null

This component enables to handle Activity/Fragment entity events is a very centralized way, a bit like in AOP

The Interceptor API

Page 24: 20120308 droid4me-paug presentation

ActivityController

The framework offers a SmartApplication abstract class inherited from the Android legacy Application class, which offers to register in one point the ActivityController 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!

Initialization

Page 25: 20120308 droid4me-paug presentation

ActivityController

The ActivityController is a central component which offers some key features like exception handling, screen workflows management and life cycle events in a 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

Recap and use cases

Page 26: 20120308 droid4me-paug presentation

Roadmap

● 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

Evolution thoughts

Page 27: 20120308 droid4me-paug presentation

Thank you!

Questions and answers?

http://droid4me.googlecode.com/ Twitter : dr0id4me