Kotlin: Unresolved reference to member function Intellisense suggests? - android

I am learning kotlin in android studio, and I must be making a syntax error.
I have the class:
abstract class RoomDB : RoomDatabase() {
fun getInstance(context:Context) : RoomDB {
// either finds an existing database or makes a new one
// returns the database
}
}
Later I am writing the following code:
import android.example.app.Database.RoomDB
class MainActivity : AppCompatActivity() {
lateinit var database:RoomDB
override fun onCreate(savedInstanceState: Bundle?) {
database = RoomDB.getInstance(this)
}
}
Autocomplete suggests the getInstance method; however, when I write this code, I get an unresolved reference error to this method. Any idea why?

At the suggestion of Slaw I put the method declaration inside of a companion object which fixed the compile errors. I do not understand why that fixed this.
abstract class RoomDB : RoomDatabase() {
companion object {
fun getInstance(context:Context) : RoomDB {
// either finds an existing database or makes a new one
// returns the database
}
}
}

Related

Kotlin - Companion object not allowed in an inner class

I am trying to create a test class with an inner class but I am getting an error "companion object is not allowed here". What is supposedly be the problem? Please see my sample code snippet below. And also i am using JUnit4 for this development.
#RunWith(Enclosed::class)
class OuterUnitTest{
#RunWith(Parameterized::class)
inner class Inner1UnitTest {
#Test
fun testInner1(){
// test code here
}
companion object{
#JvmStatic
#Parameterized.Parameters
fun testData() : Any? {
return something
}
}
}
}

Kotlin, Dagger and Realm - DI concept problem

I'm starting this brand new project only for fun, but at the first steps I got a problem, there it goes:
I have this class "Note", it's a realm class as you can see below
#RealmClass
open class Note
#Inject constructor (#PrimaryKey var id: String,
var text: String,
var badge: NoteBadge?
) : RealmObject() {
fun getRandomNoteText(): String = "supposed to be random"
}
Then I have my Main activity class, where I already got Dagger working.
class MainActivity : AppCompatActivity() {
#Inject lateinit var note: Note
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
DaggerNoteComponent.create().inject(this)
Log.d("MAIN_ACTIVITY", note.getRandomNoteText())
Log.d("MAIN_ACTIVITY", note.badge?.getRandomBadgeText())
}
}
It got tricky in terms of concepts, the code above doesn't compile, I have to add this line to my Note class to make it work:
constructor(): this(UUID.randomUUID().toString(), "", NoteBadge()){}
However there I have NoteBadge() I'm creating an instance of NoteBadge manually, that's bad, I would like dagger did that.
I've tried sending a null value as parameter, but them I have a null NoteBadge at my MainActivity.
So do you have any idea how to fix that and make my dependency injection fully funcional? With no manual instance initializations?
EDIT -> Paste NoteComponent
#Component(modules = [NoteBadgeModule::class])
interface NoteComponent {
fun inject(activity: MainActivity)
}

Why not show data when use Dagger2 on Android

In my application i want use Dagger2 and i want show just one image from server and for show image i used Picasso.
I write below codes, but after run application not show me any image into imageview!
For android i use Kotlin language.
Application class :
class App : Application() {
var component: AppComponent? = null
override fun onCreate() {
super.onCreate()
//Init dagger component
component = DaggerAppComponent.builder().modulePicasso(ModulePicasso(this)).build()
}
fun getAppComponent(): AppComponent? {
return component
}
}
Activity class :
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
App().getAppComponent()?.getPicasso()?.load("https://cdn01.zoomit.ir/2017/6/5f0e97c1-9eb7-4176-aa02-35252489ede8.jpg")
?.into(imageView)
}
}
How can i fix it?
I think it's because you are creating a new instance of you application class, eg. App() and then calling getAppComponent() which for sure returns null, as you should not construct the application instance yourself, but instead access a static property referencing it.
To fix it, you need to add a static property (instance) to the App class and get the AppComponent using that property.

Error using Dagger 2 with Kotlin in Android Studio

