Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Android Loader and Enroscar Async

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.

Android Loader and Enroscar Async

Assuming the audience is already familiar with Loader class, we'll discuss problems that occur while using it, try to understand their reasons and see how they can be solved with Enroscar Async. And maybe we'll find out that Loader can be a rather powerful tool.

Avatar for Roman Mazur

Roman Mazur

October 25, 2014
Tweet

More Decks by Roman Mazur

Other Decks in Programming

Transcript

  1. #dfua getLoaderManager().initLoader(MAGIC_ID, null, new LoaderManager.LoaderCallbacks<Cursor>() { @Override public Loader<Cursor> onCreateLoader(int

    id, Bundle args) { CursorLoader loader = new CursorLoader(getApplicationContext()); loader.setUri(SOME_URI); return loader; } // TODO }); create a Loader that performs your operation
  2. #dfua getLoaderManager().initLoader(MAGIC_ID, null, new LoaderManager.LoaderCallbacks<Cursor>() { @Override public Loader<Cursor> onCreateLoader(int

    id, Bundle args) { CursorLoader loader = new CursorLoader(getApplicationContext()); loader.setUri(SOME_URI); return loader; } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { // cursor loaded } // TODO }); implement an action to be 
 taken when data is loaded
  3. #dfua getLoaderManager().initLoader(MAGIC_ID, null, new LoaderManager.LoaderCallbacks<Cursor>() { @Override public Loader<Cursor> onCreateLoader(int

    id, Bundle args) { CursorLoader loader = new CursorLoader(getApplicationContext()); loader.setUri(SOME_URI); return loader; } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { // cursor loaded } @Override public void onLoaderReset(Loader<Cursor> loader) { // does anybody know what to do here? } }); get rid of any references 
 to the data previously loaded
  4. #dfua @Override protected void onCreate(Bundle savedState) { super.onCreate(savedState); getLoaderManager().initLoader(MAGIC_ID, null,

    new LoaderManager.LoaderCallbacks<Cursor>() { @Override public Loader<Cursor> onCreateLoader(int id, Bundle args) { CursorLoader loader = new CursorLoader(getApplicationContext()); loader.setUri(SOME_URI); return loader; } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { // cursor loaded } @Override public void onLoaderReset(Loader<Cursor> loader) { // get rid of data } }); } the simplest case:
 init in 
 Activity.onCreate, Fragment.onCreate, Fragment.onActivityCreated
  5. #dfua public class Loader<D> { public void deliverResult(D data) {

    } protected void onStartLoading() { } protected boolean onCancelLoad() { } protected void onForceLoad() { } protected void onStopLoading() { } protected void onAbandon() { } protected void onReset() { } } What you have to think about implementing a custom loader
  6. #dfua @Override protected void onCreate(Bundle savedState) { super.onCreate(savedState); findViewById(android.R.id.button1).setOnClickListener(new View.OnClickListener()

    { @Override public void onClick(View v) { getLoaderManager().initLoader(MAGIC_ID, null, callback); } }); } start loading when button is tapped
  7. #dfua @Override protected void onCreate(Bundle savedState) { super.onCreate(savedState); if (isLoadingInProgress(savedState))

    { getLoaderManager().initLoader(MAGIC_ID, null, callback); } findViewById(android.R.id.button1).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { loading = true; getLoaderManager().initLoader(MAGIC_ID, null, callback); } }); } 1 save your state;
 don’t forget about 
 onSaveInstanceState 2 attach a callback
 if bundle has your
 flag set
  8. #dfua @Override protected void onCreate(Bundle savedState) { super.onCreate(savedState); if (isLoadingInProgress(savedState))

    { getLoaderManager().initLoader(MAGIC_ID, null, callback); } findViewById(android.R.id.button1).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { loading = true; getLoaderManager().restartLoader(MAGIC_ID, null, callback); } }); } e.g. if you want to submit an order ensures your operation will be performed
  9. #dfua public class Loader<D> { public void deliverResult(D data) {

    } protected void onStartLoading() { } protected boolean onCancelLoad() { } protected void onForceLoad() { } protected void onStopLoading() { } protected void onAbandon() { } protected void onReset() { } } Loader abstraction Serves for solving one main problem:
 control your async operation execution. Control is done by LoaderManager through
 binding to UI lifecycle. Delivered data is retained.
  10. #dfua Define Operations class TwitterOperations { final TwitterApi api; @Load

    Async<List<Tweet>> loadTweets(String query) { return Tools.async(new Callable<List<Tweet>>() { @Override public List<Tweet> call() { return api.search(query); } }); } } @Send Async<Boolean> postTweet(String message) { return Tools.async(new Callable<Boolean>() { @Override public Boolean call() { return api.post(message); } }); }
  11. #dfua Use Generated Operator // somewhere in your Activity TwitterOperationsOperator

    operator = TwitterOperationsOperator.build() .operations(new TwitterOperations(api)) .loaderManager(getSupportLoaderManager()) .context(this) .get(); // trigger operator.loadTweets(“#dfua”); operator.postTweet(“@roman_mazur talks about Enroscar Async”);
  12. #dfua Reactive Extensions operator .when().loadTweetsIsFinished() .subscribe(action); operator. .when().postTweetIsFinished() .map(res ->

    res ? “Your tweet is posted!” : “Too big message!”) .subscribe(displayUserMessage);