Android Session 4: Data Management

Objectives

  • Store data using SharedPreferences
  • Build and interact with databases in Android

Shared preferences

The Android framework offers an API for storing key-value pairs accessible only to your app. Usually they are used for persisting settings (user preferences).

The key-value pairs are stored in files. You can use one or several files, depending on your app's design. In order to access them, you need to obtain a SharedPreference object using methods provided by the Context class. These files can also be specific to an activity.

// In this example we are in MainActivity
 
SharedPreferences sharedPref = this.getPreferences(MODE_PRIVATE); 
// or 
sharedPref = this.getSharedPreferences("mysettings", Context.MODE_PRIVATE);
// or
sharedPref = PreferenceManager.getDefaultSharedPreferences(context);
  • Context.getSharedPreferences is used when we have multiple shared preferences files and we want to obtain the given name
  • Context.getPreferences if we only use one shared preference file for that activity. We can only provide the MODE_PRIVATE since the other options have been deprecated from API Level 17 for security reasons. They granted read and write access to these files to other apps.
  • PreferenceManager.getDeaultSharedPreferences provides the default file for storing the key-value pairs for the entire app.
SharedPreferences.Editor editor = getPreferences(MODE_PRIVATE).edit();
editor.putString("my_key", "my_value");
editor.putBoolean("my_bool", true);
editor.putInt("my_int", 0);
 
// Must save them!
editor.apply();  //async write to disc
// or use
editor.commit(); //immediately writes to disc, avoid using it from UI thread.
 
//obtain values:
sharedPref.getString("my-key", "default-value");

Threading in Android

When an application is launched, the system creates a process for it (or more, if it declares services in separate processes) and a main thread (UI thread). As discussed in the previous labs, any code you write in your components (unless they are Intent Services) is run on the main thread. But an app might need to perform processing in worker threads, for example, in case of networking or database operations. If we block the UI thread while performing computational intensive code or waiting for certain events, the system will display an ANR (Application Not Responding) dialog.

For working with threads and scheduling tasks we can leverage language-specific APIs for threading, Android specific components or many third-party libraries.

:!: Calling methods from the Android UI API must be done on the UI thread. For example, if you want to show a toast from a worker-thread, use runOnUiThread.

Handlers and Runnables

In Android we can create new threads by creating objects of type Thread and Runnable, as we do in Java programming. Since we also need communication with the Android's UI components, the SDK offers a specific type of objects: Handler.

Runnables

In the following example we load data from db on a different thread:

                Runnable runnable = new Runnable() {
                    @Override
                    public void run() {
                        loadData();
                    }
                };
                Thread thread = new Thread(runnable);
                thread.start();
            }
 

What happens if we want to show a Toast from the run() method?

public void run() {
    List<Records> records = loadData();
    Toast.makeText(MainActivity.this, records.get(0).getName(), Toast.LENGTH_SHORT).show();
}

We have to use runOnUIThread

public void run() {
    List<Records> records = loadData();
    runOnUiThread(new Runnable() {
 
                        @Override
                        public void run() {
                            Toast.makeText(MainActivity.this, records.get(0).getName(), Toast.LENGTH_SHORT).show();
                        }
                    });
 
}

Schedule tasks on a Handler

Using the Handler's postDelayed method we can schedule runnables to be executed in the future, on that thread. In this way we can also implement timers in Android.

In the following example we save data to db every [interval] time:

        HandlerThread thread = new HandlerThread("I handle things");
        thread.start();
        Handler writeHandler = new Handler(thread.getLooper());
 
        writeHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                try {
                    saveDataToDB();
                } finally {
                    writeHandler.postDelayed(this, interval);
                }
            }
        }, interval);

TASKS

  1. Setup SharedPreferences (Follow TODO 1)
    1. Get sharedPreferences
    2. Get co2Threshold and vocThreshold from the corresponding EditText and save the values to sharedPreferences
    3. Get co2Threshold and vocThreshold from sharedPreferences and set the values to the corresponding EditText
  2. Setup database (Follow TODO 2)Room library documentation
    1. Setup Entity
    2. Setup Dao
    3. Setup Database
  3. Save records into db every X seconds using HandlerThread (Follow TODO 3)
  4. Show records in the HistoryActivity (Follow TODO 4)
    1. Load data on a different thread (not on the UI thread)
    2. Set the list of records to the adapter on the UI thread

Files

fss/sessions/session4-android.txt ยท Last modified: 2019/07/11 18:36 by beniamin.dobre
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0