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

[Roma Mazur] Android Loader, problems and solutions

[Roma Mazur] Android Loader, problems and solutions

Presentation from GDG DevFest - the biggest Google related event in Ukraine. October 24-25, Lviv. Learn more at http://devfest.gdg.org.ua/

Google Developers Group Lviv

October 25, 2014
Tweet

More Decks by Google Developers Group Lviv

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);