Room,Kotlin,Dagger 2.15如果没有@Inject构造函数或@ Provide-annotated方法

时间:2018-03-26 06:30:41

标签: android kotlin dagger-2 android-room dagger

我使用dagger for Room Module进行了以下实现。这会导致在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

失败:构建因异常而失败。

2 个答案:

答案 0 :(得分:1)

AppComponent @BindsInstance Builder遗失了@Component.Builder interface Builder : AndroidInjector.Builder<App> { @BindsInstance Builder application(Application application); AppComponent build(); }

import UIKit

class WebController: UIViewController, UIPickerViewDelegate, 
UIPickerViewDataSource {

    @IBOutlet weak var itemLabel: UILabel!

    @IBOutlet weak var urlLabel: UILabel!

    @IBOutlet weak var webView: UIWebView!

    var states = [
    ["title": "Alabama","link": "https://www.dmv.org/al-alabama/"],
    ["title": "Alaska", "link": ""],
    ["title": "Arizona", "link": ""],
    ["title": "Arkansas", "link": ""],
    ["title": "California", "link": ""],
    ["title": "Colorado", "link": ""],
    ["title": "Connecticut", "link": ""],
    ["title": "Deleware", "link": ""],
    ["title": "Florida", "link": ""],
    ["title": "Georgia", "link": ""],
    ["title": "Hawaii", "link": ""],
    ["title": "Idaho", "link": ""],
    ["title": "Illinois", "link": ""],
    ["title": "Indiana", "link": ""],
    ["title": "Iowa", "link": ""],
    ["title": "Kansas","link": ""],
    ["title": "Kentucky", "link": ""],
    ["title": "Louisiana", "link": ""],
    ["title": "Maine", "link": ""],
    ["title": "Maryland", "link": ""],
    ["title": "Massachusetts", "link": ""],
    ["title": "Michigan", "link": ""],
    ["title": "Minnesota", "link": ""],
    ["title": "Mississippi", "link": ""],
    ["title": "Missouri", "link": ""],
    ["title": "Montana", "link": ""],
    ["title": "Nebraska", "link": ""],
    ["title": "Nevada", "link": ""],
    ["title": "New Hampshire", "link": ""],
    ["title": "New Jersey", "link": ""],
    ["title": "New Mexico", "link": ""],
    ["title": "New York", "link": ""],
    ["title": "North Carolina", "link": ""],
    ["title": "North Dakota", "link": ""],
    ["title": "Ohio", "link": ""],
    ["title": "Oklahoma", "link": ""],
    ["title": "Oregon", "link": ""],
    ["title": "Pennsylvania", "link": ""],
    ["title": "Rhode Island", "link": ""],
    ["title": "South Carolina", "link": ""],
    ["title": "South Dakota", "link": ""],
    ["title": "Tennessee", "link": ""],
    ["title": "Texas", "link": ""],
    ["title": "Utah", "link": ""],
    ["title": "Vermont", "link": ""],
    ["title": "Virginia", "link": ""],
    ["title": "Washington", "link": ""],
    ["title": "West Virginia", "link": ""],
    ["title": "Wisconsin", "link": ""],
    ["title": "Wyoming", "link": ""]
    ]//end states[] array

    override func viewDidLoad() {
        super.viewDidLoad()
        itemLabel.text = states[0]["title"]
        urlLabel.text = states[0]["link"]
    }//end viewDidLoad()


    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }//end didReceiveMemoryWarning()


    //How many parts to the wheel do you need?
    func numberOfComponents(in pickerView: UIPickerView) -> Int{
        return 1
    }//end numberOfComponents


    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int{
        return states.count
    }//end numberOfRowsInComponent


    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String?{
        return states[row]["title"]
    }//end titleForRow


    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        var itemSelected = states[row]["title"]
        var urlSelected = states[row]["link"]
        itemLabel.text = itemSelected
        urlLabel.text = urlSelected
    }//end didSelectRow


    @IBAction func submitStateBtn(_ sender: UIButton) {
        let url = URL(string: "http://www.google.com")//this line needs to change
        let requestObj = URLRequest(url: url!)
        webView.loadRequest(requestObj)
    }//end submitStateBtn

}//end WebController() class

答案 1 :(得分:-1)

我使用下面代码使用的dagger 2提供了简单的房间数据库演示,但它是可以轻松转换为kotlin的java代码。

步骤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:为房间数据库定义模块类..

@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类..

@Dao
public interface HeroDao {
    @Insert
    void insertRecord(Hero hero);
}

第5步:定义commpoent类..

@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:使用房间db或者注入..提供使用房间将数据插入表格的完整代码。

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("");

    }
}