6. Where would you load your data?
onCreate? onStart? onResume?
What happens when the phone rotates?
how to get fresh data as soon as it’s ready?
How to get the data? AsyncTask?
7. a Loader is an Android Specific pattern,
Designed so that async data retrieval is…
Easy to implement PROPERLY.
So, What are Loaders?
8. Available since Android 3.0 (Honeycomb, API level 11 and support libs),
to Activities and Fragments,
Also use that Observer Pattern we’ve seen
last week,
Are cached between configuration changes.
So, What are Loaders?
9. - Recommended way to load data
BUT NOT ONLY!
- Works best with Cursors,
BUT NOT ONLY!
Why to use loaders?
10. API Breakdown
Loader Abstract class that performs async
loading of data.
It can monitor its data-source while
active.
11. API Breakdown
More commonly, we’ll see these:
a loader implementation that provies an
AsyncTask to do to loading,
an AsyncTaskLoader that is used to query
data from a ContentProvider and returns a
Cursor.
Loader
Async Task
Loader
Cursor
Loader
12. API Breakdown
This is where the magic is:
LoaderManager helps an activity
manage long-running operations
with the activity lifecylce.
Loader
Async Task
Loader
Cursor
Loader
LoaderManager
13. API Breakdown
The callbacks are used to abstract
the specific loader from the loader
manager.
3 Methods: onCreateLoader (int id, Bundle args),
onLoadFinished(Loader<D>
loader, D data),
onLoaderReset(Loader<D>
loader)
Loader
Async Task
Loader
Cursor
Loader
LoaderManager
LoaderCallbacks <D>
14. How to use loaders?
Step 1: Create a unique ID for your loader.
Step 2: LoaderManager.Loadercallbacks<D>
Step 3: init the loader with the id.
15. How to use loaders? - Step 1
Have a constant int, unique for the loader in
the activity.
private static final int LOADER_ID = 31415;
16. How to use loaders? - Step 2
Implement the
LoaderManager.LoaderCallbacks<D>.
Our demo will use a Long, so:
implements
LoaderManager.LoaderCallbacks<Long>
17. How to use loaders? - Step 3
in the Activity’s onCreate,
or in the Fragment’s onActivityCreate,
init the loader as such:
getLoaderManager().initLoader( LOADER_ID,
Parameter,
LoaderCallback);
18. in the Activity’s onCreate,
or in the Fragment’s onActivityCreate,
init the loader as such:
getLoaderManager().initLoader( LOADER_ID,
Parameter,
LoaderCallback);
How to use loaders?
If the activity has multiple loaders,
each should have its own unique ID.
This enables the LoaderManager to re-
use the Loader.
19. How to use loaders?
in the Activity’s onCreate,
or in the Fragment’s onActivityCreate,
init the loader as such:
getLoaderManager().initLoader( LOADER_ID,
Parameter,
LoaderCallback);
The parameter is passed to the loader.
20. How to use loaders?
in the Activity’s onCreate,
or in the Fragment’s onActivityCreate,
init the loader as such:
getLoaderManager().initLoader( LOADER_ID,
Parameter,
LoaderCallback);
the manager uses this instance of
LoaderManager.LoaderCallbacks to
manage the loader’s lifecycle.
21. Loader Initialization - 1
when LM.initLoader is called, if the loader
does not exist, the callback’s onCreateLoader
method is called.
That’s where you create the loader.
22. Loader Initialization - 2
when LM.initLoader is called, if the loader
does exist, the callback’s onCreateLoader
method is not called - but the new Listener
replaces the old listener.
That’s how you get away with Configuration
Changes.
23. Demo
We’ll see 2 activities.
in onCreate, one starts a 5 second async task,
and the other starts a 5 second loader.
We’ll rotate the device after ~2 seconds in each.
Check out the LogCat too - to see just the 1 creation.
25. Story time: AsyncTaskLoader - Fail
How I thought it would look:
public class DemoLoader extends AsyncTaskLoader<Long> {
public DemoLoader(Context context) {
super(context);
}
@Override
public Long loadInBackground() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {}
return new Long(SystemClock.upTimeMillies());
}
}
This code moved to
“TheBrain”.
26. Story time: AsyncTaskLoader - Fail
However, it was not that simple -
the DemoLoader class is about 100 lines long
(and the “real” data loading is a one-liner).
Why?
27. Story time: AsyncTaskLoader - Epif.
I did not consider the responsibilities of the
loader:
Getting
Data
Keeping
Data
Observing
Data source
Lifecycle
28. Quiz Time
Is it OK to have 2 loaders with the same ID?
→ Yes, if they’re not on the same Activity.
Can an activity have multiple loaders?
→ Yes, but they have to have a different ID.
What types can a loader return?
→ Everything, as long as it’s an Object.
29. Quiz Time
How does this mechanism handles configuration changes?
→ The loader manager keeps the loader, but replaces
the
callbacks object - so the most recent activity gets
notified when the loader is done.
What happens when the data is changed?
→ The Loader is notified (by the Observer) and pushes
new information to the onLoaderFinished method.
30. Quiz Time
When to init the loader? (to call LoaderManager.init)
→ In onCreate(), or onActivityCreated()
Yeah, but when exactly to init the loader?
→ TRICKY…
→ If the loader already has an answer for you, then
the
onLoaderFinished callback will fire - so you should
init the loader after you’re ready for this callback.
31. Quiz Time
What to do when a loader needs to change?
→ Call RestartLoader. The loader will get an
onReset(),
and the activity will get an onLoaderReset() call.
You should release everything there, and let a new
loader do the entire cycle for you.
32. How to restart a loader
The loader manager has a method for that:
getLoaderManager().restartLoader( LOADER_ID,
Parameter,
LoaderCallback);
34. So, What’s a cursor loader?
a CursorLoader is an AsyncTaskLoader,
designed to handle Cursors -
Which is what our ContentProvider provides,
with its SQLite database and the
SQLiteOpenHelper
35. How to use a Cursor Loader
1)Create a Loader ID constant. Simple int.
1)Fill-in Loader callbacks - for Cursor
1)Init a loader with LoaderManager
36. How to use a Cursor Loader - Step 1
private static final int
WORDS_LOADER_ID=1337;
private WordsAdapter adapter;
// initialize in onCreate()
37. How to use a Cursor Loader - Step 2
Implement the loader callbacks, keep the
adapter.
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
adapter.swapCursor(data);
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
adapter.swapCursor(null);
}
38. How to use a Cursor Loader - Step 3
Step 3 - Initialize as usual
getLoaderManager()
.initLoader(WORDS_LOADER_ID,
null,
this);
39. Cursor Loader - What’s the benifit?
Super easy to implement ()יחסית
All the benefits of loaders -
Minimum lines of code.
40. Implement the Adapter
See code,
public View newView(Context context, Cursor cursor, ViewGroup parent)
public void bindView(View view, Context context, Cursor cursor)
41. Let’s go over the agenda
In our previous sessions, We talked about:
Handlers and AsyncTasks (2)
The activity lifecycle (4a)
Databases and Cursors (4b)
42. Let’s go over the agenda
Loaders are object that abstract data retrieval
and observation, and simplify its
implementation regarding:
Activity Lifecycle
Data Observation
Cache
And is implemented in 3 simple steps.
43. Let’s go over the agenda
CursorLoaders are loaders that are specific
to accessing ContentProviders, and make the
best-practices implementation really easy.
47. Thank you,
We’ll stick around for any questions you might
have, or any issues you’ve stumbled upon
when implementing Sunhine or your app.
Drive home safely.
48. Thank you,
We’ll stick around for any questions you might
have, or any issues you’ve stumbled upon
when implementing Sunhine or your app.
Drive home safely.