developing apps for emerging markets

Post on 09-Feb-2017

256 Views

Category:

Mobile

2 Downloads

Preview:

Click to see full reader

TRANSCRIPT

ONLINE-OFFLINEDeveloping Apps for Emerging Markets

OFF GRID ELECTRIC

From: https://medium.com/@Offgrid

OFF GRID ELECTRIC

AGENDA

ARCHITECTURELIBRARIES

CHALLENGES

ARCHITECTURE

BE USEFUL

My App ‣Store data locally ‣Separate UI and network ‣Queue requests

MVP(Model View Presenter)

EVENT BUS

DATABASE

REPOSITORY

REPOSITORY

ACTIVITY

FRAGMENT

JOBS

PRESENTER

PRESENTER

SERVICE

DISPLAY A VIEW

PRESENTER

SERVICE

ACTIVITY

EVENT BUS

DATABASEREPOSITORY

TAKE AN ACTION

PRESENTER

SERVICE

ACTIVITY

EVENT BUS

DATABASEREPOSITORY

JOB NETWORK

APP SERVER

AGREE ON

‣Conflict Resolution ‣Adding Timestamps to Requests ‣Bundling Requests ‣Use of Status Fields

EVENT BUS

DATABASE

REPOSITORY

REPOSITORY

ACTIVITY

FRAGMENT

JOBS

PRESENTER

PRESENTER

SERVICE

LIBRARIES

WHAT WE USE

‣Realm ‣EventBus ‣Android Job

STORE DATA LOCALLY

REALM

▸Easy to Set Up

▸Faster than ORMs

▸Has a Fluent API

REALM - MODEL CLASS

@RealmClasspublic class Place implements RealmModel{

}

REALM - MODEL CLASS

@RealmClasspublic class Place implements RealmModel{ @PrimaryKey private String localId;

@Index private Long remoteId;private Gps location; …

}

REALM - MODEL CLASS

localId remoteId location

19444498-2a40… 1458260

65031f36-bde9…

e85c9757-f546…

REALM - ADDING A RECORD

