Home > Enterprise >  Hilt field injection android
Hilt field injection android

Time:03-14

here I am trying to inject the adapter in activity via field injection. Adapter has a parameter(list). Can somebody assist me here? i am facing compile time error cannot be provided without an @Provides-annotated method.

Please refer below code

@AndroidEntryPoint
class RecipeActivity() : PostLoginActivity() {

    var TAG = MainActivity::class.java.simpleName
    private lateinit var binding: ActivityRecipeBinding
    private val viewModel: RecipeViewModel by viewModels()
    @Inject lateinit var adapter: RecipeAdapter


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    }
}


class RecipeAdapter @Inject constructor(list: MutableList<RecipeModel> ) :
    BaseAdapter<RecipeModel>(list) {
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseViewHolder<RecipeModel> {
        return RecipeViewHolder(
            LayoutInflater.from(parent.context).inflate(R.layout.item_recipe, parent, false), this
        )
    }

    override fun onBindViewHolder(holder: BaseViewHolder<RecipeModel>, position: Int) {
        holder.bindData(baseList[position])
    }
}

data class RecipeModel(
    var title: String,
    var imageType: String,
    var url: String
) : Item()

CodePudding user response:

Well as an error suggests you need to have a module in which you provide default construction of you adapter. Example:

@Module
@InstallIn(ActivityComponent::class)
object AppModule {

    @Provides
    fun provideRecipeAdapter(
        list: MutableList<RecipeModel>
    ): RecipeAdapter {
        return RecipeAdapter(list)
    }
}

This is just an example of what you are missing, not actual working code. For more details of how to create these modules look at the documentation

CodePudding user response:

In order to Inject a class, Hilt/Dagger needs to understand exactly how to Inject it. In your project, you should have a 'Module' class. Within here, you can create @Provides methods, which tell Hilt/Dagger exactly what a class looks like so that it can be injected (find out more here).

For example, to provide a class that implements some Android Retrofit services, you might have a module that looks like:

@Module
@InstallIn(ActivityComponent::class)
object AnalyticsModule {

  @Provides
  fun provideAnalyticsService(
    // Potential dependencies of this type
  ): AnalyticsService {
      return Retrofit.Builder()
               .baseUrl("https://example.com")
               .build()
               .create(AnalyticsService::class.java)
  }
}

In this example, we can now use @Inject for an AnalyticsService, as Hilt/Dagger now knows how to make one!

In your scenario, it looks like your adapter needs to be constructed with a list of RecipeModels. As you will unlikely have access to this data at the Module level, I don't think you want to be injecting the Adapter like this? Simply creating it in the Activity should be sufficient for what you need!

Something like this:

private var adapter: RecipeAdapter? = null // OR
lateinit var adapter: RecipeAdapter

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    adapter = RecipeAdapter(viewModel.recipeModels)
}

As a rule of thumb, it is generally more common to use injection for services, factories and view models rather than UI elements like adapters, as these UI elements need to often be constructed with actual data which isn't available in an application's Hilt/Dagger module.

  • Related