Differences

This shows you the differences between two versions of the page.

Link to this comparison view

smd:laboratoare:04 [2019/03/18 15:10]
adriana.draghici [Tasks]
smd:laboratoare:04 [2021/05/12 17:46] (current)
adriana.draghici [Tasks]
Line 6: Line 6:
   * Understand and practice the basic way of multi-threading in Android using handlers, runnables and thread pools.   * Understand and practice the basic way of multi-threading in Android using handlers, runnables and thread pools.
   * Learn why AsyncTasks are not recommended to be used.   * Learn why AsyncTasks are not recommended to be used.
-  * Revise basic concurrency objects available in Java 
  
 ==== Threading in Android ==== ==== Threading in Android ====
Line 16: Line 15:
 :!: 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]].
  
-Regarding the relationship between the threading components and the **lifecycle** the UI components (activities and fragments), certain threading objects can be tied and other not. The IntentServices we discussed in Lab3 are not tied to the activities or fragments lifecycle, but the AsyncTasks (Android specific threading components),​ are terminated when the UI components are destroyed.+Regarding the relationship between the threading components and the **lifecycle** ​of the UI components (activities and fragments), certain threading objects can be tied to the UI lifecycle ​and other not. The IntentServices we discussed in Lab3 are not tied to the activities or fragments lifecycle, but the AsyncTasks (Android specific threading components),​ are terminated when the UI components are destroyed.
  
 In [[smd:​laboratoare:​03#​using_intent_services|Lab 3]] we presented IntentServices which also run on separate threads. The mechanisms we will focus on this lab, some of them you might be familiar with from Java: In [[smd:​laboratoare:​03#​using_intent_services|Lab 3]] we presented IntentServices which also run on separate threads. The mechanisms we will focus on this lab, some of them you might be familiar with from Java:
   * Runnables and Handlers   * Runnables and Handlers
   * ThreadPoolExecutor   * ThreadPoolExecutor
-  * AsyncTasks - not recommended 
   * JobScheduler   * JobScheduler
  
-Other threading mechanisms ​we recommend+We will also briefly discuss AsyncTasks, which are not recommended and will be deprecated in the next Android release (R). 
-  * Reactive programming using [[https://​blog.gojekengineering.com/​multi-threading-like-a-boss-in-android-with-rxjava-2-b8b7cf6eb5e2|RxJava]] or RxKotlin - do not need to explicitly create threads, just choose a scheduler+ 
 +<note tip>​Because this course'​s scope does not include learning a new language, we will not address in this lab asynchronous programming using the **[[https://​developer.android.com/​topic/​libraries/​architecture/​coroutines|coroutines]]** provided in **Kotlin**. Nonetheless,​ if you want to learn and code in Kotlin, or are already familiar with it, feel free to use them in your project. Useful video overview: [[https://​www.youtube.com/​watch?​v=BOHK_w09pVA|Understand Kotlin Coroutines on Android (Google I/​O'​19)]]. 
 +</​note>​ 
 +Other threading mechanisms ​you can use and are not covered in this lab
 +  ​* **Reactive programming** using **[[https://​blog.gojekengineering.com/​multi-threading-like-a-boss-in-android-with-rxjava-2-b8b7cf6eb5e2|RxJava]]** or **RxKotlin** - do not need to explicitly create threads, just choose a scheduler
     * proceed with caution! (completely changes the design of the app, choose it depending on what you need to do, e.g. it's very useful if your app relies heavily on event-driven logic)     * proceed with caution! (completely changes the design of the app, choose it depending on what you need to do, e.g. it's very useful if your app relies heavily on event-driven logic)
-  * [[https://​kotlinlang.org/​docs/​reference/​coroutines/​coroutines-guide.html|Coroutines]] - Kotlin specific light-weight threads 
   * [[https://​github.com/​androidannotations/​androidannotations|androidannotations]] - not to be confused with the [[https://​developer.android.com/​studio/​write/​annotations|annotations]] offered by the Android API   * [[https://​github.com/​androidannotations/​androidannotations|androidannotations]] - not to be confused with the [[https://​developer.android.com/​studio/​write/​annotations|annotations]] offered by the Android API
  
Line 104: Line 105:
 === Using Handlers ===  === Using Handlers === 
 We need a **messaging mechanism between threads**, and Android offers [[https://​developer.android.com/​reference/​android/​os/​Handler|Handlers]]. These are closely connected to other objects needed for messaging: We need a **messaging mechanism between threads**, and Android offers [[https://​developer.android.com/​reference/​android/​os/​Handler|Handlers]]. These are closely connected to other objects needed for messaging:
-  * [[https://​developer.android.com/​reference/​android/​os/​Looper|Looper]] - provided to a Handler, ​it runs the message queue in loop+  * [[https://​developer.android.com/​reference/​android/​os/​Looper|Looper]] - provided to a Handler, ​keeps thread alive, loops through MessageQueue and sends Messages to the corresponding Handler to process it
   * [[https://​developer.android.com/​reference/​android/​os/​Message|Message]] - the message to be sent to a Handler   * [[https://​developer.android.com/​reference/​android/​os/​Message|Message]] - the message to be sent to a Handler
   * [[https://​developer.android.com/​reference/​android/​os/​MessageQueue|MessageQueue]] - the messages dispatached to a Looper, the developer doesn'​t interact directly with it, most interaction is through the Handler class   * [[https://​developer.android.com/​reference/​android/​os/​MessageQueue|MessageQueue]] - the messages dispatached to a Looper, the developer doesn'​t interact directly with it, most interaction is through the Handler class
Line 207: Line 208:
 ==== AsyncTask ==== ==== AsyncTask ====
    
-Using AsyncTasks we can run logic in background on a thread and pass results back to the UI (main thread).+Using AsyncTasks we can run logic in background on a thread and pass results back to the UI (main thread).  
 + 
 +They have been widely used in the Android world for more than 10 years. When searching for tutorials on asynchronous programming/​threading in Android you might encounter a lot of examples with AsyncTask, but bear in mind their deprecation and if you really want to use them, use them only for very short operations.
    
-The [[https://​developer.android.com/​reference/​android/​os/​AsyncTask|AsyncTask]] is an abstract task and developers need to extend it and implement at least its only abstract method, **''​doInBackground''​**,​ which is **always run on the dedicated thread**. Inside it we can call ''​publishProgress''​ if we want to send updates to the UI while the task is still running. The rest of its methods are **run on the main UI thread** and usually called implicitly: ''​onPreExecute,​ onProgressUpdate,​ onPostExecute''​. You should not call them from your UI components, just implement the ones you need, they will be called by the system. +The [[https://​developer.android.com/​reference/​android/​os/​AsyncTask|AsyncTask]] is an abstract task and developers need to extend it and implement at least its only abstract method, **''​doInBackground''​**,​ which is **always run on the dedicated thread**. Inside it we can call ''​publishProgress''​ if we want to send updates to the UI while the task is still running. The rest of its methods are **run on the main UI thread** and usually called implicitly: ''​onPreExecute,​ onProgressUpdate,​ onPostExecute''​. You should not call them from your UI components, just implement the ones you need, they will be called by the system. The official documentation recommends the AsyncTasks only for short operations (a few seconds)
-   +
-<note important>​The official documentation recommends the AsyncTasks only for short operations (a few seconds)</​note>​+
    
-AsyncTasks offer the advantage of easily running code on a different thread and also send the results to the UI, but they are not recommended for operations longer than a few seconds, ​ because of their dependence on UI.+AsyncTasks offer the advantage of easily running code on a different thread and also send the results to the UI, but they are not recommended for operations longer than a few seconds, because of their dependence on UI.
   *     The UI can be blocked in some cases because pre and post execute methods are run on the UI thread: e.g. when one task takes more than expected, and other tasks are triggered from the UI, the second task’s preExecute method is blocked until the first task’s postExecute method is called.   *     The UI can be blocked in some cases because pre and post execute methods are run on the UI thread: e.g. when one task takes more than expected, and other tasks are triggered from the UI, the second task’s preExecute method is blocked until the first task’s postExecute method is called.
-  *     Can lead to memory leaks if the activity that started the task was destroyed in the meantime.+  *     ​Can ​**lead to memory leaks** if the activity that started the task was destroyed in the meantime. 
 + 
 +<note important>​Official reason for deprecation of the AsyncTask:​ 
 +//AsyncTask was intended to enable proper and easy use of the UI thread. However, the most common use case was for integrating into UI, and that would cause Context leaks, missed callbacks, or crashes on configuration changes. It also has inconsistent behavior on different versions of the platform, swallows exceptions from doInBackground,​ and does not provide much utility over using Executors directly.// (snippet from AsyncTask javadoc) 
 +</​note>​
    
 ==== Synchronization mechanisms ==== ==== Synchronization mechanisms ====
Line 232: Line 237:
 Create an Android Studio project and name it `Lab 4`.  Create an Android Studio project and name it `Lab 4`. 
  
-=== Task 1 (3p) === +=== Task 1 (6p) ===
- +
-In this task we will download a file from a URL and will inform the user about the progress and final result. All of this will be done on a background thread using an [[smd:​laboratoare:​03#​asynctask|AsyncTask]]. +
- +
-  * In ''​MainActivity''​ create a private inner ''​AsyncTask''​ class and name it ''​FileDownloadTask''​. The AsyncTask will receive a URL, will send an Integer as update and will return a Long result. +
-  * In the ''​FileDownloadTask''​ override ''​onPreExecute(),​ doInBackground(),​ onProgressUpdate()''​ and ''​onPostExecute()''​. Add a debug Log statement with the current method and thread name. +
-  * In''​ doInBackground()''​ download the file from the URL and publish an update based on the total bytes downloaded. In this exercise we will not download a real file. In exchange will put a ''​Thread.sleep(100)''​ and will increment a counter representing the total bytes transferred. Use the code for doInBackground() from the lab archive. +
-  * In ''​onProgressUpdate()''​ call a method which updates the text of a TextView to show to the user the progress of the download. Use the code for onProgressUpdate() from the lab archive. +
-  * In ''​onPostExecute()''​ display the final value and present a Toast message to the user informing that the file download is complete. Use the code for onPostExecute() from the lab archive. +
- +
-===Task 2 (2p)=== +
- +
-Using the code from the previous task we will see why AsyncTask is not recommended to be used.  +
-  * Change the Thread.sleep() value to 1000 milliseconds and make a configuration change(example screen rotation). What happens with the AsyncTask?​ +
-  * Close the AsyncTask when the activity lifecycle has ended. When the task is stopped? +
- +
-===Task 3 (3p)===+
  
-Implement ​the file download ​mocking ​from Task 1 using a runnable and handler.+Create an application that mocks the download ​of a file from an URL and will inform the user about the progress and final result. All of this will be done on a background thread ​using an a runnable and handler. 
 +  * the mock download is performed in a runnable 
 +  * the main activity is informed by the runnable about the mock progress using a handler
  
 **Hint:** Check the code examples from the lab. **Hint:** Check the code examples from the lab.
  
-===Task 4 (2p)===+/*===Task 4 (2p)===
  
-Using the notification code from the lab archive and a service from [[smd:​laboratoare:​03|Lab 3]] create a foreground service by adding the notification code. Create ​a button ​that will stop the notification using ''​stopForeground()''​+Using the notification code from the lab archive and a service from [[smd:​laboratoare:​03|Lab 3]] create a foreground service by adding the notification code. Create ​two buttons ​that will start and stop the foreground service
  
-Disclaimer: ​leftover topic from Lab3, it is not related to threading, the service runs in the main thread.+Disclaimer: ​Topic from Lab3, it is not related to threading, the service runs in the main thread.*/
  
-===Task ​(2p bonus)===+===Task ​(4p)===
  
-Mock the download of several files (at least 10) in parallel on multiple threads using Runnables and ThreadPoolExecutor ([[https://​developer.android.com/​reference/​java/​util/​concurrent/​ThreadPoolExecutor|documentation]],​ [[https://developer.android.com/training/multiple-threads/​create-threadpool#​ThreadPool|creation ​example]]). +Mock the download of several files (at least 10) in parallel on multiple threads using Runnables and ThreadPoolExecutor ([[https://​developer.android.com/​reference/​java/​util/​concurrent/​ThreadPoolExecutor|documentation]],​ [[https://www.journaldev.com/1069/threadpoolexecutor-java-thread-pool-example-executorservice|example]]). 
-  * In the "mocking" ​of download, each thread should sleep a random number between 100 and 200 ms.+  * For the "mock" download, each thread should sleep a random number between 100 and 200 ms.
   * The UI should update in real time a text view with the following content:   * The UI should update in real time a text view with the following content:
      <​code>​      <​code>​
Line 271: Line 262:
       …       …
       </​code>​       </​code>​
-   ​* ​The text view must have the option ​android:​inputType="​textMultiLine".+   ​* ​To show multiple line you can add the ''​android:​inputType="​text"''​ to the TextView
  
  
-==== Resources ==== +/*==== Resources ==== 
-  * {{:​smd:​laboratoare:​lab4.zip|lab4-skel}} - code snippets for the AsyncTask and Foreground Service exercise+  * {{:​smd:​laboratoare:​lab4_skel.zip|lab4-skel}} - code snippets for the AsyncTask and Foreground Service exercise*/
  
 ==== Useful links ==== ==== Useful links ====
smd/laboratoare/04.1552914637.txt.gz · Last modified: 2019/03/18 15:10 by adriana.draghici
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