Android Open Source - com.elsewhat.android.slideshow Async Read Queue






From Project

Back to project page com.elsewhat.android.slideshow.

License

The source code is released under:

Copyright (C) 2012 Dagfinn Parnas <dagfinn.parnas@gmail.com> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Sof...

If you think the Android project com.elsewhat.android.slideshow listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.elsewhat.android.slideshow.api;
//from   www.  j  av a  2  s.  c  o  m
import java.util.ArrayList;
import java.util.EmptyStackException;
import java.util.Iterator;
import java.util.Stack;

import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;

/**
 * Class which implements a Last-In/First-Out queue for operations that require background processing and an update to the UI thread
 * 
 * My usage is to read large photos from the file system
 * 
 * @author dagfinn.parnas
 */
public class AsyncReadQueue<T> {  
  protected static final String LOG_PREFIX="Slideshow PhotoIOQueue";
  //if the tasks can be processed in parallel (for example http), increase this to 2 or more
  protected int numberOfThreads=1;
  //that workers
  protected ArrayList<ReaderTask>  readerTasks;
  
  Context context;
  //stack is synchronized
  Stack<AsyncQueueableObject> queuedObjects;
  AsyncQueueListener listener;

  
  /**
   * Constructor 
   * @param context
   * @param listener The listener which will be notified when a task has completed
   */
  public AsyncReadQueue(Context context,AsyncQueueListener listener) {
    super();
    this.context = context;
    this.listener=listener;
    
    //lets make sure the List is synchronized
    queuedObjects= new Stack<AsyncQueueableObject>();
  }
  
  /**
   * Listener which is notified when the read is finished is complete or retrieved error
   */
  public interface AsyncQueueListener {
    /*These methods should be synchronized when implemented*/
    void onAsyncReadComplete (AsyncQueueableObject queueableObject);
  }
  
  
  
  /**
   * Add an object to the queue. 
   * Will trigger the worker tasks to start if they are not running 
   *  
   * @param queueObject
   */
  public void add(AsyncQueueableObject queueObject){
    queuedObjects.push(queueObject);
    
    if(!hasRunningTasks()){
      if(queuedObjects.size()>1){
        Log.d(LOG_PREFIX, "Added new queued object, queue size="+queuedObjects.size()+". New tasks triggered"+ queueObject );
      }
      
      processQueue();
    }else {
      Log.d(LOG_PREFIX, "Added new queued object, queue size="+queuedObjects.size()+". Processed by already running tasks "+ queueObject );
    }

  }
  
  protected void processQueue(){
    //if this is called, we assume there hasRunningTasks()==false has been called first
    //Log.i(LOG_PREFIX, "Starting new reader tasks to process queue" );
    readerTasks= new ArrayList<ReaderTask>(numberOfThreads);
    for (int i = 0; i < numberOfThreads; i++) {
      ReaderTask readerTask = new ReaderTask(i);
      readerTasks.add(readerTask);
      readerTask.execute();  
    }
  }
  
  protected boolean hasRunningTasks(){
    if(readerTasks==null || readerTasks.size()==0){
      return false;
    }
    boolean hasActiveTask= false;
    for (Iterator<ReaderTask> iterator = readerTasks.iterator(); iterator.hasNext();) {
      ReaderTask readerTask = iterator.next();
      if(readerTask.isFinished()==false){
        hasActiveTask=true;
      }
    }
    if(hasActiveTask){
      return true;
    }else {
      return false;
    }
  }
  
  /**
   * Stops the ongoing tasks. Any queued objects are removed.
   * To start it again, a new call to add method must be made
   * 
   */
  public void stop(){
    for (Iterator<ReaderTask> iterator = readerTasks.iterator(); iterator.hasNext();) {
      ReaderTask readerTask = iterator.next();
      if(readerTask.isFinished()==false){
        Log.i(LOG_PREFIX, "Stopping ongoing async reader task");
        readerTask.cancel(true);
      }
    }
    queuedObjects.clear();
  
  }
  
  
    /**
     * AsyncTask which represent the worker threads 
     * 
     */
    public class ReaderTask extends AsyncTask<Void, AsyncQueueableObject, Void> {
      boolean hasError=false;


