Skip to content
This repository was archived by the owner on Feb 26, 2023. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.androidannotations.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.CLASS)
@Target(ElementType.METHOD)
public @interface SupposeBackground {

String[] serial() default {};

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.androidannotations.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Ensures that method is called from the UI thread. If it is not, then
* {@link java.lang.IllegalStateException} will be thrown (by default).
* //TODO how to change default
*/
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.METHOD)
public @interface SupposeUiThread {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.sun.codemodel;

import java.util.Iterator;
import java.util.List;

public class JSuperWildcard extends JClass {

private final JClass bound;

public JSuperWildcard(JClass bound) {
super(bound.owner());
this.bound = bound;
}

public String name() {
return "? super "+ bound.name();
}

public String fullName() {
return "? super "+ bound.fullName();
}

public JPackage _package() {
return null;
}

/**
* Returns the class bound of this variable.
*
* <p>
* If no bound is given, this method returns {@link Object}.
*/
public JClass _extends() {
if(bound !=null)
return bound;
else
return owner().ref(Object.class);
}

/**
* Returns the interface bounds of this variable.
*/
public Iterator<JClass> _implements() {
return bound._implements();
}

public boolean isInterface() {
return false;
}

public boolean isAbstract() {
return false;
}

protected JClass substituteParams(JTypeVar[] variables, List<JClass> bindings) {
JClass nb = bound.substituteParams(variables,bindings);
if(nb== bound)
return this;
else
return nb.wildcard();
}

public void generate(JFormatter f) {
if(bound._extends()==null)
f.p("?"); // instead of "? extends Object"
else
f.p("? super").g(bound);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@
import org.androidannotations.annotations.SeekBarTouchStart;
import org.androidannotations.annotations.SeekBarTouchStop;
import org.androidannotations.annotations.ServiceAction;
import org.androidannotations.annotations.SupposeBackground;
import org.androidannotations.annotations.SupposeUiThread;
import org.androidannotations.annotations.SystemService;
import org.androidannotations.annotations.TextChange;
import org.androidannotations.annotations.Touch;
Expand Down Expand Up @@ -193,6 +195,8 @@
import org.androidannotations.processing.ServiceActionProcessor;
import org.androidannotations.processing.SharedPrefProcessor;
import org.androidannotations.processing.SubscribeProcessor;
import org.androidannotations.processing.SupposeBackgroundProcessor;
import org.androidannotations.processing.SupposeUiThreadProcessor;
import org.androidannotations.processing.SystemServiceProcessor;
import org.androidannotations.processing.TextChangeProcessor;
import org.androidannotations.processing.TouchProcessor;
Expand Down Expand Up @@ -255,6 +259,7 @@
import org.androidannotations.validation.OptionsMenuValidator;
import org.androidannotations.validation.OrmLiteDaoValidator;
import org.androidannotations.validation.PrefValidator;
import org.androidannotations.validation.SupposeValidator;
import org.androidannotations.validation.ProduceValidator;
import org.androidannotations.validation.ResValidator;
import org.androidannotations.validation.RestServiceValidator;
Expand Down Expand Up @@ -521,6 +526,8 @@ private ModelValidator buildModelValidator(IRClass rClass, AndroidSystemServices
modelValidator.register(new ProduceValidator(processingEnv));
modelValidator.register(new RunnableValidator(UiThread.class.getName(), processingEnv));
modelValidator.register(new RunnableValidator(Background.class.getName(), processingEnv));
modelValidator.register(new SupposeValidator(SupposeUiThread.class.getName(), processingEnv));
modelValidator.register(new SupposeValidator(SupposeBackground.class.getName(), processingEnv));
modelValidator.register(new InstanceStateValidator(processingEnv));
modelValidator.register(new OrmLiteDaoValidator(processingEnv, rClass));
modelValidator.register(new HttpsClientValidator(processingEnv, rClass));
Expand All @@ -543,7 +550,7 @@ private boolean traceActivated() {
private ProcessResult processAnnotations(AnnotationElements validatedModel, IRClass rClass, AndroidSystemServices androidSystemServices, AndroidManifest androidManifest) throws ProcessingException, Exception {
timeStats.start("Process Annotations");
ModelProcessor modelProcessor = buildModelProcessor(rClass, androidSystemServices, androidManifest, validatedModel);
ProcessResult processResult = modelProcessor.process(validatedModel);
ProcessResult processResult = modelProcessor.process(processingEnv, validatedModel);
timeStats.stop("Process Annotations");
return processResult;
}
Expand Down Expand Up @@ -620,9 +627,11 @@ private ModelProcessor buildModelProcessor(IRClass rClass, AndroidSystemServices
}
modelProcessor.register(new SubscribeProcessor());
modelProcessor.register(new ProduceProcessor());
modelProcessor.register(new UiThreadProcessor());
modelProcessor.register(new UiThreadProcessor());
modelProcessor.register(new SupposeUiThreadProcessor());
modelProcessor.register(new BackgroundProcessor());
modelProcessor.register(new AfterInjectProcessor());
modelProcessor.register(new SupposeBackgroundProcessor());
modelProcessor.register(new AfterInjectProcessor());
modelProcessor.register(new InstanceStateProcessor(processingEnv));
modelProcessor.register(new HttpsClientProcessor(rClass));
modelProcessor.register(new OnActivityResultProcessor(processingEnv, rClass));
Expand Down Expand Up @@ -677,8 +686,10 @@ public Set<String> getSupportedAnnotationTypes() {
Touch.class, //
ItemSelect.class, //
UiThread.class, //
SupposeUiThread.class,
Transactional.class, //
Background.class, //
SupposeBackground.class,
Extra.class, //
SystemService.class, //
SharedPref.class, //
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
package org.androidannotations.api;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
Expand All @@ -25,6 +26,7 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

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

public class BackgroundExecutor {
Expand All @@ -34,7 +36,32 @@ public class BackgroundExecutor {
public static Executor DEFAULT_EXECUTOR = Executors.newScheduledThreadPool(2 * Runtime.getRuntime().availableProcessors());
private static Executor executor = DEFAULT_EXECUTOR;

public static final WrongThreadListener DEFAULT_WRONG_THREAD_LISTENER = new WrongThreadListener() {
@Override
public void onUiExpected() {
throw new IllegalStateException("Method invocation is expected from the UI thread");
}

@Override
public void onBgExpected(String... expectedSerials) {
if (expectedSerials.length == 0) {
throw new IllegalStateException("Method invocation is expected from a background thread, but it was called from the UI thread");
}
throw new IllegalStateException("Method invocation is expected from one of serials " + Arrays.toString(expectedSerials) + ", but it was called from the UI thread");
}

@Override
public void onWrongBgSerial(String currentSerial, String... expectedSerials) {
if (currentSerial == null) {
currentSerial = "anonymous";
}
throw new IllegalStateException("Method invocation is expected from one of serials " + Arrays.toString(expectedSerials) + ", but it was called from " + currentSerial + " serial");
}
};
private static WrongThreadListener wrongThreadListener = DEFAULT_WRONG_THREAD_LISTENER;

private static final List<Task> tasks = new ArrayList<Task>();
private static final ThreadLocal<String> currentSerial = new ThreadLocal<String>();

/**
* Execute a runnable after the given delay.
Expand Down Expand Up @@ -181,9 +208,17 @@ public static void execute(Runnable runnable, String id, String serial) {
* @param executor
* the new executor
*/
public static void setExecutor(Executor executor) {
BackgroundExecutor.executor = executor;
}
public static void setExecutor(Executor executor) {
BackgroundExecutor.executor = executor;
}

/**
* Change the WrongThreadListener.
* @param listener the new WrongThreadListener
*/
public static void setWrongThreadListener(WrongThreadListener listener) {
BackgroundExecutor.wrongThreadListener = listener;
}

/**
* Cancel all tasks having the specified <code>id</code>.
Expand Down Expand Up @@ -219,6 +254,50 @@ public static synchronized void cancelAll(String id, boolean mayInterruptIfRunni
}
}

/**
* Checks if current thread is UI and notifies
* {@link BackgroundExecutor.WrongThreadListener#onUiExpected()} if it doesn't.
*/
public static void checkUiThread() {
if (Looper.getMainLooper().getThread() != Thread.currentThread()) {
wrongThreadListener.onUiExpected();
}
}

/**
* Check if current thread is a background thread and, optionally, restrict it
* with passed serials. If no serials passed and current thread is UI, then
* {@link WrongThreadListener#onBgExpected(String...)} will be called.
* If current thread is not UI and serials list is empty, then method just returns.
* Otherwise, if method was called not during {@link Task} execution or the task has no
* serial, then {@link WrongThreadListener#onWrongBgSerial(String, String...)} will be called
* with null for the first parameter. If task has serial but passed serials don't contain that,
* then {@link WrongThreadListener#onWrongBgSerial(String, String...)} will be called with
* task's serial for the first parameter.
*
* @param serials (optional) list of allowed serials
*/
public static void checkBgThread(String... serials) {
if (Looper.getMainLooper().getThread() == Thread.currentThread()) {
wrongThreadListener.onBgExpected(serials);
return;
}
if (serials.length == 0) {
return;
}
String current = currentSerial.get();
if (current == null) {
wrongThreadListener.onWrongBgSerial(null, serials);
return;
}
for (String serial : serials) {
if (serial.equals(current)) {
return;
}
}
wrongThreadListener.onWrongBgSerial(current, serials);
}

/**
* Indicates whether a task with the specified <code>serial</code> has been
* submitted to the executor.
Expand Down Expand Up @@ -299,6 +378,7 @@ public void run() {
}

try {
currentSerial.set(serial);
execute();
} finally {
/* handle next tasks */
Expand All @@ -313,6 +393,7 @@ private void postExecute() {
/* nothing to do */
return;
}
currentSerial.set(null);
synchronized (BackgroundExecutor.class) {
/* execution complete */
tasks.remove(this);
Expand All @@ -333,4 +414,14 @@ private void postExecute() {

}

/**
* A callback interface to be notified when current thread, in which method has been invoked,
* is wrong.
* @see #setWrongThreadListener(WrongThreadListener)
*/
public static interface WrongThreadListener {
void onUiExpected();
void onBgExpected(String... expectedSerials);
void onWrongBgSerial(String currentSerial, String... expectedSerials);
}
}
Loading