How get scope object (like ViewModel, Fragment etc where I inject) in injected object?
I finded only #ActivityContext annotation that give you activity but i need ViewModel
#HiltViewModel
class SomeViewModel #Inject constructor(
savedStateHandle: SavedStateHandle
) : ViewModel() {
#Inject lateinit var someObj: SomeInjectedObject
//some code
}
class SomeInjectedObject #Inject constructor(){
// how can i get here view model link ?
}
I can just set it in init block but it looks like incorrect decision
#HiltViewModel
class SomeViewModel #Inject constructor(
savedStateHandle: SavedStateHandle,
var someObj: SomeInjectedObject
) : ViewModel() {
init{
someObj.vm = this
}
//some code
}
class SomeInjectedObject #Inject constructor(){
var vm: ViewModel
}
Related
I try to Hilt injection in RecyclerView Adapter but it throw me this error;
public final class RecyclerAdapterPhotos extends androidx.recyclerview.widget.RecyclerView.Adapter<com.packagename.projectName.RecyclerAdapters.RecyclerAdapterPhotos.PhotosVH> {
#AndroidEntryPoint base class must extend ComponentActivity, (support) Fragment, View, Service, or BroadcastReceiver.
Head My adapter.
#AndroidEntryPoint
class RecyclerAdapterPhotos(var context:Context, private val photoList:List\<PhotosModelItem\>):RecyclerView.Adapter\<RecyclerAdapterPhotos.PhotosVH\>() {
#Inject
lateinit var imageLoader:ImageLoaderHiltClass
...
override fun onBindViewHolder(holder: PhotosVH, position: Int) {
imageLoader.imageLoader(photoList[position].thumbnailUrl,holder.photosThumbnailVH)
...
Module of Picasso
#Module
#InstallIn(SingletonComponent::class)
object ImageLoaderModule {
#Provides
fun ProvidesImageLoader(photoUri:String,photoVH:ImageView):Picasso{
return Picasso.get()
}
I try to use Hilt for Picasso frame in my recyclerView adapter
I have a main activity as below:
#AndroidEntryPoint
class MainActivity : BaseActivity() {
#Inject
lateinit var configuration: Configuration
...
}
And a module defined like:
#Module
#InstallIn(SingletonComponent::class)
class AppModules {
#Singleton
#Provides
fun bindDeviceConfig(): Configuration {
return Configuration()
}
}
When I try running this it gives an error:
lateinit property configuration has not been initialized
I've looked at the documentation and can't seem to get my head around why I'm getting this issue. Does anyone know why?
It is code worked in java but after convert to kotlin it does not compile.
Having a base class which has some defines as static protected member in the companion object:
abstract class ParentClass {
companion object {
#JvmField
final protected val SERVICE_TYPE_A = "the_service_type_a"
}
}
and the child class:
class ChildClass: ParentClass {
public override fun getServiceType(): String {
return SERVICE_TYPE_A. //<== got compile error
}
}
it does not compile.
how to access a parent class static protected member from subclass?
You need to use #JvmStatic instead as follows:
abstract class ParentClass {
companion object {
#JvmStatic
protected val SERVICE_TYPE_A = "the_service_type_a"
}
abstract fun getServiceType(): String
}
The final keyword in SERVICE_TYPE_A is redundant since everything is final by default in Kotlin. This also mean that if you want ParentClass to be extended, then you need to explicitly define it as open.
Then your ChildClass would look as follows:
class ChildClass: ParentClass() {
override fun getServiceType(): String {
return SERVICE_TYPE_A
}
}
The Code A is from the aritcle https://developer.android.com/training/dependency-injection/hilt-android
In my mind, a abstract class can not include non-abstract class .
But the function abstract fun bindAnalyticsService( analyticsServiceImpl: AnalyticsServiceImpl): AnalyticsService accept a non-abstract class parameter, why?
Code A
interface AnalyticsService {
fun analyticsMethods()
}
// Constructor-injected, because Hilt needs to know how to
// provide instances of AnalyticsServiceImpl, too.
class AnalyticsServiceImpl #Inject constructor(
...
) : AnalyticsService { ... }
#Module
#InstallIn(ActivityComponent::class)
abstract class AnalyticsModule {
#Binds
abstract fun bindAnalyticsService(
analyticsServiceImpl: AnalyticsServiceImpl
): AnalyticsService
}
I'm trying to set up a very basic field injection using Dagger2 with the following structure:
class ToInject {}
class Injected {
#Inject
var toInject: ToInject? = null
}
#Module
object BaseModule {
var toInject: ToInject? = null
#Provides
#JvmStatic
fun toInjectProvider(): ToInject {
if (toInject == null) {
toInject = ToInject()
}
return toInject as ToInject
}
}
The field I'm trying to inject is definately PUBLIC but the compiler returns the following error
Dagger does not support injection into private fields
Can anyone please explain why am I getting this error and how to fix it?
BTW constructor injection works:
class Injected #Inject constructor(var toInject: ToInject){}
Try explicitly annotating the setter method:
class Injected {
#set:Inject
var toInject: ToInject? = null
}
or
class Injected {
var toInject: ToInject? = null
#Inject set
}
You can also annotate your field as #JvmField:
class Injected {
#JvmField
#Inject
var toInject: ToInject? = null
}
The problem is how Kotlin is translated to Java.
This Kotlin class:
class Injected {
var toInject: ToInject? = null
}
actually becomes this Java class:
public final class Injected {
#Nullable
private ToInject toInject;
#Nullable
public final ToInject getToInject() {
return this.toInject;
}
public final void setToInject(#Nullable ToInject value) {
this.toInject = value;
}
}
So despite the fact you set your field public in Kotlin, under the hood it's just a private field with a public setter and getter.
I am having similar issue while injecting primitive Int value. Only adding #JvmField worked for me. Thanks #jsamol for pointing out.
#JvmField
#Inject
#Named(NAMED_APP_LOGO)
var appLogo: Int = 0