This presentation cover following topics:
1. Mock up the main screens and navigation flow of the application
2. Describe interactions between UI, background task, and data
persistence
3. Construct a layout using XML or Java code
4. Create an Activity that displays a layout resource
5. Fetch local data from disk using a Loader on a background t
thread
6. Propagate data changes through a Loader to the UI
2. Mock up the main screens and navigation flow of the application
Describe interactions between UI, background task, and data
persistence
Construct a layout using XML or Java code
Create an Activity that displays a layout resource
Fetch local data from disk using a Loader on a background
thread
Propagate data changes through a Loader to the UI
Agenda
3. After attending this session you are expected to be able to
Have a clear idea about last slide mentioned topics
Objectives
4. Typically mid to high fidelity, mockups reflect the design choices for color schemes,
layouts, typography, iconography, the visuals of navigation, and the overall
atmosphere of the product.
In addition to setting aside time to answer the important visual questions, mockups
have several other benefits:
Intuitive to stakeholders Thanks to their higher fidelity, mockups require less
context than lo-fi documents like wireframes. Stakeholders can more easily see
the final product.
Realistic perspective Its one thing to have all your visual decisions made, but
its another to see them all working together in a way close to the real thing.
Mockups can help reveal problems that arent so apparent on paper (for
example, color clashes, or smaller type crimes going unnoticed).
Early revisions Its easier to make revisions in a mockup than in the later
coding stages (as long as the mockup itself isnt coded).
What is a Mockup?
5. In the design process, mockups come at the end of the lo-fi phase
and the beginning of the hi-fi phase.
keep these tips in mind:
Narrow your concepts The reason mockups come after
wireframing is that you first need to eliminate other big picture
options. If youre unclear about the navigation structure, dont
make mockups for both versions decide one first.
Examine competitor products Before deciding your own visuals,
take a look at what your competitors are doing. Dont copy them,
though look for areas that you can improve upon, or UI patterns
that users would want on all products of this type. A quick heuristic
review can help quantify your observations.
What is a Mockup?
6. We can divide mockups tools into three different types graphic design software,
mockup apps, and coded mockups each with their own advantages and
disadvantages.
Graphic Design Software: Because of the emphasis on visuals, some designers
prefer to build mockups in the graphic design software theyre most familiar
with. Software like Photoshop is built to create pixel-perfect images.
Mockup Apps: Tools created specifically for digital product design, like our
app UXPin or Sketch, build upon existing experience with classic tools like
Photoshop.
Code: Coded mockups are an efficient way to save time and resources provided
youre technically confident. Theres also no surprises later on if a visual
element cannot be created in code, it is simply fixed right then and there.
3 Types of Mockups
7. What is it?
Background processing in Android refers to the execution of tasks in
different threads than the Main Thread, also known as UI Thread,
where views are inflated and where the user interacts with our app.
Why background processing?
To avoid UI blockages by I/O events and prevent the
famous Application Not Responding dialog. A freezing app means
bad UX.
Some operations are not allowed to run in the Main Thread, such
as HTTP calls.
To improve performance.
So, here are some of the best known alternatives,
Interactions between UI, background task
8. Thread & Handler
Create a Thread with a Runnable and do the heavy operation, when the heavy
operation ends call the handler created earlier on the UI Thread.
By default the views have a handler, so you can do View.post(). The Handler is
the means of communication between the heavy task running on the created
thread and the UI Thread.
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
final String result = performBlockingTask();
runOnUiThread(new Runnable() {
@Override
public void run() {
mTextView.setText(result);
}
});
});
thread.start();
Activity.runOnUiThread() simply posts to a main thread Handler internally.
Interactions between UI, background task
9. Other way,
final Handler handler = new Handler();
final Runnable uiRunnable = new Runnable() {
@Override
public void run() {
mTextView.setText(mResult);
}
};
Thread thread = new Thread(new Runnable() {
public void run() {
mResult = performBlockingTask();
handler.post(uiRunnable);
}
});
thread.start();
Interactions between UI, background task
10. Overview of Data Storing :
App data is private to the application
Have several mechanism like:
State Storage: Ram memory!
Mechanism for saving Activitys state temporarily
Preferences
Lightweight mechanism to store and retrieve key-value pairs
Files
Open and save 鍖les on the device or removable storage
SQLite databases
Databases
Content provider is used to give the data to other apps
Data persistence
11. Activity State: Using RAM:
Activitys state information can be lost, if its closed
When activity is no longer on the screen and its
closed because of freeing memory
When screen rota1on is changed, the activity is destroyed and opened again
How to store and read state information
Store state:
onSaveInstanceState(Bundle)
Read state
onRestoreInstanceState(Bundle)
This will store data only temporarily: for app life1me!
Data will be held in memory until the app is closed!
Data persistence
12. Store:
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
String text = tv.getText().toString();
savedInstanceState.putString("someKey", text);
super.onSaveInstanceState(savedInstanceState);
}
Load:
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
if (savedInstanceState != null) {
String strValue = savedInstanceState.getString("someKey");
if (strValue != null) {
textfield.setText(strValue);
}
}
}
Data persistence
13. public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Button myButton = new Button(this);
myButton.setText("Press me");
myButton.setBackgroundColor(Color.YELLOW);
RelativeLayout myLayout = new RelativeLayout(this);
myLayout.setBackgroundColor(Color.BLUE);
EditText myEditText = new EditText(this);
myButton.setId(1);
myEditText.setId(2);
Layout using java code
15. The ConstraintLayout is a powerful new class, imagine a RelativeLayout on steroids
- yea, thats the ConstraintLayout. It allows us to lay out child views using
constraints to define position based relationships between different views found
in our layout.
The aim of the ConstraintLayout is to help reduce the number of nested views,
which will improve the performance of our layout files.
For example, the attributes of a relative layout allow us to position a view using:
layout_toRightOf
layout_toLeftOf
layout_toTopOf
layout_toBottomOf
ConstraintLayout
16. However, the ConstraintLayout features several more attributes:
layout_constraintTop_toTopOfAlign the top of the desired view to the top of another.
layout_constraintTop_toBottomOfAlign the top of the desired view to the bottom of another.
layout_constraintBottom_toTopOfAlign the bottom of the desired view to the top of another.
layout_constraintBottom_toBottomOfAlign the bottom of the desired view to the bottom of
another.
layout_constraintLeft_toTopOfAlign the left of the desired view to the top of another.
layout_constraintLeft_toBottomOfAlign the left of the desired view to the bottom of another.
layout_constraintLeft_toLeftOfAlign the left of the desired view to the left of another.
layout_constraintLeft_toRightOfAlign the left of the desired view to the right of another.
layout_constraintRight_toTopOfAlign the right of the desired view to the top of another.
layout_constraintRight_toBottomOfAlign the right of the desired view to the bottom of another.
layout_constraintRight_toLeftOfAlign the right of the desired view to the left of another.
layout_constraintRight_toRightOfAlign the right of the desired view to the right of another.
If desired, attributes supporting start and end are also available in place of left and right alignment.
ConstraintLayout
17. By default, device configuration changes such as rotating your screen involve
restarting your whole Activity (one of the many reasons it is so critical not to keep a
reference to your Activity or any Views). The best part about Loaders is
that Loaders survive configuration changes.
But even better: Loaders dont stay around forever. Theyll be automatically
cleaned up when the requesting Activity or Fragment is permanently destroyed.
That means no lingering, unnecessary loads.
Loaders
18. How to Use Loaders in Android
Class Usage
LoaderManager
Manages your Loaders for you. Responsible
for dealing with the Activity or Fragment
lifecycle
LoaderManager.LoaderCallbacks A callback interface you must implement
Loader The base class for all Loaders
AsyncTaskLoader
An implementation that uses an AsyncTask to
do its work
CursorLoader
A subclass of AsyncTaskLoader for accessing
ContentProvider data
The classes and interfaces of the Loader API :
19. You do not instantiate the LoaderManager yourself. Instead you simply
call getLoaderManager() from within your activity or your fragment to get hold of it.
Most often you are only interested in two methods of the manager:
initLoader() and
restartLoader()
initLoader()
The initLoader() method adds a Loader to the LoaderManager:
getLoaderManager().initLoader(LIST_ID, null, this);
restartLoader()
* You reset your Loader by using the restartLoader() method. Of course you have to use the
same ID you used for initializing.
getLoaderManager().restartLoader(LIST_ID, null, this);
LoaderManager
20. The interface LoaderCallbacks defines methods you must implement to create your Loader,
to deal with the results and to clean up resources.
Since the interface is parameterized you must specify the type of data your Loader holds.
Most often the type will be Cursor:
public class YourFragment extends Fragment implements LoaderCallbacks<Cursor> { //... }
The methods you have to implement are:
onCreateLoader(),
onLoadFinished() and
onLoadReset()
LoaderManager.LoaderCallbacks
21. onCreateLoader():
The LoaderManager calls this method when you call initLoader() for the first time. As
mentioned, the manager only calls this method if no loader for the given ID exists.
A typical example creating a CursorLoader looks like this:
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
CursorLoader loader = new CursorLoader(
this.getActivity(),
SOME_CONTENT_URI,
projection,
selection,
selectionArgs,
sortOrder);
return loader;
}
LoaderManager.LoaderCallbacks
22. onLoadFinished():
This method is the most interesting one. Here you update the UI based on the
results of your query.
This is how it looks in the sample project:
public void onLoadFinished( Loader<Cursor> loader, Cursor cursor) {
if (cursor != null && cursor.getCount() > 0) {
cursor.moveToFirst();
int idIndex = cursor.getColumnIndex(LentItems._ID);
int nameIndex = cursor.getColumnIndex(LentItems.NAME);
int borrowerIndex =
cursor.getColumnIndex(LentItems.BORROWER);
this.itemId = cursor.getLong(idIndex);
String name = cursor.getString(nameIndex);
String borrower = cursor.getString(borrowerIndex);
((EditText)findViewById(R.id.name)). setText(name);
((EditText)findViewById(R.id.person)). setText(borrower); } }
LoaderManager.LoaderCallbacks
23. onLoadReset():
This method allows you to release any resources you hold, so that
the Loader can free them. You can set any references to the cursor
object you hold to null.
But do not close the cursor - the Loader does this for you.
CursorLoader is default Loader if you want your own load then can
create a Custom Loader using AsyncTaskLoader
LoaderManager.LoaderCallbacks
24. public static class JsonAsyncTaskLoader extends
AsyncTaskLoader<List<String>> {
private List<String> mData;
public JsonAsyncTaskLoader(Context context) {
super(context);
}
@Override
protected void onStartLoading() {
if (mData != null) {
// Use cached data
deliverResult(mData);
}
AsyncTaskLoader
25. if (mFileObserver == null) {
String path = new File(
getContext().getFilesDir(), "downloaded.json").getPath();
mFileObserver = new FileObserver(path) {
@Override
public void onEvent(int event, String path) {
// Notify the loader to reload the data
onContentChanged();
// If the loader is started, this will kick off
// loadInBackground() immediately. Otherwise,
// the fact that something changed will be cached
// and can be later retrieved via takeContentChanged()
}
};mFileObserver.startWatching();
} if (takeContentChanged() || mData == null) {
// Something has changed or we have no data,
// so kick off loading it
forceLoad();}}
AsyncTaskLoader
26. @Override
public List<String> loadInBackground() {
// This is on a background thread
// Good to know: the Context returned by getContext()
// is the application context
File jsonFile = new File(
getContext().getFilesDir(), "downloaded.json");
List<String> data = new ArrayList<>();
// Parse the JSON using the library of your choice
// Check isLoadInBackgroundCanceled() to cancel out early
return data;
}
AsyncTaskLoader
27. @Override
public void deliverResult(List<String> data) {
// Well save the data for later retrieval
mData = data;
// We can do any pre-processing we want here
// Just remember this is on the UI thread so nothing lengthy!
super.deliverResult(data);
}
}
AsyncTaskLoader
28. You shouldn't use Loaders if you need the background tasks to
complete.
Android destroys Loaders together with the Activities/Fragments
they belong to.
If you want to do some tasks, that have to run until completion, do
not use Loaders. You should use services for this kind of stuff
instead.
Keep in mind that Loaders are special components to help you
create responsive UIs and to asynchronously load data that this UI
component needs
That's the reason why Loaders are tied to the lifecycle of their
creating components. Do not try to abuse them for anything else!
When not to use Loaders