public class PlaceRepository implements Repository<Place> { @Override public void add (final Place item) {

}

REALM - ADDING A RECORD

public class PlaceRepository implements Repository<Place> { @Override public void add (final Place item) { Realm realm = Realm.getDefaultInstance(); realm.executeTransaction( (realm) -> { realm.copyToRealmOrUpdate( item ); } ); realm.close(); }

REALM - QUERY RESULT

private static final String PLACE_ID = "id";

@Overridepublic Place toResult (Realm realm){ return realm.where( Place.class )

}

REALM - QUERY RESULT

private static final String PLACE_ID = "id";

@Overridepublic Place toResult (Realm realm){ return realm.where( Place.class ) .equalTo( PLACE_ID, placeId ) .findFirst();}

SEPARATE UI AND NETWORK

EVENTBUS

From: http://greenrobot.org/eventbus

… WHEN YOU HAVE LOTS OF OBJECTS THAT ARE POTENTIAL EVENT SOURCES.

Martin Fowler

EVENTBUS

EVENTBUS - SETUP

@Provides @Singletonpublic Bus provideBus (){ return new Bus( EventBus.builder() .logNoSubscriberMessages( BuildConfig.DEBUG ) .throwSubscriberException( false ) .build() );}

EVENTBUS - REGISTER

public class LeadsMapPresenter { private final Bus bus; private LeadsMapView leadsMapView; @Inject LeadsMapPresenter (Bus bus) { this.bus = bus; } …

EVENTBUS - REGISTER

public class LeadsMapPresenter { public void attachView (LeadsMapView view) { this.leadsMapView = view; bus.register( this ); }

EVENTBUS - REGISTER

public class LeadsMapPresenter { public void attachView (LeadsMapView view) { this.leadsMapView = view; bus.register( this ); }

public void detachView () { this.leadsMapView = null; bus.unregister( this ); }

TAKE AN ACTION

PRESENTER

SERVICE

ACTIVITY

EVENT BUS

DATABASEREPOSITORY

JOB NETWORK

EVENTBUS - POST EVENT

api.submitPlace( place ).enqueue( new Callback<Place>(){

…JOB

EVENTBUS - POST EVENT

api.submitPlace( place ).enqueue( new Callback<Place>() { @Override public void onResponse (Call<Place> call, Response<Place> response) { if ( response.isSuccessful() ) { }

…JOB

EVENTBUS - POST EVENT

api.submitPlace( place ).enqueue( new Callback<Place>() { @Override public void onResponse (Call<Place> call, Response<Place> response) { if ( response.isSuccessful() ) { Place updatedPlace = response.body(); bus.post( new PlaceSubmissionSuccessEvent( updatedPlace ) ); }

…JOB

EVENTBUS - RETRIEVE EVENT

public class LeadsMapPresenter { @Subscribe public void onPlaceSubmissionSuccess (PlaceSubmissionSuccessEvent event) { leadsMapView.displaySuccessMessage( PLACE_SUCCESS ); }

PRESENTER

QUEUE REQUESTS

ANDROID JOB

ANDROID JOB

‣Alarm Manager

‣Job Scheduler

‣GCM Network Manager

ANDROID JOB

JOB MANAGER

JOB CREATOR

ANDROID JOB

JOB MANAGERPROVIDER

JOB

JOB CREATOR

PROVIDER

JOB

PROVIDER

JOB

ANDROID JOB

JOB MANAGERPROVIDER

JOB

JOB CREATOR

PROVIDER

JOB

PROVIDER

JOB

JOB REQUEST

ANDROID JOB

JOB MANAGERPROVIDER

JOB

JOB CREATOR

PROVIDER

JOB

PROVIDER

JOB

JOB REQUEST

JOB

ANDROID JOB - CREATOR

@Singletonpublic class ConfettiJobCreator implements JobCreator{ @Inject Map<String, Provider<Job>> jobs; @Override public Job create (String tag) {

}}

ANDROID JOB - CREATOR

@Singletonpublic class ConfettiJobCreator implements JobCreator { @Inject Map<String, Provider<Job>> jobs; @Override public Job create (String tag) { Provider<Job> jobProvider = jobs.get( tag ); return jobProvider.get(); }}

ANDROID JOB - JOB EXECUTION

@Overrideprotected Result onRunJob (final Params params){

} JOB

ANDROID JOB - JOB EXECUTION

@Overrideprotected Result onRunJob (final Params params) { PersistableBundleCompat extras = params.getExtras(); String placeId = extras.getString( PARAM_PLACE_ID );

} JOB

ANDROID JOB - JOB EXECUTION

@Overrideprotected Result onRunJob (final Params params) { PersistableBundleCompat extras = params.getExtras(); String placeId = extras.getString( PARAM_PLACE_ID ); if ( submitRequest( placeId ) ) { return Result.SUCCESS; } return Result.FAILURE;} JOB

ANDROID JOB

JOB MANAGERPROVIDER

JOB

JOB CREATOR

JOB REQUEST

JOB

ANDROID JOB - SCHEDULING

public static JobRequest buildJobRequest (String placeId) { PersistableBundleCompat extras = new PersistableBundleCompat(); extras.putString( PARAM_PLACE_ID, placeId );

}

ANDROID JOB - SCHEDULING

public static JobRequest buildJobRequest (String placeId) { PersistableBundleCompat extras = new PersistableBundleCompat(); extras.putString( PARAM_PLACE_ID, placeId ); return new JobRequest.Builder( SendPlaceRequestJob.JOB_TAG )

}

ANDROID JOB - SCHEDULING

public static JobRequest buildJobRequest (String placeId) { PersistableBundleCompat extras = new PersistableBundleCompat(); extras.putString( PARAM_PLACE_ID, placeId ); return new JobRequest.Builder( SendPlaceRequestJob.JOB_TAG ) .setExecutionWindow( 10_000L, 20_000L ) .setRequiredNetworkType( JobRequest.NetworkType.CONNECTED )

}

ANDROID JOB - SCHEDULING

public static JobRequest buildJobRequest (String placeId) { PersistableBundleCompat extras = new PersistableBundleCompat(); extras.putString( PARAM_PLACE_ID, placeId ); return new JobRequest.Builder( SendPlaceRequestJob.JOB_TAG ) .setExecutionWindow( 10_000L, 20_000L ) .setRequiredNetworkType( JobRequest.NetworkType.CONNECTED ) .setExtras( extras ) }

ANDROID JOB - SCHEDULING

public static JobRequest buildJobRequest (String placeId) { PersistableBundleCompat extras = new PersistableBundleCompat(); extras.putString( PARAM_PLACE_ID, placeId ); return new JobRequest.Builder( SendPlaceRequestJob.JOB_TAG ) .setExecutionWindow( 10_000L, 20_000L ) .setRequiredNetworkType( JobRequest.NetworkType.CONNECTED ) .setExtras( extras ) .setRequirementsEnforced( true ) .build(); }

ANDROID JOB - SCHEDULING

jobManager.schedule( );

ANDROID JOB - SCHEDULING

jobManager.schedule( SendPlaceRequestJob.buildJobRequest( id ) );

JOB REQUEST

JOB QUEUE

WHAT WE USE

‣Realm ‣EventBus ‣Android Job

CHALLENGES

WHAT’S NEXT?

‣RxJava ‣Mapbox ‣Push Notifications

THANKS

@brwngrldev

+AnnyceDavis

www.adavis.info

top related