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

org.jdeferred.android.AndroidDeferredManager Maven / Gradle / Ivy

There is a newer version: 1.2.4
Show newest version
/*******************************************************************************
 * Copyright 2013 Ray Tsang
 * 
 * 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 org.jdeferred.android;

import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;

import org.jdeferred.DeferredFutureTask;
import org.jdeferred.DeferredManager;
import org.jdeferred.Promise;
import org.jdeferred.impl.DefaultDeferredManager;
import org.jdeferred.multiple.MasterDeferredObject;
import org.jdeferred.multiple.MasterProgress;
import org.jdeferred.multiple.MultipleResults;
import org.jdeferred.multiple.OneReject;

import android.annotation.SuppressLint;
import android.os.AsyncTask;
import android.os.Build;

/**
 * This DeferredManager is designed to execute deferred tasks in the background,
 * but also executes callbacks (e.g., done, fail, progress, and always) in the UI thread.
 * This is important because only UI thread executions can update UI elements!
 * 
 * You can use {@link DeferredAsyncTask} to write in the more familiar Android {@link AsyncTask} API
 * and still being able to take advantage of {@link Promise} chaining.
 * 
 * Even more powerful, you can also use {@link Promise}, {@link Runnable}, {@link Callable},
 * and any other types supported by {@link DeferredManager}.  This implementation will hand off
 * callbacks to UI thread automatically.
 * 
 * @author Ray Tsang
 *
 */
public class AndroidDeferredManager extends DefaultDeferredManager {
	private static Void[] EMPTY_PARAMS = new Void[]{};
	
	public AndroidDeferredManager() {
		super();
	}

	public AndroidDeferredManager(ExecutorService executorService) {
		super(executorService);
	}
	
	/**
	 * Return a {@link Promise} for the {@link DeferredAsyncTask}.
	 * This can also automatically execute the task in background depending on 
	 * {@link DeferredAsyncTask#getStartPolicy()} and/or {@link DefaultDeferredManager#isAutoSubmit()}.
	 * 
	 * Prior to Android Honeycomb (API 11), {@link AsyncTask#execute(Object...)} would be
	 * executed in the background concurrently in a thread pool, but starting with Honeycomb,
	 * {@link AsyncTask#execute(Object...)} will execute the background task serially.  To achieve
	 * older behavior, developer need to use {@link AsyncTask#executeOnExecutor(java.util.concurrent.Executor, Object...)}.
	 * 
	 * This method will always execute task in background concurrently if the task should be executed/submitted automatically.
	 * Hence, when using this method on Android API prior to Honeycomb, the task will be executed 
	 * using {@link AsyncTask#execute(Object...)}.  On Android API version starting from Honeycomb,
	 * this method will execute with @see {@link AsyncTask#executeOnExecutor(java.util.concurrent.Executor, Object...)}
	 * using {@link Executor} from {@link #getExecutorService()}
	 * 
	 * @param task {@link DeferredAsyncTask} to run in the background
	 * @return {@link DeferredAsyncTask#promise()}
	 * @see {@link AsyncTask#execute(Object...)}
	 * @see {@link AsyncTask#executeOnExecutor(java.util.concurrent.Executor, Object...)}
	 */
	@SuppressLint("NewApi")
	public  Promise when(
			DeferredAsyncTask task) {
		
		if (task.getStartPolicy() == StartPolicy.AUTO 
				|| (task.getStartPolicy() == StartPolicy.DEFAULT && isAutoSubmit())) {
			
			if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
				task.executeOnExecutor(getExecutorService(), EMPTY_PARAMS);
			} else {
				task.execute(EMPTY_PARAMS);
			}
		}
		
		return task.promise();
	}
	
	@SuppressWarnings("rawtypes")
	public Promise when(
			DeferredAsyncTask ... tasks) {
		assertNotEmpty(tasks);
		
		Promise[] promises = new Promise[tasks.length];
		
		for (int i = 0; i < tasks.length; i++) {
			promises[i] = when(tasks[i]);
		}
		
		return when(promises);
	}
	
	@SuppressWarnings("rawtypes")
    public Promise when(AndroidExecutionScope scope,
            DeferredAsyncTask ... tasks) {
        assertNotEmpty(tasks);
        Promise[] promises = new Promise[tasks.length];
        for (int i = 0; i < tasks.length; i++) {
            promises[i] = when(tasks[i]);
        }
        return when(scope, promises);
    }

	/**
	 * Wrap with {@link AndroidDeferredObject} so that callbacks can be executed in UI thread.
	 * This method is called by a number of other when(...) methods.  Effectively, at least these
	 * methods will also be wrapped by {@link AndroidDeferredObject}:
	 * 
    *
  • {@link DeferredManager#when(Callable)}
  • *
  • {@link DeferredManager#when(Callable...)}
  • *
  • {@link DeferredManager#when(Runnable)}
  • *
  • {@link DeferredManager#when(Runnable..)}
  • *
  • {@link DeferredManager#when(java.util.concurrent.Future)}
  • *
  • {@link DeferredManager#when(java.util.concurrent.Future...)}
  • *
  • {@link DeferredManager#when(org.jdeferred.DeferredRunnable...)}
  • *
  • {@link DeferredManager#when(org.jdeferred.DeferredRunnable)}
  • *
  • {@link DeferredManager#when(org.jdeferred.DeferredCallable...)}
  • *
  • {@link DeferredManager#when(org.jdeferred.DeferredCallable)}
  • *
  • {@link DeferredManager#when(DeferredFutureTask...)}
  • *
*/ @Override public Promise when(DeferredFutureTask task) { return new AndroidDeferredObject(super.when(task)).promise(); } /** * If a non-Android friendly promise is passed in, wrap it with {@link AndroidDeferredObject} * so that callbacks can be executed in the UI thread. */ @Override public Promise when(Promise promise) { if (promise instanceof AndroidDeferredObject) { return promise; } return new AndroidDeferredObject(promise).promise(); } /** * If a non-Android friendly promise is passed in, wrap it with {@link AndroidDeferredObject} * so that callbacks can be executed in the corresponding execution scope. * @param scope Whether to execute in UI thread or Background thread * @param promise A promise * @return A promise wrapped in @{link AndroidDeferredObject} */ public Promise when(Promise promise, AndroidExecutionScope scope) { if (promise instanceof AndroidDeferredObject) { return promise; } return new AndroidDeferredObject(promise, scope).promise(); } /** * Wraps {@link MasterDeferredObject} with {@link AndroidDeferredObject} so that callbacks can * be executed in UI thread. */ @SuppressWarnings({ "rawtypes" }) @Override public Promise when(Promise... promises) { return new AndroidDeferredObject (super.when(promises)).promise(); } /** * Wraps {@link MasterDeferredObject} with with {@link AndroidDeferredObject} * so that callbacks can be executed in the corresponding execution scope. * @return A promise wrapped in @{link AndroidDeferredObject} */ @SuppressWarnings({ "rawtypes" }) public Promise when(AndroidExecutionScope scope, Promise... promises) { return new AndroidDeferredObject (super.when(promises), scope).promise(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy