This shows you the differences between two versions of the page.
fss:sessions:session4-android [2019/07/11 15:59] beniamin.dobre created |
fss:sessions:session4-android [2019/07/11 18:36] (current) beniamin.dobre [Handlers and Runnables] |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Android Session 3: Bluetooth Low Energy Communication ====== | + | ====== Android Session 4: Data Management ====== |
- | {{:fss:sessions:android_bluetooth_low_energy_communication.pdf|Slides}} | + | {{:fss:sessions:android__data_management.pdf|Slides}} |
===== Objectives ===== | ===== Objectives ===== | ||
* Store data using SharedPreferences | * Store data using SharedPreferences | ||
* Build and interact with databases in Android | * 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. | ||
+ | <code Java> | ||
+ | // 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); | ||
+ | </code> | ||
+ | |||
+ | |||
+ | *[[https://developer.android.com/reference/android/content/Context.html#getSharedPreferences(java.lang.String,%20int)|Context.getSharedPreferences]] is used when we have multiple shared preferences files and we want to obtain the given name | ||
+ | * [[https://developer.android.com/reference/android/app/Activity.html#getPreferences(int)|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. | ||
+ | * [[https://developer.android.com/reference/android/preference/PreferenceManager.html#getDefaultSharedPreferences(android.content.Context)|PreferenceManager.getDeaultSharedPreferences]] provides the default file for storing the key-value pairs for the entire app. | ||
+ | |||
+ | <code Java> | ||
+ | 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"); | ||
+ | </code> | ||
==== Threading in Android ==== | ==== Threading in Android ==== | ||
Line 14: | Line 48: | ||
:!: 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 [[https://developer.android.com/reference/android/app/Activity#runOnUiThread(java.lang.Runnable)|runOnUiThread]]. | :!: 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 [[https://developer.android.com/reference/android/app/Activity#runOnUiThread(java.lang.Runnable)|runOnUiThread]]. | ||
- | ==== TASK ==== | + | ==== 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: | ||
+ | |||
+ | <code java> | ||
+ | Runnable runnable = new Runnable() { | ||
+ | @Override | ||
+ | public void run() { | ||
+ | loadData(); | ||
+ | } | ||
+ | }; | ||
+ | Thread thread = new Thread(runnable); | ||
+ | thread.start(); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | What happens if we want to show a Toast from the run() method? | ||
+ | |||
+ | <code java> | ||
+ | public void run() { | ||
+ | List<Records> records = loadData(); | ||
+ | Toast.makeText(MainActivity.this, records.get(0).getName(), Toast.LENGTH_SHORT).show(); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | We have to use runOnUIThread | ||
+ | <code java> | ||
+ | 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(); | ||
+ | } | ||
+ | }); | ||
+ | |||
+ | } | ||
+ | </code> | ||
+ | |||
+ | === Schedule tasks on a Handler === | ||
+ | Using the Handler's [[https://developer.android.com/reference/android/os/Handler.html#postDelayed(java.lang.Runnable,%20java.lang.Object,%20long)|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: | ||
+ | <code java> | ||
+ | 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); | ||
+ | </code> | ||
+ | |||
+ | |||
+ | ==== TASKS ==== | ||
- Setup SharedPreferences (Follow TODO 1) | - Setup SharedPreferences (Follow TODO 1) | ||
- Get sharedPreferences | - Get sharedPreferences | ||
Line 27: | Line 127: | ||
- Load data on a different thread (not on the UI thread) | - Load data on a different thread (not on the UI thread) | ||
- Set the list of records to the adapter on the UI thread | - Set the list of records to the adapter on the UI thread | ||
+ | |||
+ | ===== Files ===== | ||
+ | {{:fss:sessions:android_4_start.zip|}} |