Room,Kotlin,Dagger 2.15 android.app.Application не может быть предоставлена без конструктора @Inject или с помощью аннотированного метода @Provides
У меня есть следующая реализация с кинжалом для комнатного модуля. Это вызывает ошибку при введении RoomMoule
на ViewModel
учебный класс. Ниже приведен мой код:
Приложение
class App : DaggerApplication(), HasActivityInjector {
@Inject
lateinit var activityDispatchInjector: DispatchingAndroidInjector<Activity>
override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
return DaggerAppComponent.builder().create(this)
}
override fun activityInjector(): DispatchingAndroidInjector<Activity> {
return activityDispatchInjector
}
}
AppModule
@Module
class AppModule {
@Provides
@Singleton
fun providesContext(app: Application): Context = app
}
RoomModule
@Module
class RoomModule {
@Singleton
@Provides
fun provideAppDatabase(context: Context): AppRoomDataBase =
Room.databaseBuilder(context,
AppRoomDataBase::class.java, "sample.db")
.build()
@Singleton
@Provides
fun provideRepository(appRoomDataBase: AppRoomDataBase): ResultRepository {
return ResultRepository(appRoomDataBase)
}
}
AppComponent
@Singleton
@Component(modules = [
(AndroidSupportInjectionModule::class),
(AppModule::class),
(ActivityModule::class),
(FragmentModule::class),
(ViewModelModule::class),
(RoomModule::class)])
interface AppComponent : AndroidInjector<App> {
@Component.Builder
abstract class Builder : AndroidInjector.Builder<App>()
}
HomeViewModel
class HomeViewModel @Inject constructor() : ViewModel() {
@Inject lateinit var resultRepository: ResultRepository
private var liveList: LiveData<List<Result>>? = null
fun getResults(): LiveData<List<Result>>? {
liveList = resultRepository.findAll()
return liveList
}
}
ResultRepository
class ResultRepository(appRoomDB : AppRoomDataBase) {
val mAppDb : AppRoomDataBase = appRoomDB
fun findAll(): LiveData<List<Result>> {
return mAppDb.resultDao().getAll()
}
}
При построении этого я получаю ошибку как
AppComponent.java:11: error: [dagger.android.AndroidInjector.inject(T)]
android.app.Application cannot be provided without an @Inject constructor or
from an @Provides-annotated method.
public abstract interface AppComponent extends
dagger.android.AndroidInjector<com.dailypay.base.App> {
^
android.app.Application is injected at
com.dailypay.di.AppModule.providesContext(app)
android.content.Context is injected at
com.dailypay.di.RoomModule.provideAppDatabase(context)
com.dailypay.room.AppRoomDataBase is injected at
com.dailypay.di.RoomModule.provideRepository(appRoomDataBase)
com.dailypay.repo.ResultRepository is injected at
com.dailypay.ui.home.HomeViewModel.resultRepository
com.dailypay.ui.home.HomeViewModel is injected at
com.dailypay.di.ViewModelModule.bindMainViewModel(mainViewModel)
java.util.Map<java.lang.Class<? extends android.arch.lifecycle.ViewModel>,javax.inject.Provider<android.arch.lifecycle.ViewModel>> is injected at
com.dailypay.di.ViewModelFactory.<init>(creators)
com.dailypay.di.ViewModelFactory is injected at
com.dailypay.di.ActivityModule.bindViewModelFactory(factory)
android.arch.lifecycle.ViewModelProvider.Factory is injected at
com.dailypay.ui.home.HomeFragment.viewModelFactory
com.dailypay.ui.home.HomeFragment is injected at
dagger.android.AndroidInjector.inject(arg0)
: app: kaptDebugKotlin FAILED
FAILURE: сборка не удалась, исключение.
2 ответа
Ваш AppComponent
отсутствует @BindsInstance
в Builder
,
@Component.Builder
interface Builder : AndroidInjector.Builder<App> {
@BindsInstance Builder application(Application application);
AppComponent build();
}
Я предоставил простую демонстрационную версию БД для комнаты с использованием dagger 2, использованного ниже, но это Java-код, который вы легко можете конвертировать в kotlin.
Шаг 1: Определите класс pojo для таблицы, а класс определите аннотацию @Entity. Шаг 2: Определите в этом классе класс базы данных, как показано ниже...
@Database(entities = {Hero.class, User.class}, version = 1)
public abstract class DemoDatabase extends RoomDatabase {
public abstract HeroDao getHeroDao();
public abstract UserDao getUserDao();
}
Шаг 3: Определите класс модуля для комнаты db.
@Module
public class RoomDbModule {
private DemoDatabase demoDatabase;
public RoomDbModule(Application application) {
demoDatabase= Room.databaseBuilder(application,DemoDatabase.class,"DemoDb").allowMainThreadQueries().build();
}
@Provides
@Singleton
DemoDatabase getDemoDatabase(){
return demoDatabase;
}
}
Шаг 4: Определите класс Дао.
@Dao
public interface HeroDao {
@Insert
void insertRecord(Hero hero);
}
Шаг 5: определить класс компонента.
@Singleton
@Component(modules = {AppModule.class, NetModule.class, RoomDbModule.class, DbHelperModule.class})
public interface ApiComponent {
void injectApi(MainActivity activity);
void roomDb(InsertActivity insertActivity);
void roomDb(PageingActivity pageingActivity);
void dbHelper(AppCompatActivity appCompatActivity);
}
Шаг 6: Определите AppActivity как уровень приложения и перейдите в файл манифеста...
public class AppActivity extends Application {
private ApiComponent component;
@Override
public void onCreate() {
super.onCreate();
component = DaggerApiComponent.builder()
.appModule(new AppModule(this))
.roomDbModule(new RoomDbModule(this))
.dbHelperModule(new DbHelperModule(new DbHelper(this, "UserDb", 1)))
.netModule(new NetModule("https://api.github.com")).build();
}
public ApiComponent getComponent() {
return component;
}
}
и определите в файле манифеста в теге приложения, используемом ниже
android:name=".app.AppActivity" // your activity name.
Шаг 7: Используется Room db или inject. Укажите полный код для вставки данных в таблицу, используя комнату.
public class InsertActivity extends BaseActivity {
private EditText mEtName,mEtRealName,mEtTeamName;
private Button mBtnInsert;
@Inject
DemoDatabase demoDatabase;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.insert_activity);
((AppActivity)getApplication()).getComponent().roomDb(this);
initView();
}
private void initView() {
mEtTeamName=findViewById(R.id.iaEtTeamName);
mEtName=findViewById(R.id.iaEtName);
mEtRealName=findViewById(R.id.iaEtRealName);
mBtnInsert=findViewById(R.id.iaBtnInsert);
mBtnInsert.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
insertData();
}
});
}
private void insertData() {
Hero hero=new Hero();
hero.setName(mEtName.getText().toString().trim());
hero.setRealname(mEtRealName.getText().toString().trim());
hero.setTeam(mEtTeamName.getText().toString().trim());
demoDatabase.getHeroDao().insertRecord(hero);
Toast.makeText(getApplicationContext(),"Insert Successfully",Toast.LENGTH_SHORT).show();
mEtRealName.setText("");
mEtName.setText("");
mEtTeamName.setText("");
}
}