I have a requirement in my Android project where I need to validate an argument's annotation.
For eg in below function , I need to ensure if block has the required annotation otherwise throw compilation error or lint error
fun doSomething(block : () -> Unit){}
Is there some annotation processing that could help me here
Or can lint check help me
Thank you.
To keep your code cleaner I would suggest to use lint checks, however there is a way to achieve this programatically.
You can use reflection on parameters.
val isAnnotated: Boolean = block::check.hasAnnotation<SomeAnnotation>()
if (!isAnnotated) throw Exception()
Related
I have the following kotlin property declared in a class of my Android app:
private val updateRef: KFunction<*> by lazy {
dao::class.functions.find {it.name.equals("update", true)}!!
}
Where dao is a reference to a Room DAO interface. Since I've updated kotlin to version 1.6.10 it doesn't work anymore, the following wierd exception is thrown every time I try to execute the code above. The same exception is thrown when I evaluate the expression using Android Studio's EVALUATE tool:
"Incorrect resolution sequence for Java method public open suspend fun count(): kotlin.Int defined in it.kfi.lorikeetmobile.db.dao.TablePriorityDao_Impl[JavaMethodDescriptor#d45ec9a]".
Where count() is a suspend method declared in the DAO interface. But I get this for every DAO class I have in my project and for different methods, so I think the method has nothing to do with the real problem here... I cannot figure out what is happening.
Before the update I had no problems at all. Please help.
In the end I discovered that the last version of kotlin-reflect (v. 1.6.10 in my case) doesn't keep backward compatibility for Kotlin classes that extend Java super-classes. Using Kotlin reflection to access member properties or functions of a Java super-class extended by a Kotlin class will fail as described in my question. It works fine if also the super-class is a Kotlin class. That is for me a bug that should be addressed.
This is an simplified example of what I try to do but still failed
class Definition {
#Target(AnnotationTarget.TYPE, AnnotationTarget.VALUE_PARAMETER)
#IntDef(View.VISIBLE, View.INVISIBLE, View.GONE)
//only 0,4,8 are allowed
#Retention(AnnotationRetention.SOURCE)
annotation class Visibility
}
fun isVisibleView(#Definition.Visibility visibility: Int, viewList: ArrayList<View>, ) {
for (view in viewList) {
view.visibility = visibility
}
}
//I want the ide to SHOW ERROR here since 2 is not in 0,4,8 (show before compile)
isVisibleView(2, visibleItems)
I think this question is about IDE config or Kotlin syntax
In short Enum is enough.
IntDef is android specific so you'd have to find an Android rule for IntelliJ to analyze those annotations.
Even you can make it work it only on java not Kotlin.
It seems like the warning will be generated by lint but only if you write the annotation in Java, not Kotlin
As state in this issue https://youtrack.jetbrains.com/issue/KTIJ-18693
https://developer.android.com/studio/write/annotations?fbclid=IwAR2duPFqsMx1VPDlK0nyt8-mAKJyLw_WAjY5GQMIHH__-FMpRV9SNJpqY6k
Credit: Anton Malinsky
I'm trying to migrate my MVP application from Rx to Kotlin's coroutines (which I'm new to).
As I was running some trials, I found that any code with the following structure fails to compile with org.jetbrains.kotlin.codegen.CompilationException: Back-end (JVM) Internal error: wrong bytecode generated
val scope = CoroutineScope(Dispatchers.IO)
fun a(i: Int) {
scope.launch {
withContext(Dispatchers.Main) {
val b = i + 1
}
}
}
It appears that trying to access the parameter i inside the withContext is the problem. If I assign the value of i to something else inside the function block and use that instead, it works alright. But I have the feeling I might be doing something extra wrong here hehe
This lives in a Presenter. My idea is to use "launch" with the IO dispatcher to call the repository and get some data from the database, then use it to update the UI in the Main dispatcher. It looks solid to me, but I'm a bit worried because apparently no one else is running into that same issue, which might mean this pattern I'm trying to implement should be avoided for some reason.
Any clues?
After some fiddling I found that the problem was with my kotlin plugin version.
I changed it from 1.3.50 to 1.3.72 and... magic :D
In kotlin, if we use a when block on an enum while exhausting all the enum values but without adding an else branch, we get this warning: "Enum argument can be null in Java, but exhaustive when contains no null branch".
Android Studio then suggest to add the suppress flag #Suppress("WHEN_ENUM_CAN_BE_NULL_IN_JAVA") either to the statement, function, class or file scope.
Is there any way to add this to the project scope ? Since my project is 100% Kotlin I don't need this warning and would like to disable it globally.
I have Result wrapper that wraps data comes from backend
data class Result<T>(val success: Boolean, val result: T?, val message: String?)
Idea of this, check success instead of result being null or not valid and get formatted message for UI error reporting. But when trying to use this with android lifestyle components, specifically in Observer I have to check for null.
How can I avoid this null check? This happens because of
void onChanged(#Nullable T t);
in Observer. I've tried to extend this but it seem to require more custom wrapper classes. Do we have a solution for avoid null check here.
It's a framework bug that argument is annotated as #Nullable. Fixed in androix.lifecycle 2.0.0-beta01.
Updated answer from #Andrei Vinogradov's answer
Until you upgrade to 2.0.0-beta01, you can try this solution. Use standard function let from Kotlin library :
it?.let{ result ->
if(result.success){
// Rest of your code ..
}
}