    Throwable throwable;
      String userErrorMsg;
      int threadId;
      boolean isFinished=false;
      T result;
      
      public ReaderTask(int threadId){
        this.threadId=threadId;
        isFinished=false;
      }
      
    @Override
    protected Void doInBackground(Void... arg0) {
      //loop which continues until the queue/stack is empty
      while(!queuedObjects.isEmpty()){
        if(isCancelled()){
          Log.d(LOG_PREFIX,"Async task was cancelled");
          return null;
        }
        AsyncQueueableObject asyncObject=null; 
        try {
          asyncObject= queuedObjects.pop();
        }catch (EmptyStackException e) {
          //can happen if we have more than one running ReaderTask
          return null;
        }
        if(asyncObject!=null){
          //process the async operation
          //this is the time consuming task
          asyncObject.performOperation();
          
          //publish progress will cause the handleOperationResult to be run on the UI thread
          publishProgress(asyncObject);        
        }
  
      }
      isFinished=true;
      return null;
    }
    
    
    /** 
     * Called when one of the queue objects have performmed the operation
     * 
     * @see android.os.AsyncTask#onProgressUpdate(Progress[])
     */
    @Override
    protected void onProgressUpdate(AsyncQueueableObject... asyncObjects) {
      if(asyncObjects.length==1){
        AsyncQueueableObject asyncObject = asyncObjects[0];
        asyncObject.handleOperationResult();
        listener.onAsyncReadComplete(asyncObject);    
      }else {
        Log.w(LOG_PREFIX, "Unexpected number of DownloadableObject in onProgressUpdate:"+asyncObjects.length );
      }
    }

    protected boolean isFinished(){
      return isFinished;
    }

    @Override
    protected void onPostExecute(Void result) {
      //isFinished=true;
      //Log.i(LOG_PREFIX, "Async reader task " + threadId + " completed" );
      
      //handle a case where a new queued object has been added at the same time we are finished this task
      if(queuedObjects!=null && queuedObjects.size()>0 && hasRunningTasks()==false){
        //Log.w(LOG_PREFIX, "Queue not empty at end of run. Restarting async reader tasks"  );
        processQueue();
      }
    }
    
      /* (non-Javadoc)
     * @see android.os.AsyncTask#onCancelled()
     */
    @Override
    protected void onCancelled() {
      Log.i(LOG_PREFIX, "Download task stopped");
      super.onCancelled();
    }
    }
  
}




Java Source Code List

com.elsewhat.android.slideshow.activities.ChromecastAddin.java
com.elsewhat.android.slideshow.activities.ISlideshowInstance.java
com.elsewhat.android.slideshow.activities.SlideshowActivity.java
com.elsewhat.android.slideshow.activities.SlideshowDreamService.java
com.elsewhat.android.slideshow.activities.SlideshowPreferences.java
com.elsewhat.android.slideshow.api.Analytics.java
com.elsewhat.android.slideshow.api.AndroidUtils.java
com.elsewhat.android.slideshow.api.AsyncQueueableObject.java
com.elsewhat.android.slideshow.api.AsyncReadQueue.java
com.elsewhat.android.slideshow.api.CustomGallery.java
com.elsewhat.android.slideshow.api.DeletablePreference.java
com.elsewhat.android.slideshow.api.DownloadableObject.java
com.elsewhat.android.slideshow.api.FileDownloader.java
com.elsewhat.android.slideshow.api.FileUtils.java
com.elsewhat.android.slideshow.api.FlingKeyEvent.java
com.elsewhat.android.slideshow.api.ImageAdapter.java
com.elsewhat.android.slideshow.api.QueueablePhotoObject.java
com.elsewhat.android.slideshow.api.ReadOnlyPreference.java
com.elsewhat.android.slideshow.api.SlideshowBackend.java
com.elsewhat.android.slideshow.api.SlideshowPhotoCached.java
com.elsewhat.android.slideshow.api.SlideshowPhotoDrawable.java
com.elsewhat.android.slideshow.api.SlideshowPhoto.java
com.elsewhat.android.slideshow.backend.FlickrPublicSetBackend.java
com.elsewhat.android.slideshow.backend.OPMLBackend.java
com.elsewhat.android.slideshow.backend.SmugMugRecentBackend.java