I am new to Dagger 2 and I am trying to learn it with Kotlin. Let me explain my Project structure first. I am having a Class name "Info":
class Info constructor(var message: String) {}
I have created a module for this class "InfoModule"
#Module
class InfoModule {
#Provides #Choose("HELLO")
fun sayHello(): Info{
return Info(message = "Hello dagger 2")
}
#Provides #Choose("HI")
fun sayHi(): Info{
return Info(message = "Hi dagger 2")
}
}
I have created a component interface for this module named "MagicBox"
#Component(modules = [InfoModule::class])
interface MagicBox {
fun poke(app: MainActivity)
}
Then in the MainActivity I have injected the two fields for "Info"
class MainActivity : AppCompatActivity() {
var textView: TextView? = null;
#Inject #field:Choose("HELLO") lateinit var infoHello: Info
#Inject #field:Choose("HI") lateinit var infoHi: Info
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
DaggerMagicBox.create().poke(this)
textView = findViewById<TextView>(R.id.textView)
textView!!.text = infoHi.message
}
}
#Qualifier
#MustBeDocumented
#kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
annotation class Choose(val value: String)
As you see above I haved created a #Choose annotation to learn how #Qualifier works. Up to here the code works perfectly and it is really a magic of Dagger :).
PROBLEM STARTS HERE:>>
Then I decided to Inject another field called "car" inside my MainActivity in the same way the "info" field is injected in the MainActivity. To do that first i need a Car class.
class Car constructor(var engine: Engine, var wheels: Wheels) {
fun drive(){
Log.d("Car","Driving")
}
}
Now the car class needs Engine and Wheels. So below are Engine and Wheel classes
Engine Class:
class Engine {
}
Wheel Class:
class Wheels {
}
Then I have created a Module for Car class
#Module
class CarModule {
#Provides
fun provideEngine(): Engine{
return Engine()
}
#Provides
fun provideWheel(): Wheels{
return Wheels()
}
#Provides #Choose("NewCar")
fun provideCar(engine: Engine, wheels: Wheels): Car{
Log.d("NewCar", "Created")
return Car(engine, wheels)
}
}
The component for Car is below
#Component (modules = [CarModule::class])
interface CarComponent {
fun injectCar(mainActivity: MainActivity)
}
Then I have injected the car field in the MainActivity and I have tried to called the "drive" method of Car class.
Now my MainActivity looks like this.
class MainActivity : AppCompatActivity() {
var textView: TextView? = null;
#Inject #field:Choose("HELLO") lateinit var infoHello: Info
#Inject #field:Choose("HI") lateinit var infoHi: Info
#Inject #field:Choose("NewCar") lateinit var car: Car
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
DaggerMagicBox.create().poke(this)
textView = findViewById<TextView>(R.id.textView)
textView!!.text = infoHi.message
DaggerCarComponent.create().injectCar(this)
car.drive()
}
}
#Qualifier
#MustBeDocumented
#kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
annotation class Choose(val value: String)
The Logcat Error after MakeProject:
error: [Dagger/MissingBinding] #de.test.testtheapp.Choose("HELLO") de.test.testtheapp.Api.Info cannot be provided without an #Provides-annotated method.
public abstract interface CarComponent {
^
#de.test.testtheapp.Choose("HELLO") de.test.testtheapp.Api.Info is injected at
de.test.testtheapp.MainActivity.infoHello
de.test.testtheapp.MainActivity is injected at
de.test.testtheapp.Components.CarComponent.injectCar(de.test.testtheapp.MainActivity)
What i really find strange is that although the "info" field injection was working prefectly before, why after adding car field injection, the logcat is now showing error about info field injection or Info class. I know its also saying something about "CarComponent". Now nothing is working. Even the "DaggerMagicBox" is unresolved. I am clueless about the error and I am stuck on this since two days. My knowledge about dagger is very limited that I don't know what is the solution. I will be very thankful if some give me a clue. I am using Android Studio 3.5.1 and Dagger version 2.21
You are trying to use CarComponent to inject dependencies of MainActivity:
DaggerCarComponent.create().injectCar(this)
But your CarComponent doesn't have a way to provide Info:
#Inject #field:Choose("HELLO") lateinit var infoHello: Info
Because the provider method is defined in InfoModule and CarComponent doesn't have it in its modules list.
You are using two components to inject the dependencies of MainActivity:
DaggerMagicBox.create().poke(this)
...
DaggerCarComponent.create().injectCar(this)
You should only use one.
Either add the CarModule to the list of modules of MagicBox and remove DaggerCarComponent.create().injectCar(this).
Or add the InfoModule to the list of modules of CarComponent and remove DaggerMagicBox.create().poke(this)

add extension on Log in android (Kotlin)

I use this code to add extension for Log class android
fun Log.i2(msg:String):Unit{
Log.i("Test",msg)
}
when using in the activity
class MainActivity: AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Log.i2("activity_main")
}
}
Log.i2 not found. What's wrong?
To achieve extension function in static class, you need to write extension of the companion object(refer this)
fun Log.Companion.i2(msg:String) {
...
}
You have created Extension function of Class Log.
Which is suppose to call by Instance of Class Log. You are trying to treat extension function as static and calling it by Class name. Which is not correct in the case
Currently, static extension methods in Kotlin is not supported without the companion object, because android.util.Log is a java class, so there is no companion object.
Instead, I recommend you to use a static function (package-level function, simply declared outside a class in a source code file):
fun logI2(msg: String) {
Log.i("Test", msg)
}
And just use it like this:
logI2("activity_main")

Categories

Resources