Grzegorz Adam Hankiewicz Grzegorz Adam Hankiewicz - 6 months ago 26
Android Question

How can I annotate a lambda with @WorkerThread?

I'm updating some code to use retrolambda on Android. The code mostly works, but the Android Studio 2.1 IDE seems to flag the previously OK code:

@WorkerThread void expensiveBackgroundOperation()
{
// Stuff.
}

@UiThread void updateSomeStuffOld()
{
AsyncTask.execute(new Runnable() {
@Override public void run()
{
expensiveBackgroundOperation();
}
});
}

@UiThread void updateSomeStuffNew()
{
AsyncTask.execute(() -> expensiveBackgroundOperation());
}


The following screenshot shows that the old runnable syntax is inferred correctly (or rather, it is not inferred and the
run()
method would need to be annotated with @WorkerThread for annotations to work inside properly…) but in the retrolambda syntax version the method is inferred to run on the UI, which is not:

enter image description here

How can I annotate the lambda with a
@WorkerThread
annotation? I've tried placing it in several places but I can't seem to make the IDE happy.

Answer

Apparently, the audit tool has no idea of lambda expressions and how they work. Since you are using Retrolambda, the audit most probably works on the compiled code, in which the lambda expression has been desugared into a synthetic method, which does not have any annotations. But since that synthetic method has a LineNumberTable attribute by default, errors generated by the audit tool can be associated with he correct source code line, i.e. the location of the lambda expression.

There is no way to enforce an annotation on the synthetic method generated for a lambda expression, but you can get rid of the synthetic method at all:

@UiThread void updateSomeStuffNew()
{
    AsyncTask.execute(this::expensiveBackgroundOperation);
}

Now, the runtime-generated Runnable will invoke expensiveBackgroundOperation directly (much closer to your anonymous inner class variant) and there’s no method in your class to complain about. The run() method of the runtime-generated class won’t have any annotation either, but that’s not visible to the audit.