All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.gh.bmd.jrt.android.v4.routine.DefaultAndroidRoutine Maven / Gradle / Ivy
/*
* 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 com.gh.bmd.jrt.android.v4.routine;
import android.content.Context;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import com.gh.bmd.jrt.android.builder.AndroidRoutineBuilder.CacheStrategy;
import com.gh.bmd.jrt.android.builder.AndroidRoutineBuilder.ClashResolution;
import com.gh.bmd.jrt.android.invocation.AndroidInvocation;
import com.gh.bmd.jrt.android.routine.AndroidRoutine;
import com.gh.bmd.jrt.android.runner.Runners;
import com.gh.bmd.jrt.builder.RoutineConfiguration;
import com.gh.bmd.jrt.builder.RoutineConfiguration.OrderType;
import com.gh.bmd.jrt.common.InvocationException;
import com.gh.bmd.jrt.common.InvocationInterruptedException;
import com.gh.bmd.jrt.common.RoutineException;
import com.gh.bmd.jrt.invocation.Invocation;
import com.gh.bmd.jrt.log.Logger;
import com.gh.bmd.jrt.routine.AbstractRoutine;
import com.gh.bmd.jrt.runner.Execution;
import java.lang.ref.WeakReference;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* Routine implementation delegating to Android loaders the asynchronous processing.
*
* Created by davide on 1/10/15.
*
* @param the input data type.
* @param the output data type.
*/
class DefaultAndroidRoutine extends AbstractRoutine
implements AndroidRoutine {
private final CacheStrategy mCacheStrategy;
private final ClashResolution mClashResolution;
private final Constructor extends AndroidInvocation > mConstructor;
private final WeakReference mContext;
private final int mInvocationId;
private final OrderType mOrderType;
/**
* Constructor.
*
* @param configuration the routine configuration.
* @param context the context reference.
* @param invocationId the invocation ID.
* @param resolution the clash resolution type.
* @param cacheStrategy the result cache type.
* @param constructor the invocation constructor.
* @throws java.lang.IllegalArgumentException if at least one of the parameter is invalid.
* @throws java.lang.NullPointerException if any of the specified non-null parameter is
* null.
*/
@SuppressWarnings("ConstantConditions")
DefaultAndroidRoutine(@Nonnull final RoutineConfiguration configuration,
@Nonnull final WeakReference context, final int invocationId,
@Nullable final ClashResolution resolution, @Nullable final CacheStrategy cacheStrategy,
@Nonnull final Constructor extends AndroidInvocation > constructor) {
super(configuration);
if (context == null) {
throw new NullPointerException("the context must not be null");
}
if (constructor == null) {
throw new NullPointerException("the invocation constructor must not be null");
}
mContext = context;
mInvocationId = invocationId;
mClashResolution = (resolution == null) ? ClashResolution.ABORT_THAT_INPUT : resolution;
mCacheStrategy = (cacheStrategy == null) ? CacheStrategy.CLEAR : cacheStrategy;
mConstructor = constructor;
mOrderType = configuration.getOutputOrderOr(null);
}
@Override
public void purge() {
super.purge();
final WeakReference context = mContext;
if (context.get() != null) {
final Class extends AndroidInvocation > invocationClass =
mConstructor.getDeclaringClass();
Runners.mainRunner().run(new PurgeExecution(context, mInvocationId, invocationClass), 0,
TimeUnit.MILLISECONDS);
}
}
@Nonnull
@Override
protected Invocation convertInvocation(final boolean async,
@Nonnull final Invocation invocation) {
try {
invocation.onDestroy();
} catch (final InvocationInterruptedException e) {
throw e;
} catch (final Throwable t) {
getLogger().wrn(t, "ignoring exception while destroying invocation instance");
}
return newInvocation(async);
}
@Nonnull
@Override
protected Invocation newInvocation(final boolean async) {
final Logger logger = getLogger();
if (async) {
return new LoaderInvocation (mContext, mInvocationId, mClashResolution,
mCacheStrategy, mConstructor, mOrderType,
logger);
}
final Object context = mContext.get();
if (context == null) {
throw new IllegalStateException("the routine context has been destroyed");
}
final Context appContext;
if (context instanceof FragmentActivity) {
final FragmentActivity activity = (FragmentActivity) context;
appContext = activity.getApplicationContext();
} else if (context instanceof Fragment) {
final Fragment fragment = (Fragment) context;
appContext = fragment.getActivity().getApplicationContext();
} else {
throw new IllegalArgumentException(
"invalid context type: " + context.getClass().getCanonicalName());
}
try {
final Constructor extends AndroidInvocation > constructor =
mConstructor;
logger.dbg("creating a new instance of class: %s", constructor.getDeclaringClass());
final AndroidInvocation invocation = constructor.newInstance();
invocation.onContext(appContext);
return invocation;
} catch (final InvocationTargetException e) {
logger.err(e, "error creating the invocation instance");
throw new InvocationException(e.getCause());
} catch (final RoutineException e) {
logger.err(e, "error creating the invocation instance");
throw e;
} catch (final Throwable t) {
logger.err(t, "error creating the invocation instance");
throw new InvocationException(t);
}
}
public void purge(@Nullable final INPUT input) {
final WeakReference context = mContext;
if (context.get() != null) {
final Class extends AndroidInvocation > invocationClass =
mConstructor.getDeclaringClass();
final List inputList = Collections.singletonList(input);
Runners.mainRunner()
.run(new PurgeInputsExecution (context, mInvocationId, invocationClass,
inputList), 0, TimeUnit.MILLISECONDS);
}
}
public void purge(@Nullable final INPUT... inputs) {
final WeakReference context = mContext;
if (context.get() != null) {
final Class extends AndroidInvocation > invocationClass =
mConstructor.getDeclaringClass();
final List inputList =
(inputs == null) ? Collections. emptyList() : Arrays.asList(inputs);
Runners.mainRunner()
.run(new PurgeInputsExecution (context, mInvocationId, invocationClass,
inputList), 0, TimeUnit.MILLISECONDS);
}
}
public void purge(@Nullable final Iterable extends INPUT> inputs) {
final WeakReference context = mContext;
if (context.get() != null) {
final List inputList;
if (inputs == null) {
inputList = Collections.emptyList();
} else {
inputList = new ArrayList ();
for (final INPUT input : inputs) {
inputList.add(input);
}
}
final Class extends AndroidInvocation > invocationClass =
mConstructor.getDeclaringClass();
Runners.mainRunner()
.run(new PurgeInputsExecution (context, mInvocationId, invocationClass,
inputList), 0, TimeUnit.MILLISECONDS);
}
}
/**
* Execution implementation purging all loaders with a specific invocation class.
*/
private static class PurgeExecution implements Execution {
private final WeakReference mContext;
private final Class> mInvocationClass;
private final int mInvocationId;
/**
* Constructor.
*
* @param context the context reference.
* @param invocationId the invocation ID.
* @param invocationClass the invocation class.
*/
private PurgeExecution(@Nonnull final WeakReference context, final int invocationId,
@Nonnull final Class> invocationClass) {
mContext = context;
mInvocationId = invocationId;
mInvocationClass = invocationClass;
}
public void run() {
final Object context = mContext.get();
if (context != null) {
LoaderInvocation.purgeLoaders(context, mInvocationId, mInvocationClass);
}
}
}
/**
* Execution implementation purging the loader with a specific invocation class and inputs.
*
* @param the input data type.
*/
private static class PurgeInputsExecution implements Execution {
private final WeakReference mContext;
private final List mInputs;
private final Class> mInvocationClass;
private final int mInvocationId;
/**
* Constructor.
*
* @param context the context reference.
* @param invocationId the invocation ID.
* @param invocationClass the invocation class.
* @param inputs the list of inputs.
*/
private PurgeInputsExecution(@Nonnull final WeakReference context,
final int invocationId, @Nonnull final Class> invocationClass,
@Nonnull final List inputs) {
mContext = context;
mInvocationId = invocationId;
mInvocationClass = invocationClass;
mInputs = inputs;
}
public void run() {
final Object context = mContext.get();
if (context != null) {
LoaderInvocation.purgeLoader(context, mInvocationId, mInvocationClass, mInputs);
}
}
}
}