Async task and handlers
AsyncTask:
AsyncTask
is a class provided by Android that allows you to perform background operations and update the UI thread with the results. It simplifies the process of handling asynchronous tasks in Android by providing convenient methods for executing code in the background and updating the UI. The use of AsyncTask
is to perform background operations in Android applications, such as making network requests, database queries, or any other long-running tasks that should not block the main/UI thread. By executing these operations in the background, you ensure that the UI remains responsive and does not freeze.
The three generic types used in AsyncTask
are Params
, Progress
, and Result
, which represent the types of parameters passed to the task, the type of progress units published during the task's execution, and the result returned by the task.
AsyncTask's generic types
The three types used by an asynchronous task are the following:
Params
, the type of the parameters sent to the task upon execution.Progress
, the type of the progress units published during the background computation.Result
, the type of the result of the background computation. Not all types are always used by an asynchronous task. To mark a type as unused, simply use the type Void:
The 4 steps
When an asynchronous task is executed, the task goes through 4 steps:
onPreExecute()
, invoked on the UI thread before the task is executed. This step is normally used to setup the task, for instance by showing a progress bar in the user interface.doInBackground(Params)
, invoked on the background thread immediately after onPreExecute() finishes executing. This step is used to perform background computation that can take a long time. The parameters of the asynchronous task are passed to this step. The result of the computation must be returned by this step and will be passed back to the last step. This step can also use publishProgress(Progress) to publish one or more units of progress. These values are published on the UI thread, in the onProgressUpdate(Progress) step.onProgressUpdate(Progress)
, invoked on the UI thread after a call to publishProgress(Progress). The timing of the execution is undefined. This method is used to display any form of progress in the user interface while the background computation is still executing. For instance, it can be used to animate a progress bar or show logs in a text field.onPostExecute(Result)
, invoked on the UI thread after the background computation finishes. The result of the background computation is passed to this step as a parameter. Here's an example of usingAsyncTask
to fetch data from a network API and update the UI with the results:
In this example, doInBackground()
method performs the network operation in the background, while onPostExecute()
runs on the UI thread and updates the UI with the fetched data. The execute()
method is used to start the task.
The AsyncTask<Void, Void, String>
used in the NetworkTask
class declaration represents the type parameters for the AsyncTask
class. These type parameters define the input, progress, and result types for the task. Let's break down each type parameter:
Void
: The first type parameter represents the input type for the task'sdoInBackground
method. In this case,Void
indicates that the task does not take any input parameters. ThedoInBackground
method in theNetworkTask
example does not require any input, soVoid
is used.Void
: The second type parameter represents the progress type for the task. It is used when you want to report the progress of the background operation to the UI thread. In this example,Void
is used to indicate that no progress information will be reported. If you need to update the UI with progress updates, you can replaceVoid
with a suitable progress type, such asInteger
orFloat
.String
: The third type parameter represents the result type of the task'sdoInBackground
method and the input type for theonPostExecute
method. In this case, thedoInBackground
method fetches data from the API and returns it as aString
. TheonPostExecute
method receives this result and uses it to update the UI.
The AsyncTask
class provides a convenient way to handle the background operation and communicate with the UI thread. It contains several callback methods that allow you to execute code on the background thread (doInBackground
), report progress (onProgressUpdate
), and update the UI with the result (onPostExecute
).
In the example you provided, AsyncTask<Void, Void, String>
is used to create a background task that fetches data from an API and updates a textView
with the fetched data. The doInBackground
method performs the network operation, onPostExecute
updates the UI, and execute
is called to start the task.
Example that includes all three arguments of an AsyncTask
:
In this example:
The
NetworkTask
class extendsAsyncTask<String, Integer, String>
, indicating that the first parameter (String
) represents the input type, the second parameter (Integer
) represents the progress type, and the third parameter (String
) represents the result type.The
doInBackground
method receives an array of URLs as the input (String... urls
) and iterates over each URL. For demonstration purposes, it simulates progress by incrementing thetotalProgress
variable and publishing the progress usingpublishProgress(totalProgress)
.The
onProgressUpdate
method logs the progress value received (progressValues[0]
in this case).The
onPostExecute
method logs the completion of the task and the result.
To execute this NetworkTask
and process multiple URLs, you can use the following code:
In this example, url1
, url2
, and url3
represent the URLs you want to process. Create an instance of NetworkTask
and call execute
on it, passing the URLs as separate arguments. This will start the execution of the NetworkTask
, triggering the appropriate methods (doInBackground
, onProgressUpdate
, onPostExecute
) based on the execution flow.
As the NetworkTask
processes each URL, it will publish progress updates through publishProgress
, and the onProgressUpdate
method will be invoked with the progress value. After all URLs are processed, the onPostExecute
method will be called, logging the completion of the task and the result message.
Handler:
Handler
is a class that allows you to schedule and handle messages and runnable objects to be executed on a specific thread. It is often used for communication between background threads and the UI thread in Android. Handler
allows you to post messages or runnables to the message queue of a thread and process them at a later time.
Here's an example of using Handler
to update a UI element periodically:
This code snippet demonstrates a common pattern used in Android development for performing periodic updates to the user interface (UI) elements.
private Handler handler = new Handler();
: This line creates an instance of theHandler
class, which is used to schedule and manage tasks on the main (UI) thread.private Runnable runnable = new Runnable() {...}
: This creates an anonymous inner class implementing theRunnable
interface. TheRunnable
interface represents a unit of work that can be executed by a thread. In this case, therun()
method will be executed periodically to update the UI elements.public void run() { ... }
: Therun()
method contains the code that will be executed periodically. In this example, theupdateUI()
method is called to update the UI elements. You would replace this method with your own code to update the UI based on your requirements.handler.postDelayed(this, 1000);
: This line schedules the next execution of therun()
method after a 1-second delay. It uses thepostDelayed()
method of theHandler
class to enqueue theRunnable
for execution on the main (UI) thread.handler.post(runnable);
: This line starts the periodic updates by posting therunnable
object to theHandler
for execution. Therun()
method will be called immediately, and subsequent executions will be scheduled usingpostDelayed()
.handler.removeCallbacks(runnable);
: This line stops the periodic updates by removing any pending executions of therunnable
from theHandler
's queue. It ensures that therun()
method will no longer be called periodically.
In summary, this code sets up a Handler
to execute a Runnable
periodically on the UI thread. The run()
method updates the UI elements, and the updates occur every 1 second (1000 milliseconds) until removeCallbacks()
is called to stop the periodic updates.
ThreadPoolExecutor:
ThreadPoolExecutor
is a class that provides an efficient way to manage and execute multiple threads in a pool. It is a more flexible alternative to using raw threads directly. ThreadPoolExecutor
allows you to control the maximum number of threads, handle task scheduling, and manage thread lifecycle.
Here's an example of using ThreadPoolExecutor
to execute multiple tasks concurrently:
This code snippet demonstrates the usage of ThreadPoolExecutor
in Java for managing and executing multiple tasks concurrently.
int corePoolSize = 2;
: This line defines the core pool size, which represents the number of threads that the executor will keep alive even if they are idle. In this example, the core pool size is set to 2.int maximumPoolSize = 4;
: This line specifies the maximum pool size, which is the maximum number of threads that can be created by the executor. If there are more tasks than the core pool size and the work queue is full, the executor can create additional threads up to the maximum pool size. In this example, the maximum pool size is set to 4.long keepAliveTime = 60L;
: This line sets the keep-alive time for idle threads in the pool. If a thread is idle for the specified duration, it may be terminated and removed from the pool until the pool size reduces to the core pool size. In this example, the keep-alive time is set to 60 seconds.TimeUnit unit = TimeUnit.SECONDS;
: This line specifies the time unit for the keep-alive time. In this case, it is set to seconds.BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>();
: This line creates aBlockingQueue
implementation calledLinkedBlockingQueue
to hold the tasks that are waiting to be executed. TheLinkedBlockingQueue
has an unlimited capacity, but other implementations with a fixed capacity can also be used.ThreadFactory threadFactory = Executors.defaultThreadFactory();
: This line creates aThreadFactory
that will be used by the executor to create new threads. In this case, thedefaultThreadFactory()
method from theExecutors
class is used to create a default thread factory.RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
: This line sets theRejectedExecutionHandler
that determines what happens when a task cannot be accepted by the executor due to resource limitations. In this example, theAbortPolicy
is used, which throws aRejectedExecutionException
when a task cannot be executed.ThreadPoolExecutor executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
: This line creates an instance ofThreadPoolExecutor
with the specified parameters. It represents the executor that will manage the execution of tasks.executor.submit(new Task1());
: This line submits a task (Task1
) to the executor for execution. Thesubmit()
method returns aFuture
object representing the task's result and allows monitoring its status and obtaining the result if necessary.executor.shutdown();
: This line initiates the graceful shutdown of the executor. It allows the executor to finish executing the existing tasks but does not accept any new tasks. Once all tasks are completed, the executor terminates and releases its resources.
In summary, this code creates a ThreadPoolExecutor
with a fixed number of core and maximum threads, a work queue for holding tasks, and specific policies for managing rejected tasks. It then submits tasks to the executor and shuts it down when no more tasks need to be submitted..
Last updated
Was this helpful?