最近在Build的過程中注意到Gradle的log中有一個關於JavaCompiler的警告。
具體如下:
Configure project :App
WARNING: API ‘variant.getJavaCompiler()’ is obsolete and has been replaced with ‘variant.getJavaCompileProvider()’.
It will be removed at the end of 2019.
For more information, see https://d.android.com/r/tools/task-configuration-avoidance.
To determine what is calling variant.getJavaCompiler(), use -Pandroid.debug.obsoleteApi=true on the command line to display more information.
按照提示,可以給build包命令加上參數來查看更詳細的信息,運行以下命令:
.\gradlew assembleDebug -Pandroid.debug.obsoleteApi=true
結果如下:
Configure project :App
WARNING: API ‘variant.getJavaCompiler()’ is obsolete and has been replaced with ‘variant.getJavaCompileProvider()’.
It will be removed at the end of 2019.
For more information, see https://d.android.com/r/tools/task-configuration-avoidance.
REASON: Called from: D:\StudioProjects3.5\MyProject\App\build.gradle:267
WARNING: Debugging obsolete API calls can take time during configuration. It’s recommended to not keep it on at all times.
看來問題是在這個 build.gradle 文件上面,對應的代碼如下:
android.libraryVariants.all { variant ->
variant.javaCompiler.options.encoding = 'UTF-8'
}
可以看出上面的 .javaCompiler 是不推薦使用了,我們可以通過按住 Ctrl+ 點擊 libraryVariant 查看源碼來確定這一點。此時會打開 LibraryExtension.java 文件,相應的方法說明如下:
/**
* Returns a collection of <a
* href="https://developer.android.com/studio/build/build-variants.html">build variants</a> that
* the library project includes.
*
* <p>To process elements in this collection, you should use the <a
* href="https://docs.gradle.org/current/javadoc/org/gradle/api/DomainObjectCollection.html#all(org.gradle.api.Action)">
* <code>all</code></a> iterator. That's because the plugin populates this collection only after
* the project is evaluated. Unlike the <code>each</code> iterator, using <code>all</code>
* processes future elements as the plugin creates them.
*
* <p>The following sample iterates through all <code>libraryVariants</code> elements to <a
* href="https://developer.android.com/studio/build/manifest-build-variables.html">inject a
* build variable into the manifest</a>:
*
* <pre>
* android.libraryVariants.all { variant ->
* def mergedFlavor = variant.getMergedFlavor()
* // Defines the value of a build variable you can use in the manifest.
* mergedFlavor.manifestPlaceholders = [hostName:"www.example.com"]
* }
* </pre>
*/
public DefaultDomainObjectSet<LibraryVariant> getLibraryVariants() {
return libraryVariantList;
}
這個方法是用來返回 Library 項目的所有構件變體的,所以要找的方法應該在 LibraryVariant 接口裏面了。
/** A Build variant and all its public data. */
public interface LibraryVariant extends BaseVariant, TestedVariant {
/**
* Returns the Library AAR packaging task.
*
* @deprecated Use {@link #getPackageLibraryProvider()}
*/
@Nullable
@Deprecated
Zip getPackageLibrary();
/**
* Returns the {@link TaskProvider} for the Library AAR packaging task.
*
* <p>Prefer this to {@link #getPackageLibrary()} as it triggers eager configuration of the
* task.
*/
@Nullable
TaskProvider<Zip> getPackageLibraryProvider();
}
沒有直接看到 getJavaCompiler() 方法,繼續查看父接口 BaseVariant。
/**
* A Build variant and all its public data. This is the base class for items common to apps,
* test apps, and libraries
*/
public interface BaseVariant {
/**
* Returns the Java Compilation task
*
* @deprecated Use {@link #getJavaCompileProvider()}
*/
@NonNull
@Deprecated
JavaCompile getJavaCompile();
/**
* Returns the {@link TaskProvider} for the Java Compilation task
*
* <p>Prefer this to {@link #getJavaCompile()} as it triggers eager configuration of the task.
*/
@NonNull
TaskProvider<JavaCompile> getJavaCompileProvider();
總算找到了 getJavaCompiler() ,源碼上也確實註明了這個方法被棄用了,推薦使用 getJavaCompileProvider().
觀察這兩個方法,發現返回類型不一樣,getJavaCompilerProvider() 返回的是一個 TaskProvider。來看看這個接口是什麼:
/**
* Providers a task of the given type.
*
* @param <T> Task type
* @since 4.8
*/
public interface TaskProvider<T extends Task> extends NamedDomainObjectProvider<T> {
/**
* Configures the task with the given action. Actions are run in the order added.
*
* @param action A {@link Action} that can configure the task when required.
* @since 4.8
*/
void configure(Action<? super T> action);
/**
* The task name referenced by this provider.
* <p>
* Must be constant for the life of the object.
*
* @return The task name. Never null.
* @since 4.9
*/
String getName();
}
這個接口提供了一個 configure 方法,可以傳入一個 Action 去配置對應的 Task。這樣我們就可以改一下之前的 build.gradle 文件了。
android.libraryVariants.all { variant ->
variant.javaCompileProvider.configure {
}
}
本來處理到這裏的時候有點懵逼了,也沒參數,接下來怎麼處理?看着看着,感覺跟 Kotlin 的 apply 方法很像啊,那就試試看。之前的 TaskProvider 的泛型參數類型是 JavaCompile。那我們是不是可以直接調用這個 JavaCompile 類的方法呢?那就試試:
android.libraryVariants.all { variant ->
variant.javaCompileProvider.configure {
options.encoding = 'UTF-8'
}
}
Sync一下,Success。警告也消失了。Android Gradle Plugin 廢棄 getJavaCompiler 方法應該是出於設計或性能考慮,大家遇到這類警告,最好也是花點時間按照提示一步步處理。在這裏給想學習Gradle的同學推薦一下《Android Gradle 權威指南》。這本書對各個知識點理解得非常透徹,看完收穫很大。最後感謝看到這裏的同學。拜拜。