ca.ualberta.cmput301w14t08.geochan.managers.ThreadManager.java Source code

Java tutorial

Introduction

Here is the source code for ca.ualberta.cmput301w14t08.geochan.managers.ThreadManager.java

Source

/*
 * Copyright 2014 Artem Chikin
 * Copyright 2014 Artem Herasymchuk
 * Copyright 2014 Tom Krywitsky
 * Copyright 2014 Henry Pabst
 * Copyright 2014 Bradley Simons
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package ca.ualberta.cmput301w14t08.geochan.managers;

import java.util.Queue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.osmdroid.bonuspack.overlays.Marker;

import android.app.ProgressDialog;
import android.content.Context;
import android.graphics.Bitmap;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.support.v4.app.FragmentActivity;
import android.support.v4.util.LruCache;
import android.widget.ImageView;
import ca.ualberta.cmput301w14t08.geochan.fragments.ThreadListFragment;
import ca.ualberta.cmput301w14t08.geochan.fragments.ThreadViewFragment;
import ca.ualberta.cmput301w14t08.geochan.helpers.SortUtil;
import ca.ualberta.cmput301w14t08.geochan.models.Comment;
import ca.ualberta.cmput301w14t08.geochan.models.CommentList;
import ca.ualberta.cmput301w14t08.geochan.models.GeoLocation;
import ca.ualberta.cmput301w14t08.geochan.models.ThreadComment;
import ca.ualberta.cmput301w14t08.geochan.models.ThreadList;
import ca.ualberta.cmput301w14t08.geochan.tasks.GetCommentsTask;
import ca.ualberta.cmput301w14t08.geochan.tasks.GetImageTask;
import ca.ualberta.cmput301w14t08.geochan.tasks.GetPOITask;
import ca.ualberta.cmput301w14t08.geochan.tasks.GetThreadCommentsTask;
import ca.ualberta.cmput301w14t08.geochan.tasks.PostTask;

/**
 * Responsible for managing various threads that require to run in the
 * background and communicate with the network. Can set up, launch given tasks,
 * monitor their state, and react to state changes by communicating with the UI.
 * Is a singleton.
 * 
 * Created using the tutorial at
 * http://developer.android.com/training/multiple-threads/create-threadpool.html
 * 
 * @author Artem Herasymchuk
 * @author Artem Chikin
 * 
 */
public class ThreadManager {

    // These are the states of all tasks this manager handles
    // Post a comment to elasticSearch
    public static final int POST_FAILED = 1;
    public static final int POST_RUNNING = 2;
    public static final int POST_COMPLETE = 3;
    // Update the commentList on elasticSearch
    public static final int UPDATE_FAILED = 4;
    public static final int UPDATE_RUNNING = 5;
    // Post an image to elasticSearch
    public static final int POST_IMAGE_FAILED = 6;
    public static final int POST_IMAGE_RUNNING = 7;
    public static final int POST_IMAGE_COMPLETE = 8;
    // Retrieve commentList from elasticSearch
    public static final int GET_COMMENT_LIST_FAILED = 9;
    public static final int GET_COMMENT_LIST_RUNNING = 10;
    public static final int GET_COMMENT_LIST_COMPLETE = 11;
    // Retrieve single comment from elasticSearch
    public static final int GET_COMMENTS_FAILED = 12;
    public static final int GET_COMMENTS_RUNNING = 13;
    public static final int GET_COMMENTS_COMPLETE = 14;
    // Retrieve an bitmap image from elasticSearch
    public static final int GET_IMAGE_FAILED = 15;
    public static final int GET_IMAGE_RUNNING = 16;
    public static final int GET_IMAGE_COMPLETE = 17;
    // Get a point of interest
    public static final int GET_POI_FAILED = 18;
    public static final int GET_POI_RUNNING = 19;
    public static final int GET_POI_COMPLETE = 20;
    // Retrieve the threadList from elasticSearch
    public static final int GET_THREADS_FAILED = 21;
    public static final int GET_THREADS_RUNNING = 22;
    public static final int GET_THREADS_COMPLETE = 23;
    // Get a point of interest during a post
    public static final int POST_GET_POI_FAILED = 24;
    public static final int POST_GET_POI_RUNNING = 25;
    public static final int POST_GET_POI_COMPLETE = 26;
    public static final int POST_TASK_COMPLETE = 27;

