Difference between file and classes in kotlin - android

I am a bit confuse that where to use file or class in kotlin can some one please suggest when to use file,it is not clear for me due to less documents for both the case.

You got to use a kotlin file to declare extension methods , and import that file to the class or file you're working on
Eg: the kotlin file contains
package com.something.mediaplayersystem
public fun String.toLowerCaseByAnExtensionMethod(){
this.toLowerCase()
}
And I want to use that extension method on a class
package com.something.mediaplayersystem
import com.something.mediaplayersystem.toLowerCase
class Classa {
var word:String = "WELCOME"
public fun Method(){
var lowerCaseWord = word.toLowerCaseByAnExtensionMethod()
}
}
In the case of String you don't need to import the method but in mayor cases you have to.

Related

Platform declaration clash kotlin

I am seeing the following error
Platform declaration clash: The following declarations have the same
JVM signature (getHosts()Landroidx/lifecycle/MutableLiveData;):
private final fun <get-hosts>(): MutableLiveData<List> defined
in com.example.xx.viewmodel.HostsViewModel public final fun
getHosts(): MutableLiveData<List> defined in
com.example.xx.viewmodel.HostsViewModel
What am I doing wrong?
class HostsViewModel : ViewModel() {
private val hostsService = HostsService()
private val hosts: MutableLiveData<List<Host>> by lazy {
MutableLiveData<List<Host>>().also {
loadHosts()
}
}
fun getHosts(): MutableLiveData<List<Host>> {
return hosts
}
private fun loadHosts(){
hosts.value = hostsService.getHosts().body()
}
}
For every class property (val), Kotlin generates a getter called getHosts() and for var also a setter called setHosts(MutableLiveData<List<Host>> value) as per Java's convention. It hides it from the Kotlin user as getters and setters are usually just boilerplate code without offering much value. As such, your own getHosts() method clashes with the generated method at compilation. You have multiple possibilities to solve this issue:
Rename private val hosts to something else, e.g. private val internalHosts
Annotate the getHosts method with #JvmName("getHosts2"). If you do that though, consider the possibility that someone might call your code from Java and in that case, the caller would need to call getHosts2() in Java code, which might not be such nice API-design.
Reconsider your api design. In your case, you could simply make val hosts public and remove your getHosts() entirely, as the compiler will auto-generate getHosts() for you.
In addition to that, you might want to consider not exposing MutableLiveData in general as mentioned in the comments.
Edit:
Also, I would recommend that you do this:
val hosts: MutableLiveData<List<Host>> by lazy {
MutableLiveData<List<Host>>().also {
it.value = hostsService.getHosts().body()
}
}
and remove loadHosts to make your code more concise.

Junit 4 test inner class in kotlin

I use Junit4 and kotlin.
I use the Enclosed for the inner class test.
import org.junit.Test
import org.junit.experimental.runners.Enclosed
import org.junit.runner.RunWith
#RunWith(Enclosed::class)
class SampleTest {
var text = "parent class"
class Class1 {
#Test
fun `print the text`() {
println(text)
}
}
inner class Class2 {
#Test
fun `print the text`() {
println(text)
}
}
}
in Class1 and Class2, need the text variable.
I use the inner for an access child class to parent class.
but I have a problem, the test function is removed and I can't test that. see the photo.
can I test the inner class in kotlin with Junit4?
Class1 is a plain nested class that happens to be in SampleTest. It's just an organisational thing, your Class1 instance doesn't have any reference to a SampleTest instance, so it can't access text (not without being passed an instance explicitly).
If you want a nested class to be able to access an enclosing instance like that, you need to mark it as inner, like with Class2. That way you can create an instance of Class2 through an instance of SampleClass, like
val sample = SampleClass()
val class2 = sample.Class2()
sample.text = "wow!"
class2.`print the text`()
You can read about this stuff in the docs if it's unfamiliar
So yeah, if JUnit constructs a Class1 instance, it doesn't know what text is, since that's an instance variable in some other unrelated class.
And I'm assuming it doesn't know how to create Class2, since it requires a SampleTest instance to do that. All the examples for Enclosed use static nested classes, and like the Java docs say:
A static nested class interacts with the instance members of its outer class (and other classes) just like any other top-level class. In effect, a static nested class is behaviorally a top-level class that has been nested in another top-level class for packaging convenience.
so that's basically the same as Kotlin's (non-inner) nested classes, like your Class1. You probably can't use inner classes (not to organise and automatically run tests, anyway)
You probably want to stick text in a companion object if you're organising your tests in classes (or just a top-level object outside of SampleClass, or just in the top level of the file if you really want - just somewhere it can be accessed by any other class in a "static" way
we can use 3 wayes
use NestedRunner this
use HierarchicalContextRunner this
use Enclosed and the companion object and don't use the inner class
#RunWith(Enclosed::class)
class TEST {
companion object {
var text = "parent class"
}
class Class1 {
#Test
fun `print the text`() {
println(text)
}
}
class Class2 {
#Test
fun `print the text`() {
println(text)
}
}
}

How to write / read internal files securely

I'm trying to create a helper class that will handle reading and writing internal files in my android app using Kotlin.
Here are the links I followed in order:
https://developer.android.com/guide/topics/data/data-storage
https://developer.android.com/training/data-storage/files.html#WriteInternalStorage
https://developer.android.com/training/data-storage/files/internal
https://developer.android.com/topic/security/data
Here's my code:
package com.example.testapp
// Added
import android.content.Context
import java.io.File
// External
import androidx.security.crypto.EncryptedFile
import androidx.security.crypto.MasterKeys
#Suppress("unused")
class SystemMain {
fun writeFile(context: Context) {
// Although you can define your own key generation parameter specification, it's recommended that you use the value specified here.
val keyGenParameterSpec = MasterKeys.AES256_GCM_SPEC
val masterKeyAlias = MasterKeys.getOrCreate(keyGenParameterSpec)
// Creates a file with this name, or replaces an existing file that has the same name. Note that the file name cannot contain path separators.
val fileToWrite = "my_sensitive_data.txt"
val encryptedFile = EncryptedFile.Builder(File(fileToWrite), context, masterKeyAlias, EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB).build()
encryptedFile.bufferedWriter().use { writer ->
writer.write("MY SUPER-SECRET INFORMATION")
}
}
}
Here's my build.gradle:
...
implementation "androidx.lifecycle:lifecycle-extensions:2.1.0"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.1.0"
implementation "androidx.security:security-crypto:1.0.0-alpha02"
...
The error I'm getting is here: encryptedFile.bufferedWriter()
Unresolved reference. None of the following candidates is applicable
because of receiver type mismatch:
#InlineOnly public inline fun File.bufferedWriter(charset: Charset = ..., bufferSize: Int = ...): Buffered Writer defined in kotlin.io
#InlineOnly public inline fun OutputStream.bufferedWriter(charset: Charset = ...): BufferedWriter defined in kotlin.io
Am I missing a reference somewhere? Am I using the incorrect references? Has the code changed and the documentation on the links are outdated?
I'm very new at this. Any advice / help will be appreciated.
After looking at definitions and declarations; I've found this:
encryptedFile.openFileOutput().bufferedWriter().use {writer ->
writer.write("MY SUPER-SECRET INFORMATION")
}
Not sure how well this will work, but there's no error.
Hope this helps someone else.

Kotlin Companion Objection unresolved references

I have a Kotlin class with companion object which sees some fields of the parent class and does not see others. There is no option in Android Studio to import.
class A{
var a = 1
var b = 2
companion object {
a += 1// visible and imported
b += 1// unresolved reference
}
}
I do not want to create this variable inside the companion object.
You are absolutely incorrect.
You cannot access members of class inside companion object at all. But you can use companion`s members in your class.
If you see kotlin bytecode you will see that Companion object compiles to
public static final class Companion {
private Companion() {
}
// $FF: synthetic method
public Companion(DefaultConstructorMarker $constructor_marker) {
this();
}
}
Since Companion is static class it can exist without class where it is declared.
So in your case you can not access a and b because probably they are not exists.
They are not accessable for you too, but probably you cought IDE bug and it doesnt give you error
You cannot access instance variables from static context (companion), this is the same as Java code
Android Studio imported A class variables. In imports i see import package.A.a, but not import package.A.b
import package.A.a simply doesn't make sense for a class property a, and companion object wouldn't require an import from the class it's companion to anyway. My best guess is that it's importing from an object in a different package.

Kotlin extension not recognized in adapter

I have basic extension util for picasso:
public val Context.picasso: Picasso
get() = Picasso.with(this)
public fun ImageView.load(path: String, request: (RequestCreator) -> RequestCreator) {
request(context.picasso.load(path)).into(this)
}
And when I try to call it from imageview context in adapter it's not recognized.
Same thing with itemView.context.picasso
Thanks!
I'm pretty sure your extensions are out of scope (in a different package).
Import your extensions like so:
import your.package.picasso
import your.package.load
Take a look at the docs for more info.

Categories

Resources