Combining Handler and AsyncTask in Android - Obvious Flaws? - java

I have a simple Android app which uses AsyncTasks for I/O. A frequent pattern:
User clicks a button
In response, an onClick handler instantiates and .execute()s an AsyncTask
Once the AsyncTask completes, the UI should be updated in some way
According to the documentation for AsyncTask, the correct way to accomplish the UI updates is to override onPostExecute in the AsyncTask class - this will be invoked back on the UI thread after execution and thus can touch the widgets, etc.
However, it seems wrong to me that onPostExecute should have any sort of hard reference to a UI element. I would prefer to keep my I/O tasks and UI code separate. Instead, this seems the obvious situation where I should pass an opaque callback to the AsyncTask - the callback retains a reference to the UI elements and thus we maintain isolation and reusability in the code. A classic delegate pattern (or perhaps listener, event, etc, many options here).
As an example, the code below seems wrong to me:
class QueryJobsDBTask extends AsyncTask<Void, Void, ArrayList<ContentValues>> {
#Override
protected void onPostExecute(ArrayList<ContentValues> freshJobsData) {
someList.clear();
someList.addAll(freshJobsData);
// BUG why does my DB query class hold UI references?
someAdapter.notifyDataSetChanged();
}
After some research, it looks like the Handler class is the most straightforward and lightweight way to accomplish a delegate pattern here. I can write reusable AsyncTasks for I/O and specify contextual UI update callbacks on a per-instance basis via Handler instances. So I have implemented this new Handler-enabled base class
public abstract class HandlerAsyncTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> {
private Handler preExecuteHandler, postExecuteHandler;
public void setPreExecuteHandler(Handler preExecuteHandler) {
this.preExecuteHandler = preExecuteHandler;
}
public void setPostExecuteHandler(Handler postExecuteHandler) {
this.postExecuteHandler = postExecuteHandler;
}
#Override
protected void onPreExecute() {
if (preExecuteHandler != null) {
preExecuteHandler.sendMessage(Message.obtain());
}
}
#Override
protected void onPostExecute(Result result) {
if (postExecuteHandler != null) {
Message msg = Message.obtain();
msg.obj = result;
postExecuteHandler.sendMessage(msg);
}
}
}
And voila, all of my I/O tasks are now properly partitioned from the UI - and I can still specify simple UI update callbacks when needed via Handler instances. This seems straightforward, flexible, and superior to me ... so of course I wonder what I'm missing.
How is the current framework solution superior? Is there some major pitfall to this approach? To my knowledge the topology of code execution and threads is the exact same at runtime, just code coupling is looser (and a few extra frames on the stack).

This is an elegant solution for segregating UI/Background tasks in small projects, although passing Runnables is even more elegant. Keep in mind that the AsyncTask is a wrapper around Thread/Handler, so you're doubling up on the thread-messaging that's already going on behind the scenes. The flaw here is that if you design the AsyncTasks to be reusable, you'll need to make sure that the IO you're running are all thread-safe, as there's no communication between the various AsyncTasks as to who is active or accessing which resources. An IntentService might be more appropriate if you need to queue background tasks rather than just fire them.

It's not so much a matter of superiority as purpose & use-case. AsyncTasks are usually written as private classes (or declared anonymously inline) within Activities, and as such inherit the Activity's references to various UI elements that need updating anyway.
If an AsyncTask is of sufficient size and/or complexity that it should be pulled out into its own class, and can be re-used by other classes, than using Handlers for better decoupling is a great idea. It's just that it's often not necessary, as the AsyncTask is accomplishing something specific to the Activity in which it was defined, and for simple ones, the corresponding handler code could even be larger than the entire AsyncTask itself.

Related

How to properly asychronously load UI component using Event Queues in ZK framework?

I have a custom composer/controller class that extends GenericForwardComposer. Inside this class I have some methods that are being used to initialize UI components with data. This is a very long operation and takes time to complete. Due to performance issues I am trying to asynchronously load this data using Event Queues. This way it will not block users from accessing other functions while the process runs in the background.
In my custom class there is an init method that starts the processing. This method invokes several other methods that handle the majority of the work.
My thinking was that I can use Event Queues something as such:
public class MyWidgetController extends GenericForwardComposer
{
public void init(final Component comp)
{
//other method logic ...
EventQueue queue = EventQueues.lookup("myQueue", EventQueues.SESSION, true);
queue.subscribe(this); //not sure
queue.publish(new Event("onInitPrimaryLoad", componentA, ""));
queue.publish(new Event("onInitSecondaryLoad", componentB, ""));
}
#ViewEvent(componentID = "componentA", eventName = "onInitPrimaryLoad")
public void onInitPrimary( final Event event){ //logic }
#ViewEvent(componentID = "componentB", eventName = "onInitSecondaryLoad")
public void onInitSecondary( final Event event){ //logic }
//other class methods…
}
Not sure if this is all correct. Don't really need a callback method as the Events (publish) themselves are loading the UI components with data. The application runs with no issue but I'm not sure if I'm implementing this correctly.
Any advice or corrections are appreciated
The #ViewEvent seems to be Hybris specific and is not part of the ZK framework, that's why I can't comment on it.
Your example doesn't do async processing at all, the events are published into the current thread and the ui will block and only return after all these events have been processed. (even worse using a SESSION scoped event queue the events are published into all desktops (roughly browser tabs) of that user - most likely executing your heavy work multiple times. You should use a DESKTOP scoped event queue instead.
Also I don't fully understand why you don't need a callback ... when doing async processing you always need some kind of callback or create a thread manually.
Especially in ZK it is vital to perform the heavy work in a separate thread. Once the data is retrieved lock the UI as short as possible to perform updates to the component tree or component models - this keeps the UI as responsive to the user as possible.
The EventQueue usage is described in the official docs.
Based on those I create 2 runnable examples illustrating the simplified and the more generic approach.
As an alternative you can activate/deactivate a ZK desktop directly without using event queues as in this (my preferred) example.

Do I need to use multiple AsyncTask subclasses?

My app has FTP functionality and now I want to implement a ProgressDialog for the various operations (Connect, download, upload, file list etc.)
I found this snippet here on stack and it seemed like a good starting point.
public class LoadData extends AsyncTask<Void, Void, Void> {
ProgressDialog progressDialog;
//declare other objects as per your need
#Override
protected void onPreExecute()
{
progressDialog= ProgressDialog.show(FTPConnector.this, "Please wait for ","Process Description Text", true);
//do initialization of required objects objects here
};
#Override
protected Void doInBackground(Void... params)
{
//do loading operation here
return null;
}
#Override
protected void onPostExecute(Void result)
{
super.onPostExecute(result);
progressDialog.dismiss();
};
}
I've implemented it as a subclass of my FTPConnector class which contains the various methods for connect, download, upload, listfiles,rename, delete. Do I need to create a subclass of ASyncTask for each FTP operation? If not what can I do?
Firs of all, I was under the impression that using AsyncTask as a subclass of activity was disfavored since the task would retain a reference to the activity that started it which could cause problems. I've generally used AsyncTask as its own class and passed in the context of the activity that executed it. You should look into that.
Second you could make different tasks for each server transaction. I guess it depends how many their are or how complicated your application is. Other than that you could use one class with a switch statement in the doInBackground method and pass in a string tag as one of the varargs (assuming your task takes only strings as initial arguments). This just seems cumbersome and ugly.
I'd probably just make one task for each transaction.
Do I need to create a subclass of ASyncTask for each FTP operation?
Not necessarily but that will depend on the logic that you use inside your AsyncTask methods. If you make them to handle the function that operation needs then you will be ok. But depending on the logic for each operation, it may be easier to control if you create a separate class for each.
However, note that you will need to create a new instance each time you need to call execute(), according to the Docs
The task can be executed only once (an exception will be thrown if a second execution is attempted.)
Using AsyncTask for multiple transaction will work, but this is not proper solution. As written before: it could cause problems. I suggest you to take a look at this video(it's about REST client, but described patterns will work for you too). Follow these rules:
Perform transaction in a separate thread
Every thread must be started from a Service
To retain state of transaction use database(don't keep states in a memory)
Use SyncAdapter. Not sure that it works for you(it's depends on your needs)

Firing Android Activity methods on separate process at set interval

I am writing my first Android app(allot of fun so far!) and have run into a roadblock. I am using SDK tools 21.1 targeting Android 4.2.
I am trying to set up a system that allows activities to register to invoke a method at set time intervals. I wanted to do this in such a way that the processing of the request would be handled on it's own process to avoid making the UI unresponsive.
I have been doing some reading and have explored a few avenues. First I thought that a service would be a good way to go about this but found a fair bit of information suggesting that was not a good course of action due to the OS being able to kill services indiscriminately.
I'm now looking at using a ScheduledThreadPoolExecutor. I've created this simple class with an overridable method to pass methods around:
public abstract class BaseEvent implements EventListener {
public abstract void onFire(Object... params);
}
I've created this runnable task invoke the method:
public class HeartBeatTask implements Runnable {
private BaseEvent mCallback;
private Object mParams;
public HeartBeatTask(BaseAioEvent callback,Object... params){
mParams = params;
mCallback = callback;
}
#Override
public void run() {
Log.d(LOG_TAG,"Run called");
if(mCallback != null)
{
mCallback.onEvent(mParams);
}
}
}
I'm going to use it like this (inside an Activity)
ScheduledThreadPoolExecutor threadPool = new ScheduledThreadPoolExecutor(1);
BaseEvent callback = new BaseEvent() {
public void onFire(Object... params){
if(params[0] !=null)
{
Context context = (Context)params[0];
Toast toast = Toast.makeText(context, "Task ran", Toast.LENGTH_SHORT);
toast.show();
}
}
};
threadPool.scheduleAtFixedRate(new HeartBeatTask(callback,(this)),0, 5, TimeUnit.SECONDS);
This will execute the task every 5 seconds, although the callback method is only being run once.
I'm thinking that this may not be a good way to do things. My feeling is that I'm overcomplicating things. What I really need is the ability to have something that will execute a method, on a process other than the main thread, and at a set interval, that activities can bind multiple actions to. So, for instance, I may want to have a UI component update after a call is made to a database, and would want that to happen every minute.
Could any tell me if I am on the right track here? Is what I am trying to do a viable way to accomplish my goal? Is there a better approach I could be taking? Any advice or suggestions would be very much appreciated. Thanks!
a few suggestions for an Android beginner.
Don't call it a separate process. Process is a different thing (Google 'Linux process'), you want to call them on a separate thread inside the same process.
ScheduledThreadPoolExecutor IS better than anything else people will suggest you here such as Timers or PostDelayed.
But I think you do have a philosophical error here as to UI updates shouldn't be running on a timed manner but on an event base instead. Once your Db, Disk or Network operation finishes from a background thread you callback to the UI thread to update it immediately.
There`re several tools for that and I'll list a few, point the one I like the best, but let you do some research on each one
Handler: That's basic java way
AsyncTask: Nice framework but doesn't handle screen rotation
Loader: That's my preferred way
I think your approach is a bit complicated. Consider you example
So, for instance, I may want to have a UI component update after a call is made
to a database, and would want that to happen every minute.
I think I will do it this way.
Create a AsyncTask which will update the UI component.
Create a thread which will execute a new AsyncTask and sleep one minute in a while loop.
Start the thread in step 3. at some point.
Interrupt the thread if you don't want the component to be updated.
Example of step 2
while (true) {
try {
new updateTask.execute();
Thread.sleep(60000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
Android is a mobile platform and in all honesty each time you want something run, you better consider it separately. You may be killing the battery or using resources for no reason. I begrudge Zedge app everyday for running for no reason in the background at all times. Especially since on CyanogenMod kernel puts WiFi to sleep, while apparently it is currently on.
I am guessing this is more of an exercise and for running tasks at a specified intervals. One-offs, most universal can be done via AlarmManager class. But this may not be the best solution.
For some system wide events there is the BroadcastReceiver class.
While addressing
So, for instance, I may want to have a UI component update after a call is made to a database, and would want that to happen every minute.
Easier done via an Interface really.

Swing Worker Thread : Inner class vs passing parameter

I know SO is for specific questions but I need an advise on what is the correct practice in Java for working with swing worker thread.
My application generates large HTML text in response to a calculation process which is is displayed in a jTextPane. To avoid blocking the GUI I used to do the calculation in a Swing Worker Thread.
My problem is the following to start the calculation I need plenty information available in different menus checkboxes and listbox of the GUI, and at the end of the calculation I need to start functions within the EDT.
Here are 2 possibilities for me :
First one is to send plenty of information to my Swing Worker and also need to pass the MainFrame to access specific functions in the "done()"
public class MyWorker extends SwingWorker<Void, Void> {
private MyMainFrame frame;
public MyWorker(plenty of params) {
}
#Override
public Void doInBackground() {
//my background process
}
#Override
public void done() {
frame.myfunc1;
frame.myfunc2;
frame.myfunc3;
}
}
Second one would be to use a Inner Class
Which one is correct to do in Java. If both are "correct" what are the pros and cons of one against the other.
Both approaches are OK. The advantage of an inner class is that it has access to the internals of the enclosing object. The disadvantage is that it's not reusable in another context (another frame which would have a similar interface, for example).
Just make sure your code is well structured and readable. For example, you might want to extract the three method calls in your done() method in a single method of the frame.
If it is the large amount of parameters you have to pass in the constructor that is bothering you, you can group those parameters in a container object and just pass the container (e.g. a MyWorkerContext class).
I personally would try to avoid passing the UI (elements) itself, but rather pass a model/stream/... which will be updated by the SwingWorker, allowing me to refactor the UI later on without having to fiddle with my SwingWorker class.

On MultiThreading on the Android platform

Multithreading on Android is to some extent an easy task due to the various possibilities available for us.
However it would be nice to understand the difference between the approaches.
What is the best way to multitask and based on what preferences is it the "best"?
AsyncTask?
class MultiTasker extends AsyncTask<, , >
Runnable?
Runnable myRun = new Runnable(){
public void run(){
}
};
Thread T = new Thread(myRun);
T.start();
Handler?
class MultiTasker extends Handler
Asking which one is "best" is the wrong approach here - it depends on what you are trying to accomplish.
Runnable/Thread - This is the basic, lowest-level ways to control threading in Java. Provided in the Java APIs, so they're not specific to Android. You can use these in Android programs, but you'll probably want to use one of the other two options for most tasks (or use them in addition to Threads).
Handler - Provided in the Android APIs. You can post() a Runnable directly, or sendMessage() a Message (along with other options, such as providing a delay before processing a Runnable or Message). However, Handler isn't something you would use by itself to provide multithreading - it's use is usually to get back into the main activity (UI) thread. You'd start some other Thread to do a process in the background, and inside of it would post a Runnable using the Handler when you needed to update the UI. Or if you had a task that didn't necessarily need to run in the background, but did need to pop up and do something every so often, you could post a Runnable with a delay to activate later, and then at the end post itself again with a delay.
AsyncTask - Provided in the Android APIs. This class is for doing something on a background thread, optionally providing incremental updates on the UI thread, and ultimately providing an end result on the UI thread. The Params, Progress, and Result generic types are used to provide start parameters, progress update data, and end result data, respectively. Internally, AsyncTask uses Threads, Runnables, and Handlers to accomplish this task.
Its Always better if you go with AsyncTask().. because Thats something which has been built to solve MultiThreading issues in Android..

Categories

Resources