    private static final int KEEP_ALIVE_TIME = 1;
    private static final TimeUnit KEEP_ALIVE_TIME_UNIT = TimeUnit.SECONDS;
    private static final int CORE_POOL_SIZE = 8;
    private static final int MAXIMUM_POOL_SIZE = 8;
    private static final int MAXIMUM_CACHE_SIZE = 1024 * 1024 * 10; // Start at
    // 10MB??

    // Caches for download tasks
    private final LruCache<String, CommentList> commentListCache;
    private final LruCache<String, Bitmap> getImageCache;
    private final LruCache<String, String> getPOICache;

    // Queues of runnables required by tasks
    // es GetCommentList task
    private final BlockingQueue<Runnable> getCommentListRunnableQueue;
    // es GetComment task
    private final BlockingQueue<Runnable> getCommentsRunnableQueue;
    // es Post task
    private final BlockingQueue<Runnable> postImageRunnableQueue;
    private final BlockingQueue<Runnable> postRunnableQueue;
    private final BlockingQueue<Runnable> updateRunnableQueue;
    // es GetImage task
    private final BlockingQueue<Runnable> getImageRunnableQueue;
    private final BlockingQueue<Runnable> getThreadCommentsRunnableQueue;

    // get Point of Interest Task
    private final BlockingQueue<Runnable> getPOIRunnableQueue;

    // Queues of tasks this manager is responsible for
    private final Queue<GetCommentsTask> getCommentsTaskQueue;
    private final Queue<PostTask> postTaskQueue;
    private final Queue<GetImageTask> getImageTaskQueue;
    private final Queue<GetPOITask> getPOITaskQueue;
    private final Queue<GetThreadCommentsTask> getThreadCommentsTaskQueue;

    // Thread pools for all the possible threads, one pool per each runnable
    private final ThreadPoolExecutor getCommentListPool;
    private final ThreadPoolExecutor getCommentsPool;
    private final ThreadPoolExecutor postImagePool;
    private final ThreadPoolExecutor postPool;
    private final ThreadPoolExecutor updatePool;
    private final ThreadPoolExecutor getImagePool;
    private final ThreadPoolExecutor getThreadCommentsPool;
    private final ThreadPoolExecutor getPOIPool;

    private Context context;
    private Handler handler;
    private static ThreadManager instance = null;

