All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.coolerfall.download.DownloadRequestQueue Maven / Gradle / Ivy

package com.coolerfall.download;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.atomic.AtomicInteger;

import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import com.coolerfall.download.DownloadRequest.DownloadState;

/**
 * Download request queue, this is designed according to RequestQueue in Andoird-Volley.
 * 
 * @author Vincent Cheung
 * @since  Nov. 24, 2014
 */
public class DownloadRequestQueue {
	private static final String TAG = DownloadRequestQueue.class.getSimpleName();
	
	/** the capacity of download request queue */
	private static final int CAPACITY = 20;
	
	/** the default number of download dispatcher threads */
	private static final int DEFAULT_DOWNLOAD_THREAD_POOL_SIZE = 3;
	
	/**
	 * The set of all requests currently being processed by this DownloadQueue. A Request
	 * will be in this set if it is waiting in any queue or currently being processed by
	 * any dispatcher.
	 */
	private final Set mCurrentRequests = new HashSet<>();
	
	/** the queue of download request */
	private PriorityBlockingQueue mDownloadQueue = 
			new PriorityBlockingQueue<>(CAPACITY);
	
	/** download dispatchers */
	private DownloadDispatcher[] mDispatchers;
	
	/** download callback delivery */
	private DownloadDelivery mDelivery;

	/** used for generating monotonically-increasing sequence numbers for requests */
	private AtomicInteger mSequenceGenerator = new AtomicInteger();
	
	/**
	 * Default download reuqest queue.
	 */
	public DownloadRequestQueue() {
		this(DEFAULT_DOWNLOAD_THREAD_POOL_SIZE);
	}

	/**
	 * Create the download dispatchers according to pool size.
	 */
	public DownloadRequestQueue(int threadPoolSize) {
		if (threadPoolSize < 1 || threadPoolSize > 5) {
			threadPoolSize = DEFAULT_DOWNLOAD_THREAD_POOL_SIZE;
		}
		
		mDispatchers = new DownloadDispatcher[threadPoolSize];
		mDelivery = new DownloadDelivery(new Handler(Looper.getMainLooper()));
	}

	/**
	 * Starts the dispatchers in this queue.
	 */
	protected void start() {
		/* make sure any currently running dispatchers are stopped */
		stop();
		
		/* create the download dispatcher and start it. */
		for (int i = 0; i < mDispatchers.length; i ++) {
			DownloadDispatcher dispatcher = new DownloadDispatcher(mDownloadQueue, mDelivery);
			mDispatchers[i] = dispatcher;
			dispatcher.start();
		}
	}
	
	/**
	 * Stops the download dispatchers.
	 */
	protected void stop() {
		for (DownloadDispatcher dispatcher : mDispatchers) {
			if (dispatcher != null) {
				dispatcher.quit();
			}
		}
	}
	
	/**
	 * Add download request to the download request queue.
	 * 
	 * @param request download request
	 */
	protected void add(DownloadRequest request) {
		/* if the request is downloading, do nothing */
		if (query(request.getDownloadId()) != DownloadState.INVALID) {
			Log.i(TAG, "the download requst is in downloading");
			return;
		}
		
		/* tag the request as belonging to this queue */
		request.setDownloadQueue(this);
		/* add it to the set of current requests */
		synchronized (mCurrentRequests) {
			mCurrentRequests.add(request);
		}
		
		/* process requests in the order they are added in */
		mDownloadQueue.add(request);
	}
	
	/**
	 * Cancel a download in progress.
	 * 
	 * @param  downloadId download id
	 * @return            true if download has canceled, otherwise return false
	 */
	protected boolean cancel(int downloadId) {
		synchronized (mCurrentRequests) {
			for (DownloadRequest request : mCurrentRequests) {
				if (request.getDownloadId() == downloadId) {
					request.cancel();
					return true;
				}
			}
		}
		
		return false;
	}
	
	/**
	 * Cancel all the download.
	 */
	protected void cancelAll() {
		synchronized (mCurrentRequests) {
			for (DownloadRequest request : mCurrentRequests) {
				request.cancel();
			}
		}
		
		mCurrentRequests.clear();
	}
	
	/**
	 * Get the downloading task size.
	 * 
	 * @return task size
	 */
	protected int getDownloadingSize() {
		return mCurrentRequests.size();
	}
	
	/**
	 * To check if the request is downloading according to download id.
	 *
	 * @param  downloadId download id
	 * @return            true if the request is downloading, otherwise return false
	 */
	protected DownloadState query(int downloadId) {
		synchronized (mCurrentRequests) {
			for (DownloadRequest request : mCurrentRequests) {
				if (request.getDownloadId() == downloadId) {
					return request.getDownloadState();
				}
			}
		}
		
		return DownloadState.INVALID;
	}

	/**
	 * Gets a sequence number.
	 */
	public int getSequenceNumber() {
		return mSequenceGenerator.incrementAndGet();
	}
	
	/**
	 * The download has finished and remove from set.
	 * 
	 * @param request download reqeust
	 */
	protected void finish(DownloadRequest request) {
		synchronized (mCurrentRequests) {
			mCurrentRequests.remove(request);
		}
	}
	
	/**
	 * Release all the resource.
	 */
	protected void release() {
		/* release current download request */
		cancelAll();

		/* release download queue */
		if (mDownloadQueue != null) {
			mDownloadQueue = null;
		}
		
		/* release dispathcers */
		if (mDispatchers != null) {
			stop();
			
			for (int i = 0; i < mDispatchers.length; i ++) {
				mDispatchers[i] = null;
			}
			
			mDispatchers = null;
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy