I tracked my problem down to adding to my geofenceList.
this is a global variable
lateinit var geofenceList: MutableList<Geofence>
In onCreate I add to the list:
val latitude = -26.082586
val longitude = 27.777242
val radius = 10f
geofenceList.add(Geofence.Builder()
.setRequestId("Toets")
.setCircularRegion(latitude,longitude,radius)
.setExpirationDuration(Geofence.NEVER_EXPIRE)
.setTransitionTypes(Geofence.GEOFENCE_TRANSITION_ENTER)
.build())
Every time I run the app the app closes as soon as it opens.
I tried changing it to a normal variable but I am not certain how to do it and keep it a global variable, and a List would be more useful.
I just realized what your issue is: You never initialize your list. When you follow the advice in my comment, you should find a NullPointerException and here's how to fix it:
Firstly, try to avoid lateinit if possible. The compiler actually tries to find this problem for you and by using lateinit, you basically tell the compiler to shut up - even though the mistake is still there. INstead, you need to initialize your variable like so:
var geofenceList: MutableList<Geofence> = mutableListOf()
You could make it even shorter by removing the explicit type declaration:
var geofenceList = mutableListOf<Geofence>()
Related
I am a beginner in Kotlin and going through for loop
Simple code sample:
for (i in 1..5) print(i)
Please can someone advise me why we do not specify the counter/iterator variable type "i" with the keyword var / val. Since "var /val" is the standard way to declare variables in Kotlin.
This is simply how the for loop syntax is designed. I cannot speak for the designers, but I believe that's a design decision to avoid unnecessary bloat, and maybe confusion.
You cannot use an existing variable as the loop variable. The loop variable is scoped to the loop, and shadows existing ones from outer scopes. So it's kind of implied that you're declaring a new variable here, even without a keyword (however I have to admit that the shadowing behaviour would be clearer if we had to write the val/var keyword here).
Also, the loop variable is actually a val inside the loop's body (it cannot be reassigned), but it can feel like a var because it changes for each loop turn and is technically declared outside the loop's body. In effect, it's like a new val declared in the loop's body with a new value for each loop iteration.
So your example code can be thought of as:
var temp = 1
while (temp <= 5) {
val i = temp
println(i)
temp++
}
That's probably why the designers decided to not put any keyword here: it's unnecessary, and both val and var would be confusing in their own way.
I replaced it with Val and the texts did not go away.
Edit: Changing it manually fixed it. But why "var" is it giving an error?
"Variable is never modified so it can be declared using 'val'"
In many languages, compile time validation yields information about the mutability of variables. Variables that do not change value during the execution of a function are invariables. In Kotlin (and some other languages) it is highly recommended to mark those invariables as such (by using the keyword val instead of var).
If you use val, then this has two consequences.
The obvious one is, that the value cannot change any longer. If you try to assign a new value later on, the compiler will yield a compile time error, and you must either assign the new value somewhere else, or change the val back to var. This ensures, that the original value is not accidentally changed.
{
val pi = 3.141d
for (...
pi = 3 // This will not compile
)
}
The less obvious effect is, that any reader of the scope will immediately see that the value will never change during the scope's existence. This is a great benefit in readability, as it signals any reader that variable changes happen elsewhere.
{
val myMessage = "..."
...
// Here I can be sure that myMessage is still "..."
}
It is therefore useful to mark invariables as val, as it helps read and understand the code and adds to safety in execution.
In Kotlin, var denotes a variable that can be reassigned different values, while val denotes a variable that cannot.
If you never reassign a var, it's better to show that you don't need this by using val instead. The compiler can do better optimizations and in particular smart casts with vals.
As a rule of thumb: if the compiler doesn't force you to use var, use val.
Using KotlinPoet, in order to generate a PropertySpec for adding properties to classes and constructors, you need a TypeName object.
The TypeMirror.asTypeName() KotlinPoet function is deprecated, because it won't always work correctly for Kotlin types.
But I can't find a single example of how to get a correct TypeName for a Kotlin class (e.g. kotlin.String) using the kotlinpoet-metadata APIs, the way the deprecation message says.
The docs for kotlinpoet-metadata APIs also seem completely broken (go to https://square.github.io/kotlinpoet/interop-kotlinx-metadata/#interop-with-kotlinx-metadata and click anything under the APIs section)
Does anyone have an example of how to replace TypeMirror.asTypeName() with some kotlinpoet-metadata code to get a TypeName, so that I can create a PropertySpec?
Not very sure if this aligns with the intention of the deprecation message, but this is what I got it to work.
I first had to add kotlinpoet-metadata-specs.
implementation("com.squareup:kotlinpoet:1.7.1")
implementation("com.squareup:kotlinpoet-metadata:1.7.1")
implementation("com.squareup:kotlinpoet-metadata-specs:1.7.1")
Then use a util method from com.squareup.kotlinpoet.metadata.specs.internal.ClassInspectorUtil to create className.
val packageName = getPackage(element).qualifiedName.toString()
val typeMetadata = element.getAnnotation(Metadata::class.java)
val kmClass = typeMetadata.toImmutableKmClass()
val className = ClassInspectorUtil.createClassName(kmClass.name)
then use
val funSpec = FunSpec.builder("allNullableSet")
.receiver(className)
.returns(Boolean::class.java)
.addStatement(statement)
.build()
I have found a way to get the TypeName of a TypeElement in my AbstractProcessor, thanks to having access to its processingEnv:
val kmClass = (typeElement.kotlinClassMetadata() as KotlinClassMetadata.Class).toKmClass()
val elementName: TypeName = ClassName(processingEnv.elementUtils.getPackageOf(typeElement).toString(), kmClass.name.substringAfterLast("/"))
It should also be doable without processingEnv by splitting the kmClass.name manually.
I have 2 classes lets call them A and B, I also have a function that converts an instance of A to an instance of B.
My code that is causing issues is basically:
fun fromAtoB(a: A) = B (fb1 = a.fa1, fb2 = a.fa2, fb3 = a.fa3)
val listOfA: List<A> = ...
val listOfB: listOfA.map { fromAtoB(it) }
This won't build due to the line:
fromAtoB(it)
With the error:
Due to the error Type checking has run into a recursive problem. Easiest workaround: specify types of your declarations explicitly
I Have no clue what I can do to fix this, Google had provided no results that seem to apply to my issue...
Thanks in advance for any help!
EDIT:
Here are the actual source files:
TenantEntity.kt - https://pastebin.com/mdSWiA1Y (Line 51 of this file
is the issue)
TenantDto.kt - https://pastebin.com/83UP9Cwe
ReceiptEntity.kt - https://pastebin.com/BjP2ikg9
ReceiptDto.kt - https://pastebin.com/Kpt9dSAp
This type of problem means that the compiler can't infer what the type of listOfB should be, because you have a recursive call somewhere in its definition. That's curious as I can't see any in your example code, but maybe you left out the offending code inadvertently. Anyways, this problem is usually resolved by doing what the error message suggests, manually specifying the return type like so:
val listOfB: List<B> = listOfA.map { fromAtoB(it) }
Edit:
After trying the real code, I just went after a hunch and changed line 45 in TenantEntity.kt from this:
fun fromDto(dto: TenantDto) = TenantEntity (
to this:
fun fromDto(dto: TenantDto): TenantEntity = TenantEntity (
and the error was gone. I'm not really sure why, but it should compile now.
Second edit:
Upon further inspection, you're going to run into a StackOverflowException with this code, which is ultimately why the compiler couldn't resolve the type. When you call TenantEntity.fromDto(...), that will call ReceiptEntity.fromDto(...), which will in turn call TenantEntity.fromDto(...), and back again, into eternity (or the stack limit). That's not going to work, you'll need to fix your logic there.
I really want to know why Kotlin use the word val to stand for constant?
If var means variable.val means what ? val means var + l or val is only one word for short?
In the Kotlin Documentation,we only have the following words.
Read-only local variables are declared using val keyword. Mutable
local variables are declared using var keyword.
This question is not only to make sense of the word val,but also Remind the WORD MAKER to tell us why they name the word,this is not a little thing,this will make us more comfortable to learn the new knowledge,we want to learn and make sense of everything.
For example,many people want to know why Swift use the word let or Why Objective-C use the .m filename extension?
I think the official documentation or response is really important,any guess or assuming is not really helpful,because it's not convictive,the confused will be still the confused.
I also asked this question in the official forum:
https://discuss.kotlinlang.org/t/why-kotlin-use-the-word-val-to-stand-for-constant/4491
Some references:
https://discuss.kotlinlang.org/t/change-val-to-something-else/1180/13
val means value
This is a read-only value.
var is a mutable value
const would on the other hand be not 100% correct. The value PI (3.14..) is a constant. Its value never changes. The value of x in this line val x = random.nextInt() will (hopefully) always be different, but you want the value not to be modified in the function. So the keyword val is quite appropriate.
val keyword is only one word. abbreviation for val not found anywhere. Your question explains what is val.
Read-only local variables are declared using val keyword. Mutable
local variables are declared using var keyword.
Here is a site explains why val is Read-only and not immutable.
http://blog.danlew.net/2017/05/30/mutable-vals-in-kotlin/
val does not mean immutable, val means read-only. That means that
you're not allowed to explicitly write to a val, but it doesn't
guarantee that they're immutable
https://artemzin.com/blog/kotlin-val-does-not-mean-immutable-it-just-means-readonly-yeah/
Kotlin allows you declare get() of the val which breaks immutability
of the property and leaves only read permission for external "users".
Kotlin's syntax is inspired by Scala. In Kotlin several ideas are taken from Scala besides the syntax. Kotlin also adds things on its own and does certain things very differently than Scala (i.e., no implicit conversion in Kotlin compared to Scala). Long matter short: You have to ask the Scala guys why they chose the keyword combination var and val.
val from value.
var from variable.
value - a property such as number assigned to or calculated for a variable, constant or expression(wiki)
variable - a symbolic name associated with a value and whose associated value may be changed(wiki)