    /**
     * Private constructor due to singleton pattern.
     */
    private ThreadManager() {
        commentListCache = new LruCache<String, CommentList>(MAXIMUM_CACHE_SIZE);
        getImageCache = new LruCache<String, Bitmap>(MAXIMUM_CACHE_SIZE);
        getPOICache = new LruCache<String, String>(MAXIMUM_CACHE_SIZE);

        getCommentListRunnableQueue = new LinkedBlockingQueue<Runnable>();
        getCommentsRunnableQueue = new LinkedBlockingQueue<Runnable>();
        postImageRunnableQueue = new LinkedBlockingQueue<Runnable>();
        postRunnableQueue = new LinkedBlockingQueue<Runnable>();
        updateRunnableQueue = new LinkedBlockingQueue<Runnable>();
        getImageRunnableQueue = new LinkedBlockingQueue<Runnable>();
        getThreadCommentsRunnableQueue = new LinkedBlockingQueue<Runnable>();
        getPOIRunnableQueue = new LinkedBlockingQueue<Runnable>();

        getCommentsTaskQueue = new LinkedBlockingQueue<GetCommentsTask>();
        postTaskQueue = new LinkedBlockingQueue<PostTask>();
        getImageTaskQueue = new LinkedBlockingQueue<GetImageTask>();
        getThreadCommentsTaskQueue = new LinkedBlockingQueue<GetThreadCommentsTask>();
        getPOITaskQueue = new LinkedBlockingQueue<GetPOITask>();

        getCommentListPool = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME,
                KEEP_ALIVE_TIME_UNIT, getCommentListRunnableQueue);
        getCommentsPool = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME,
                KEEP_ALIVE_TIME_UNIT, getCommentsRunnableQueue);
        postImagePool = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME,
                KEEP_ALIVE_TIME_UNIT, postImageRunnableQueue);
        postPool = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME, KEEP_ALIVE_TIME_UNIT,
                postRunnableQueue);
        updatePool = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME,
                KEEP_ALIVE_TIME_UNIT, updateRunnableQueue);
        getImagePool = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME,
                KEEP_ALIVE_TIME_UNIT, getImageRunnableQueue);
        getThreadCommentsPool = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME,
                KEEP_ALIVE_TIME_UNIT, getThreadCommentsRunnableQueue);
        getPOIPool = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME,
                KEEP_ALIVE_TIME_UNIT, getPOIRunnableQueue);

        handler = new Handler(Looper.getMainLooper()) {

            @Override
            public void handleMessage(Message inputMessage) {
                switch (inputMessage.what) {
                case POST_TASK_COMPLETE:
                    PostTask postTaskComplete = (PostTask) inputMessage.obj;
                    if (postTaskComplete.getDialog() != null) {
                        postTaskComplete.getDialog().dismiss();
                    }
                    ThreadComment threadComment = postTaskComplete.getThreadComment();
                    if (threadComment != null) {
                        if (!postTaskComplete.isEdit()) {
                            // Update the model and sort accordingly
                            ThreadList.addThread(threadComment);
                            SortUtil.sortThreads(PreferencesManager.getInstance().getThreadSort(),
                                    ThreadList.getThreads());
                        }
                        FragmentActivity activity = (FragmentActivity) context;
                        ThreadListFragment fragment = (ThreadListFragment) activity.getSupportFragmentManager()
                                .findFragmentByTag("threadListFrag");
                        if (fragment != null) {
                            fragment.finishReload();
                        }
                    }
                    break;

                case GET_THREADS_COMPLETE:
                    GetThreadCommentsTask threadTask = (GetThreadCommentsTask) inputMessage.obj;
                    threadTask.getFragment().finishReload();
                    recycleGetThreadCommentsTask(threadTask);
                    break;

                case GET_THREADS_FAILED:
                    GetThreadCommentsTask threadTaskFail = (GetThreadCommentsTask) inputMessage.obj;
                    threadTaskFail.getFragment().finishReload();
                    recycleGetThreadCommentsTask(threadTaskFail);
                    break;

                case GET_COMMENTS_COMPLETE:
                    GetCommentsTask task = (GetCommentsTask) inputMessage.obj;
                    task.getFragment().finishReload();
                    recycleCommentsTask(task);
                    break;

                case GET_COMMENTS_FAILED:
                    GetCommentsTask taskFail = (GetCommentsTask) inputMessage.obj;
                    taskFail.getFragment().finishReload();
                    recycleCommentsTask(taskFail);
                    break;

                case GET_COMMENT_LIST_RUNNING:
                    break;

                case GET_COMMENT_LIST_FAILED:
                    GetCommentsTask taskListFail = (GetCommentsTask) inputMessage.obj;
                    taskListFail.getFragment().finishReload();
                    recycleCommentsTask(taskListFail);
                    break;

                case GET_IMAGE_RUNNING:
                    GetImageTask imageTask = (GetImageTask) inputMessage.obj;
                    if (imageTask.getDialog() != null) {
                        imageTask.getDialog().show();
                    }
                    break;

                case GET_IMAGE_FAILED:
                    GetImageTask imageTaskFail = (GetImageTask) inputMessage.obj;
                    if (imageTaskFail.getDialog() != null) {
                        imageTaskFail.getDialog().dismiss();
                    }
                    recycleGetImageTask(imageTaskFail);
                    break;

                case GET_IMAGE_COMPLETE:
                    GetImageTask imageTaskComplete = (GetImageTask) inputMessage.obj;
                    if (imageTaskComplete.getDialog() != null) {
                        imageTaskComplete.getDialog().dismiss();
                    }
                    Bitmap bitmap = imageTaskComplete.getImageCache();
                    String id = imageTaskComplete.getId();
                    ImageView view = imageTaskComplete.getmImageWeakRef().get();
                    if (view != null) {
                        view.setImageBitmap(bitmap);
                    }
                    CacheManager.getInstance().serializeImage(bitmap, id);
                    recycleGetImageTask(imageTaskComplete);
                    break;

                case GET_POI_RUNNING:
                    GetPOITask poiTaskRunning = (GetPOITask) inputMessage.obj;
                    if (poiTaskRunning.getDialog() != null) {
                        poiTaskRunning.getDialog().show();
                    }
                    break;

                case GET_POI_COMPLETE:
                    GetPOITask poiTaskComplete = (GetPOITask) inputMessage.obj;
                    if (poiTaskComplete.getDialog() != null) {
                        poiTaskComplete.getDialog().dismiss();
                    }
                    if (poiTaskComplete.getMarker() != null) {
                        poiTaskComplete.getMarker().setSubDescription((poiTaskComplete.getPOICache()));
                        poiTaskComplete.getMarker().showInfoWindow();

                    }
                    poiTaskComplete.getLocation().setLocationDescription(poiTaskComplete.getPOICache());
                    recycleGetPOITask(poiTaskComplete);
                    break;

                case GET_POI_FAILED:
                    GetPOITask poiTaskFailed = (GetPOITask) inputMessage.obj;
                    if (poiTaskFailed.getDialog() != null) {
                        poiTaskFailed.getDialog().dismiss();
                    }
                    if (poiTaskFailed.getMarker() != null) {
                        poiTaskFailed.getMarker().setSubDescription(("Unknown Location"));
                        poiTaskFailed.getMarker().showInfoWindow();
                    }
                    poiTaskFailed.getLocation().setLocationDescription("Unknown Location");
                    recycleGetPOITask(poiTaskFailed);
                    break;

                case POST_GET_POI_RUNNING:
                    PostTask postPoiTaskRunning = (PostTask) inputMessage.obj;
                    if (postPoiTaskRunning.getDialog() != null) {
                        postPoiTaskRunning.getDialog().show();
                    }
                    break;

                case POST_GET_POI_COMPLETE:
                    PostTask postPoiTaskComplete = (PostTask) inputMessage.obj;
                    if (postPoiTaskComplete.getDialog() != null) {
                        postPoiTaskComplete.getDialog().setMessage("Posting to Server");
                    }
                    break;

                case POST_GET_POI_FAILED:
                    PostTask postPoiTaskFailed = (PostTask) inputMessage.obj;
                    if (postPoiTaskFailed.getDialog() != null) {
                        postPoiTaskFailed.getDialog().dismiss();
                    }
                    break;

                case UPDATE_FAILED:
                    PostTask postTaskUpdateFailed = (PostTask) inputMessage.obj;
                    if (postTaskUpdateFailed.getDialog() != null) {
                        postTaskUpdateFailed.getDialog().dismiss();
                    }
                    break;

                case POST_FAILED:
                    PostTask postTaskFailed = (PostTask) inputMessage.obj;
                    if (postTaskFailed.getDialog() != null) {
                        postTaskFailed.getDialog().dismiss();
                    }
                    break;

                case POST_RUNNING:
                    PostTask postTaskRun = (PostTask) inputMessage.obj;
                    if (postTaskRun.getDialog() != null && !postTaskRun.getDialog().isShowing()) {
                        postTaskRun.getDialog().show();
                    }
                    break;

                case POST_IMAGE_FAILED:
                    PostTask postTaskImageFailed = (PostTask) inputMessage.obj;
                    if (postTaskImageFailed.getDialog() != null) {
                        postTaskImageFailed.getDialog().dismiss();
                    }
                    break;

                default:
                    super.handleMessage(inputMessage);
                    break;
                }
            }
        };
    }

    /**
     * Generates an instance of the ThreadManager if it does not exist.
     * 
     * @param context
     *            the context
     */
    public static void generateInstance(Context context) {
        instance = new ThreadManager();
        instance.context = context;
    }

    /**
     * Start the get image from elasticSearch task, initialize a task instance
     * and add the appropriate runnable to the thread pool
     * 
     * @param id
     *            the image id under which the bitmap is stored on es
     */
    public static GetImageTask startGetImage(String id, ImageView imageView, ProgressDialog dialog) {
        GetImageTask task = instance.getImageTaskQueue.poll();
        if (task == null) {
            task = new GetImageTask();
        }
        task.initGetImageTask(instance, id, imageView, dialog);
        task.setImageCache(instance.getImageCache.get(id));
        instance.getImagePool.execute(task.getGetImageRunnable());
        return task;
    }

    /**
     * Start the get ThreadComments from elasticSearch task, initialize a task
     * instance and add the appropriate runnable to the thread pool
     * 
     * @param fragment
     *            the ThreadListFragment that will be displaying the list
     */
    public static GetThreadCommentsTask startGetThreadComments(ThreadListFragment fragment) {
        GetThreadCommentsTask task = instance.getThreadCommentsTaskQueue.poll();
        if (task == null) {
            task = new GetThreadCommentsTask();
        }
        task.initGetThreadCommentsTask(instance, fragment);
        instance.getThreadCommentsPool.execute(task.getGetThreadCommentsRunnable());
        return task;
    }

    /**
     * Start the get comments from elasticSearch task, initialize a task
     * instance and add the appropriate runnable to the thread pool.
     * 
     * @param fragment
     *            the ThreadViewFragment displaying the ThreadComment
     * @param threadIndex
     *            id of the ThreadComment for which to get Comments
     */
    public static GetCommentsTask startGetComments(ThreadViewFragment fragment, int threadIndex) {
        GetCommentsTask task = instance.getCommentsTaskQueue.poll();
        if (task == null) {
            task = new GetCommentsTask();
        }
        task.initCommentsTask(instance, fragment, threadIndex);
        task.setCommentListCache(instance.commentListCache.get(ThreadList.getThreads().get(threadIndex).getId()));
        instance.getCommentListPool.execute(task.getGetCommentListRunnable());
        return task;
    }

    /**
     * Start the post comment to elasticSearch task, initialize a task instance
     * and add the appropriate runnable to the thread pool
     * 
     * @param comment
     *            comment object to be posted
     * @param title
     *            title of the threadComment, if it is a threadComment. if it is
     *            a Comment, not a threadComment, the title field is null
     * @param location
     *            the GeoLocation of the post
     * @param dialog
     *            a ProgressDialog in the fragment to display task progress
     * 
     */
    public static PostTask startPost(Comment comment, String title, GeoLocation location, ProgressDialog dialog,
            boolean isEdit) {
        PostTask task = instance.postTaskQueue.poll();
        if (task == null) {
            task = new PostTask();
        }
        task.initPostTask(instance, comment, title, location, dialog, isEdit);
        if (location.getLocationDescription() == null) {
            task.setPOICache(instance.getPOICache.get(location.getLocation().toString()));
            instance.getPOIPool.execute(task.getGetPOIRunnable());
        } else {
            instance.postPool.execute(task.getPostRunnable());
        }
        return task;
    }

    /**
     * Start the get POI from elasticSearch task, initialize a task instance and
     * add the appropriate runnable to the thread pool
     * 
     * @param location
     *            the GeoLocation to find the POI from
     * @param dialog
     *            a ProgressDialog in a fragment to display task progress
     * @param marker
     *            an OSMDroid marker to display POI information
     */
    public static GetPOITask startGetPOI(GeoLocation location, ProgressDialog dialog, Marker marker) {
        GetPOITask task = instance.getPOITaskQueue.poll();
        if (task == null) {
            task = new GetPOITask();
        }
        task.initGetPOITask(instance, location, dialog, marker);
        task.setPOICache(instance.getPOICache.get(location.getLocation().toString()));
        instance.getPOIPool.execute(task.getGetPOIRunnable());
        return task;
    }

    /**
     * Handles the possible states of the get POI task. Passes the state to the
     * Handler that runs on the UI thread.
     * 
     * @param task
     *            the get POI task
     * @param state
     *            the state
     */
    public void handleGetPOIState(GetPOITask task, int state) {
        switch (state) {
        case GET_POI_COMPLETE:
            instance.handler.obtainMessage(state, task).sendToTarget();
            break;
        case GET_POI_RUNNING:
            instance.handler.obtainMessage(state, task).sendToTarget();
            break;
        case GET_POI_FAILED:
            instance.handler.obtainMessage(state, task).sendToTarget();
            break;
        default:
            instance.handler.obtainMessage(state, task).sendToTarget();
            break;
        }
    }

    /**
     * Handle the possible states of the get comment task. When complete, passes
     * the state to the Handler that runs on the UI thread.
     * 
     * @param task
     *            the get comments task
     * @param state
     *            the state
     */
    public void handleGetCommentsState(GetCommentsTask task, int state) {
        switch (state) {
        case GET_COMMENT_LIST_COMPLETE:
            instance.getCommentsPool.execute(task.getGetCommentsRunnable());
            break;
        case GET_COMMENTS_COMPLETE:
            instance.handler.obtainMessage(state, task).sendToTarget();
            break;
        case GET_COMMENT_LIST_RUNNING:
            instance.handler.obtainMessage(state, task).sendToTarget();
            break;
        case GET_COMMENT_LIST_FAILED:
            instance.handler.obtainMessage(state, task).sendToTarget();
            break;
        case GET_COMMENTS_FAILED:
            instance.handler.obtainMessage(state, task).sendToTarget();
            break;
        default:
            instance.handler.obtainMessage(state, task).sendToTarget();
            break;
        }
    }

    /**
     * Handle the possible states of the get thread comments task. Passes the
     * state to the Handler that runs on the UI thread.
     * 
     * @param task
     *            the get thread comments task
     * @param state
     *            the state
     */
    public void handleGetThreadCommentsState(GetThreadCommentsTask task, int state) {
        switch (state) {
        case GET_THREADS_RUNNING:
            instance.handler.obtainMessage(state, task).sendToTarget();
            break;
        case GET_THREADS_COMPLETE:
            instance.handler.obtainMessage(state, task).sendToTarget();
            break;
        case GET_THREADS_FAILED:
            instance.handler.obtainMessage(state, task).sendToTarget();
            break;
        default:
            instance.handler.obtainMessage(state, task).sendToTarget();
            break;
        }
    }

    /**
     * Handle the possible states of the getImage task. Passes the state to the
     * Handler that runs on the UI thread.
     * 
     * @param task
     *            the get image task
     * @param state
     *            the state
     */
    public void handleGetImageState(GetImageTask task, int state) {
        switch (state) {
        case GET_IMAGE_COMPLETE:
            instance.handler.obtainMessage(state, task).sendToTarget();
            break;
        case GET_IMAGE_RUNNING:
            instance.handler.obtainMessage(state, task).sendToTarget();
            break;
        case GET_IMAGE_FAILED:
            instance.handler.obtainMessage(state, task).sendToTarget();
            break;
        default:
            instance.handler.obtainMessage(state, task).sendToTarget();
            break;
        }
    }

    /**
     * Handle the possible states of the Post task. Once post is complete,
     * obtains the point of interest of the post. If the post contains an image,
     * start the Image runnable, which posts the attached image to
     * elasticSearch. If not, or after the image is complete, start the update
     * runnable, which updates the commentList on elasticSearch. Passes needed
     * task states to the handler running on the UI thread to do UI updates.
     * 
     * @param task
     *            the post task
     * @param state
     *            the state
     */
    public void handlePostState(PostTask task, int state) {
        switch (state) {
        case POST_COMPLETE:
            if (task.getComment().hasImage()) {
                instance.postImagePool.execute(task.getImageRunnable());
            } else if (task.getTitle() == null) {
                instance.updatePool.execute(task.getUpdateRunnable());
            } else {
                instance.handler.obtainMessage(POST_TASK_COMPLETE, task).sendToTarget();
            }
            break;
        case POST_IMAGE_COMPLETE:
            if (task.getTitle() == null) {
                instance.updatePool.execute(task.getUpdateRunnable());
            } else {
                instance.handler.obtainMessage(POST_TASK_COMPLETE, task).sendToTarget();
            }
            break;
        case POST_RUNNING:
            instance.handler.obtainMessage(state, task).sendToTarget();
            break;
        case POST_TASK_COMPLETE:
            instance.handler.obtainMessage(state, task).sendToTarget();
            break;
        case POST_GET_POI_COMPLETE:
            instance.handler.obtainMessage(state, task).sendToTarget();
            instance.postPool.execute(task.getPostRunnable());
            break;
        case POST_GET_POI_FAILED:
            instance.handler.obtainMessage(state, task).sendToTarget();
            instance.postPool.execute(task.getPostRunnable());
            break;
        case UPDATE_FAILED:
            instance.handler.obtainMessage(state, task).sendToTarget();
            break;
        case POST_FAILED:
            instance.handler.obtainMessage(state, task).sendToTarget();
            break;
        case POST_IMAGE_FAILED:
            instance.handler.obtainMessage(state, task).sendToTarget();
            break;
        default:
            instance.handler.obtainMessage(state, task).sendToTarget();
            break;
        }
    }

    /**
     * Recycles a get comments task for reuse.
     * 
     * @param task
     *            the task
     */
    void recycleCommentsTask(GetCommentsTask task) {
        task.recycle();
        instance.getCommentsTaskQueue.offer(task);
    }

    /**
     * Recycles a get image task for reuse.
     * 
     * @param task
     *            the task
     */
    void recycleGetImageTask(GetImageTask task) {
        task.recycle();
        instance.getImageTaskQueue.offer(task);
    }

    /**
     * Recycles a post task for reuse.
     * 
     * @param task
     *            the task
     */
    void recyclePostTask(PostTask task) {
        task.recycle();
        instance.postTaskQueue.offer(task);
    }

    /**
     * Recycles a get POI task for reuse.
     * 
     * @param task
     *            the task
     */
    void recycleGetPOITask(GetPOITask task) {
        task.recycle();
        instance.getPOITaskQueue.offer(task);
    }

    /**
     * Recycles a get thread comments task for reuse.
     * 
     * @param task
     *            the task
     */
    void recycleGetThreadCommentsTask(GetThreadCommentsTask task) {
        task.recycle();
        instance.getThreadCommentsTaskQueue.offer(task);
    }
}