we know gradle 3.x.x update the dependency configuration, I have a question when use, we know If the project use v7:26.0.1, It's better to use same version in library module, so I think use compileOnly is the best choice, it will pass the compile time and use app library's v7 code at runtime, it will reduce apk size and don`t care the v7 version right?
but it you try , you will find it can't pass compile time, why?
These are the errors I'm getting, and they are all related to xml not finding values.
Error:(43) No resource identifier found for attribute 'srcCompat' in package 'com.yalantis.ucrop.test'
Error:(19, 20) No resource found that matches the given name (at 'style' with value '#style/TextAppearance.Widget.AppCompat.Toolbar.Title').
compileOnly means it is only compiled. Meaning at runtime, when it needs the AppCompat library, it isn't present because the library isn't added to the APK itself.
You can do compileOnly with libraries like Lombok because it isn't needed at runtime - only compile time. AppCompat though, is needed at runtime as well. Don't use compileOnly with it. Use implementation (or compile if you have a gradle version that uses that).
You could use the compileOnly keyword with e.g. an annotation library (like Lombok) because the references to the libraries are usually removed at compile time (and converted to non-library code). There are of course exceptions, but that's an example of usage.
The APK is smaller with compileOnly because the library isn't added to the APK. You can't use any library features at runtime when you use compileOnly because, at runtime, the library can't be found
Related
I have a project with the following structure.
+-MyApplication
+-MyLibrayOne
+-MyLibrayTwo
MyApplication is my main application whereas MyLibrayOne and MyLibrayTwo are two libraries imported into project. MyApplication uses some classes of MyLibrayOne and MyLibrayOne uses some classes of MyLibrayTwo.
In the .gradle file of MyLibrayOne I have used - compile project(':MyLibrayTwo'). Everything works fine. But if I replace compile with implementation it can not import the classes from MyLibrayTwo. It gives error: cannot find symbol class XXXX error.
Use api instead of implementation will solve your problem. I.e.
dependencies {
// Enforce the runtime dependencies
api project(':MyLibrayOne')
api project(':MyLibrayTwo')
}
Simply to explain, api will let the depending project see all the classes of the depended projects but implementation cannot do this.
First I encourage you to have a look here in the Google I/O 2017.
compile and implementation are not the same thing.
compile lets the application access to all sub-dependencies that the sub-library has access to. This means that if MyLibrayOne depends on MyLibraryTwo and you need also access to the class from MyLibrarayTwo you'll have to direct gradle to expose the classes from MyLibrayTwo using the compile directive.
If this is not needed then implementation is enough.
I can only guess that your case is the former and so you'll need to keep using compile. Since compile is now deprecated use the api directive. They are the same.
Also, have a look here in the gradle documentation.
I made a library, but when I tried to use it with implementation 'com.example:mylibrary:1.3.0' in my app's build.gradle, I keep getting an error saying the ConstraintLayout dependency (which the library uses but not the app) is not found. However it was explicitly defined in the library's build.gradle with implementation.
When I ran gradlew app:dependencies on the terminal, it shows that the library has no dependencies, even though it actually has 2. This seems to be the source of the problem, Gradle can't detect the dependencies of the library.
I didn't run into this problem for a while but when I decided to remove the ConstraintLayout dependency from my app an error appears during build.
When you're using implementation for the dependencies in your library, the project which is dependent with it will not see the dependencies. You need to use api instead of implementation.
I know the difference between the two as discussed here.
As Android developer,
Why I should care about this?
In gradle, why should I use compileOnly vs implementation/api?
Why I should care about this?
To make your apps build but not ship with unnecessary stuff.
In gradle, why should I use compileOnly vs implementation/api?
The documentation for compileOnly gives one use case as an example:
Gradle adds the dependency to the compilation classpath only (it is not added to the build output). This is useful when you're creating an Android library module and you need the dependency during compilation, but it's optional to have present at runtime. That is, if you use this configuration, then your library module must include a runtime condition to check whether the dependency is available, and then gracefully change its behavior so it can still function if it's not provided. This helps reduce the size of the final APK by not adding transient dependencies that aren't critical. This configuration behaves just like provided (which is now deprecated).
source
For example, consider a push messaging library that supports both Firebase FCM and Amazon ADM but does not require either. It would unnecessarily bloat apps if it would ship with both as transitive dependencies. With compileOnly the library can still be built. Developers using the library can select which dependencies to actually use.
Another example could be compile-time annotations that do not need to ship with the application.
Unable to understand the latest gradle dependency configurations which are introduced in Android Studio 3.0 i.e. implementation, api , compileonly and runtimeonly.
Please refer the link : Android Studio 3.0 New Gradle Configuration available at android developers official site.
Based on description mentioned in above link:
implementation: When your module configures an implementation dependency, it's letting Gradle know that the module does not want to
leak the dependency to other modules at compile time. That is, the
dependency is available to other modules only at runtime. Using this
dependency configuration instead of api or compile can result in
significant build time improvements because it reduces the amount of
projects that the build system needs to recompile. For example, if an
implementation dependency changes its API, Gradle recompiles only that
dependency and the modules that directly depend on it. Most app and
test modules should use this configuration.
api: When a module includes an api dependency, it's letting Gradle know that the module wants to transitively export that
dependency to other modules, so that it's available to them at both
runtime and compile time. This configuration behaves just like compile
(which is now deprecated), and you should typically use this only in
library modules. That's because, if an api dependency changes its
external API, Gradle recompiles all modules that have access to that
dependency at compile time. So, having a large number of api
dependencies can significantly increase build times. Unless you want
to expose a dependency's API to a separate test module, app modules
should instead use implementation dependencies.
compileOnly: Gradle adds the dependency to the compilation classpath only (it is not added to the build output). This is useful
when you're creating an Android library module and you need the
dependency during compilation, but it's optional to have present at
runtime. That is, if you use this configuration, then your library
module must include a runtime condition to check whether the
dependency is available, and then gracefully change its behavior so it
can still function if it's not provided. This helps reduce the size of
the final APK by not adding transient dependencies that aren't
critical. This configuration behaves just like provided (which is now
deprecated).
runtimeonly: Gradle adds the dependency to the build output only, for use during runtime. That is, it is not added to the compile
classpath. This configuration behaves just like apk (which is now
deprecated).
I'm creating an Android library that will be published to something like Sonatype. Some of my classes depend on classes in the AppCompat library.
If my Android module look like this:
dependencies {
compile "com.android.support:appcompat-v7:25.3.1"
}
will my users run into problems if they add my library as a dependency and also add some future version of appcompat as a dependency?
And related, is there a way I can set this up so they don't have to specify transitive dependencies, or would that even be expected for ease of use?