MockK is a mocking library written in Kotlin and for Kotlin. In addition to the traditional functionality provided by JVM based mocking libraries, Kotlin’s language feature significantly improves MockK’s usability.
However, aside from MockK, have you ever wondered how a JVM based mocking library works under the hood? Moreover, when using other libraries together with a mocking library, have you ever had trouble in identifying the root cause encountered? These questions might explain why some may shy away from using MockK, or other mocking libraries. …
Android KTX provides opinionated methods facilitating using Kotlin Coroutines in Android Architecture Components. For instance,
Flow<T>.asLiveData() is quite helpful to migrate your apps using LiveData towards coroutine. Make sure to understand their behaviors underneath before using them!
This story is a continuation of the previous one.
When converting from Flow to LiveData, the source stream might be a hot StateFlow like above. Running the test will actually end up with the following error:
kotlinx.coroutines.test.UncompletedCoroutinesError: Unfinished coroutines during teardown. Ensure all coroutines are completed or cancelled by your test.
We know a hot Flow like SharedFlow never completes, so this…
Have you ever got frustrated to debug LiveData changes by adding numerous log statements or breakpoints? As the core data structure of Android Architecture Components, LiveData is used widely in many apps to hold observable data. However, its debugging experience could still be a pain point after these many years.
There are two traditional yet powerful methods for observing LiveData changes: Debugging and logging.
When it comes to debugging, we mostly interact with our IDE and do not need to touch any code. …
Android KTX provides opinionated methods, such as
Flow<T>.asLiveData(), facilitating using Kotlin Coroutines in Android Architecture Components. Make sure to understand their behaviors underneath before using them!
The official documentation on Kotlin coroutines on Android is quitewell-written, while there are numerous article posts covering the basics. In this story, we will focus on the lessons learned when using these extension methods, using
Flow<T>.asLiveData() as an example.
Let’s start with a concrete example using the orthodox Android App Architecture: Repository + ViewModel + Fragment
RedditServiceis a simple Retrofit service.
If generic types are exposed in Kotlin API, consider
@JvmSuppressWildcards so that your Java consumer can compile successfully.
Kotlin generics are different from (in my opinion, smarter than) Java generics. Kotlin generics has declaration-site variance and type projections, which are officially documented here. Generics is a gigantic topic itself. My usual practice is to leverage IDE warnings and compiler error messages to fix my code since they usually contain the necessary information to show you where you did wrong.
However, as we are Kotlinizing our codebase from Java to Kotlin, it is possible to have a sandwich-style code dependency that…
A simple trick to write an email report for your readers
Recently my team wrote an email report to the leadership team on the executive summary of Android Gradle Plugin upgrades. Below is the initial version of the reports in the exec summary section:
- We have migrated to Android Gradle Plugin from 4.0 to 4.1.
-We have observed a reduction in CI build by 50% at 50th percentile and 32% at 90th percentile.
- Our APK size is also reduced by -17%
The above looks pretty ordinary. But let’s compare it to the following:
Reporting a bug outside your company’s codebase is not as simple as DMing your colleague. This story listed do’s and don’ts for submitting bug reports, from the perspective of an Android engineer.
I have been working in the infrastructure team to support the feature development teams at my company for over 2 years. Many of the issues are reported directly from my colleagues and one of my responsibility is to investigate those reports, root-cause the issue, and suggest actions.
Kotlin 1.4 introduced an exciting new feature called Explicit API mode. In this new mode, libraries need to provide explicit visibility modifiers and explicit return types. Library authors can then be free from future regret in case they accidentally expose APIs to their dependents.
While applying the explicit API mode in a real-world code base, I find it extremely useful to identify the unintended exposed APIs in the library. Meanwhile, almost as expected for every new features, I discovered a few issues along with the adoption in our Android code base.
Note: The Kotlin version used in this story is…
If a generic container type is written in Java (such as LiveData<T>), it has to be used safely xor elegantly.
To use it safely and elegantly, declare the type in Kotlin.
I had an interesting conversation with my colleague today about the nullability of the input of an Observer on the LiveData. Since our app has been adopting Android Architecture Components, we have widely used LiveData and Observer across our codebase, as shown in the following scaffold:
This example probably looks too familiar to you. But here is the question: What’s the…
Update: Kotlin 1.4 announced that SAM will be supported for Kotlin (https://youtrack.jetbrains.com/issue/KT-7770). The problem presented in this story is completely solved by JetBrains/Kotlin team.
SAM conversion is a subtle feature that sparks joy when converting the codebase from Java to Kotlin. However, it is annoying when it does not work as you expected. This documents the pleasure and learnings when my team is converting our codebase from Java to Kotlin.
Functional interface, also known as SAM (Single Abstract Method), was introduced to Java 8. It can be combined with lambda expression and method reference in Java. Lambda expression simplifies Java…