3

I'm new to Android. I want to ask you guys about Asynctask. I have an activity displays item's(an app, song, story..) detail info. It requires many related data such as screenshots, related apps (songs, stories), ... So what is the best implement of Asynctask ? Do i create one asynctask for each task (ex: 2 asynctask : 1 for get screenshots, 1 for get related item...) or put all in doInBackGround and publish progress?

Thanks in advance.

Trung Nguyen
  • 7,442
  • 2
  • 45
  • 87

2 Answers2

2

From a OO perspective, business logic stuff should be always isolated from UI stuff. I would isolating and centralizing all my business call like getSong(), getStore() etc. into a POJO, and keep my activity class only focus on UI manipulation/rendering, this is how I do it:

  1. Define an interface IBusinessDAO
  2. Define RealBusinessDAO implements IBusinessDAO
  3. Define MockBusinessDAO implements IBusinessDAO
  4. Call IBusinessDAO.getSong(); inside AsyncTask.doInBackground()

    public class MyActivity extends Activity {
      IBusinessDAO businessDAO;
    
      ... ...
    
      private class MyAsyncTask extends AsyncTask<Void, Void, Void> {
        ... ...        
    
        protected void doInBackground(Void... params) {
          businessDAO.getSong();
        }
      }
    
      ... ...
    
      public void onCreate(Bundle savedInstanceState) {
        if (runInTest)
          businessDAO = new MockBusinessDAO();
        else
          businessDAO = new RealBusinessDAO();
    
        new myAsyncTask().execute();
      }
    
    }
    

So in each of your AsyncTask implementation among different Activities, your AsyncTask.doInBackgroud() will be simple and clean, resulting keeping your code more efficient and maintainable.

It also help improve code testability, for unit-test your business logic, as it is a POJO, you can use purely JUnit write your test case. Sometimes we want to test UI component and we don't really care how underlying business logic is implemented, for instance, my business logic connect to remote http server download some json data, I don't want to do this every time when I just want to test the UI layout, for this situation, I can easily change all my Activities use MockBusinessDAO (sort of Spring's DI concept), to test UI component without concerning How the actual business logic is implemented.

Last, it also improve your code reusability as your businesDAO is nothing related to Andriod other than a classic POJO, in addition, you don't need concern any concurrency within your BusinessDAO implementation, as all it's methods will be called inside AsyncTask.doInBackground() method.

Hope that help.

yorkw
  • 40,926
  • 10
  • 117
  • 130
  • May be i dont explain clearly. My app somehow likes Android Market. For example: in detail application activity, it shows app screenshots, same category apps, same provider apps, recommend apps. **So i create 4 asynctasks to get data or put 4 functions in one asynctask and update UI by call publishProgress**. Which way is more effective. I alread had different models for song, app, story... and fake data :D – Trung Nguyen Feb 27 '12 at 09:16
  • Personally I prefer single AsyncTask with publishProgress, as long as all your time-consuming tasks are handled in background thread, use one is sufficient and more efficient that use several of them. – yorkw Feb 27 '12 at 09:33
1

I have implemented such kinds of task in one AsyncTask

private void _initCommonAsyncTask(AsyncTaskName currentTaskName,
        String searchQuery) {
    CommonAsyncTask task = new CommonAsyncTask(currentTaskName, searchQuery);
    task.execute();
    taskReference = new WeakReference<CommonAsyncTask>(task);
}

/**
 * Asynchronous Task for different functionalities.
 * 
 */
private class CommonAsyncTask extends AsyncTask<Void, Void, Void> {
    private final String searchQuery;
    private AsyncTaskName currentTaskName;

    /**
     * Default constructor
     */
    public CommonAsyncTask(AsyncTaskName currentTaskName, String searchQuery) {
        super();
        this.searchQuery = searchQuery;
        this.currentTaskName = currentTaskName;
    }

    @Override
    protected void onPostExecute(Void result) {
        switch (currentTaskName) {
        case SEARCH:
            // Reinitialized the list view
            break; 
        case REFRESH:
            // Reinitialized the list view
            break;
        case LOAD_NEXT:
            // Reinitialized the list view
            break;
        default:
            break;
        }
        super.onPostExecute(result);
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }

    @Override
    protected Void doInBackground(Void... params) {
        switch (currentTaskName) {
        case SEARCH:
            // My searching stuff here
            break;
        case REFRESH:
            // my refreshing stuff here
            break;  
        case LOAD_NEXT:
            //my load next 50 orders here
            break;  
        default:
            break;
        }
        return null;
    }
}

You can call the Asynctask using

_initCommonAsyncTask(AsyncTaskName.SEARCH, searchQuery);

Define your task list in enum like this

public enum AsyncTaskName {
    SEARCH, REFRESH, LOAD_NEXT;
}
Rafiq
  • 2,000
  • 2
  • 21
  • 27