使用 Dagger 和 Room 在多个 Activity 中进行依赖注入
Dependency Injection in multiple Activities with Dagger and Room
我是 Android 的新手,有 c# 背景,遇到过使用 Dagger 进行依赖注入。我设法创建了一个简单的示例,但想知道如何在另一个 activity 中使用我的存储库(我尝试在此处使用存储库模式)。所以我的结构如下:
当我尝试在我的 MainActivity class 中创建锻炼时,它工作得很好。所以我在我的 AddWorkoutActivity class
中添加了以下行
@Inject
public WorkoutRepository workoutRepository;
但是当我尝试保存锻炼时,我总是在 workoutRepository 上收到空引用错误,所以我确实错过了一些关于 DI 在这里工作的理解。也许有人可以给我提示我必须做什么,以便我的存储库在我的 Activity.
中以正确的方式实例化
// 编辑:
我认为问题是我在 MainActivity class 的 onCreate 方法中调用了 DaggerAppComponent.builder()...,所以 AddWorkoutActivity 什么都不知道那个。但是我应该在哪里初始化 DaggerAppComponent 以便两个活动都能正确访问它?
此致
应用程序组件:
package jh.projects.wodm8.di;
import android.app.Application;
import javax.inject.Singleton;
import dagger.Component;
import jh.projects.wodm8.view.MainActivity;
import jh.projects.wodm8.data.WorkoutDao;
import jh.projects.wodm8.repository.DemoDatabase;
import jh.projects.wodm8.repository.WorkoutRepository;
@Singleton
@Component(modules = {AppModule.class, RoomModule.class})
public interface AppComponent {
void inject(MainActivity mainActivity);
WorkoutDao workoutDao();
DemoDatabase demoDatabase();
WorkoutRepository productRepository();
Application application();
}
AppModule
package jh.projects.wodm8.di;
import android.app.Application;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class AppModule {
Application mApplication;
public AppModule(Application application) {
mApplication = application;
}
@Provides
@Singleton
Application providesApplication() {
return mApplication;
}
}
房间模块
package jh.projects.wodm8.di;
import android.app.Application;
import androidx.room.Room;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
import jh.projects.wodm8.data.WorkoutDao;
import jh.projects.wodm8.repository.DemoDatabase;
import jh.projects.wodm8.repository.WorkoutDataSource;
import jh.projects.wodm8.repository.WorkoutRepository;
@Module
public class RoomModule{
private DemoDatabase demoDatabase;
public RoomModule(Application mApplication) {
demoDatabase = Room.databaseBuilder(mApplication, DemoDatabase.class, "demo-db").allowMainThreadQueries().build();
}
@Singleton
@Provides
DemoDatabase providesRoomDatabase() {
return demoDatabase;
}
@Singleton
@Provides
WorkoutDao providesWorkoutDao(DemoDatabase demoDatabase) {
return demoDatabase.getWorkoutDao();
}
@Singleton
@Provides
WorkoutRepository providesWorkoutRepository(WorkoutDao workoutDao) {
return new WorkoutDataSource(workoutDao);
}
}
WorkoutDataSource
package jh.projects.wodm8.repository;
import androidx.lifecycle.LiveData;
import java.util.List;
import javax.inject.Inject;
import jh.projects.wodm8.data.Workout;
import jh.projects.wodm8.data.WorkoutDao;
public class WorkoutDataSource implements WorkoutRepository {
private WorkoutDao workoutDao;
@Inject
public WorkoutDataSource(WorkoutDao workoutDao) {
this.workoutDao = workoutDao;
}
@Override
public LiveData<Workout> findById(int id) {
return workoutDao.findById(id);
}
@Override
public LiveData<List<Workout>> findAll() {
return workoutDao.findAll();
}
@Override
public void insert(Workout workout) {
workoutDao.insert(workout);
}
@Override
public int delete(Workout workout) {
return workoutDao.delete(workout);
}
}
WorkoutRepository
package jh.projects.wodm8.repository;
import androidx.lifecycle.LiveData;
import java.util.List;
import jh.projects.wodm8.data.Workout;
public interface WorkoutRepository {
LiveData<Workout> findById(int id);
LiveData<List<Workout>> findAll();
void insert(Workout workout);
int delete(Workout workout);
}
主要Activity
包裹 jh.projects.wodm8.view;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.Observer;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.util.List;
import javax.inject.Inject;
import jh.projects.wodm8.R;
import jh.projects.wodm8.data.Workout;
import jh.projects.wodm8.di.AppModule;
import jh.projects.wodm8.di.DaggerAppComponent;
import jh.projects.wodm8.di.RoomModule;
import jh.projects.wodm8.repository.WorkoutRepository;
public class MainActivity extends AppCompatActivity {
@Inject
public WorkoutRepository workoutRepository;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(view.getContext(), AddWorkoutActivity.class);
startActivity(intent);
}
});
DaggerAppComponent.builder()
.appModule(new AppModule(getApplication()))
.roomModule(new RoomModule(getApplication()))
.build()
.inject(this);
workoutRepository.findAll().observe(this, new Observer<List<Workout>>() {
@Override
public void onChanged(@Nullable List<Workout> products) {
Toast.makeText(MainActivity.this, String.format("Product size: %s", products.size()), Toast.LENGTH_SHORT).show();
}
});
}
}
添加锻炼Activity
package jh.projects.wodm8.view;
import androidx.appcompat.app.AppCompatActivity;
import jh.projects.wodm8.R;
import jh.projects.wodm8.data.Workout;
import jh.projects.wodm8.di.AppModule;
import jh.projects.wodm8.di.DaggerAppComponent;
import jh.projects.wodm8.di.RoomModule;
import jh.projects.wodm8.repository.DemoDatabase;
import jh.projects.wodm8.repository.WorkoutRepository;
import android.app.Application;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import javax.inject.Inject;
public class AddWorkoutActivity extends AppCompatActivity {
@Inject
public WorkoutRepository workoutRepository;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_workout);
final Button button = findViewById(R.id.saveWorkout);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Workout workout = new Workout();
EditText txtTitle = (EditText) findViewById(R.id.workoutTitleText);
workout.setTitle(txtTitle.getText().toString());
try {
workoutRepository.insert(workout);
} catch (Exception e) {
Log.v("AddWorkout", e.getMessage());
}
Toast.makeText(AddWorkoutActivity.this, "Inserted", Toast.LENGTH_SHORT).show();
}
});
}
}
// 编辑:
感谢 a_local_nobody 提供以 Dagger 开头的链接:
https://youtu.be/Qwk7ESmaCq0
我找到了另一个从 dagger 开始的资源,这对我也有帮助:
https://www.raywenderlich.com/262-dependency-injection-in-android-with-dagger-2-and-kotlin#toc-anchor-005
给你一个更完整的答案,取自这个在线资源 https://github.com/MindorksOpenSource/android-dagger2-example/blob/master/app/src/main/java/com/mindorks/example/android_dagger2_example/DemoApplication.java
(我只是简单地回顾一下,以便您更好地理解)
创建一个扩展应用程序的应用程序 class 并实现它:
@Override
public void onCreate() {
super.onCreate();
applicationComponent = DaggerApplicationComponent
.builder()
.applicationModule(new ApplicationModule(this))
.build();
applicationComponent.inject(this);
}
尽管如此,您必须定义自己的 applicationComponent,这里只是简单介绍一下。
在那之后,你应该能够在几个不同的地方使用你的存储库,在你需要的地方使用 @Inject
的注释,只记得在你需要的地方实际调用注入,利用
getActivityComponent().inject(this);
或 AndroidInjection.inject(this)
,希望这个 github 示例和教程足以回答您的一些问题
我是 Android 的新手,有 c# 背景,遇到过使用 Dagger 进行依赖注入。我设法创建了一个简单的示例,但想知道如何在另一个 activity 中使用我的存储库(我尝试在此处使用存储库模式)。所以我的结构如下:
@Inject
public WorkoutRepository workoutRepository;
但是当我尝试保存锻炼时,我总是在 workoutRepository 上收到空引用错误,所以我确实错过了一些关于 DI 在这里工作的理解。也许有人可以给我提示我必须做什么,以便我的存储库在我的 Activity.
中以正确的方式实例化// 编辑: 我认为问题是我在 MainActivity class 的 onCreate 方法中调用了 DaggerAppComponent.builder()...,所以 AddWorkoutActivity 什么都不知道那个。但是我应该在哪里初始化 DaggerAppComponent 以便两个活动都能正确访问它?
此致
应用程序组件:
package jh.projects.wodm8.di;
import android.app.Application;
import javax.inject.Singleton;
import dagger.Component;
import jh.projects.wodm8.view.MainActivity;
import jh.projects.wodm8.data.WorkoutDao;
import jh.projects.wodm8.repository.DemoDatabase;
import jh.projects.wodm8.repository.WorkoutRepository;
@Singleton
@Component(modules = {AppModule.class, RoomModule.class})
public interface AppComponent {
void inject(MainActivity mainActivity);
WorkoutDao workoutDao();
DemoDatabase demoDatabase();
WorkoutRepository productRepository();
Application application();
}
AppModule
package jh.projects.wodm8.di;
import android.app.Application;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
@Module
public class AppModule {
Application mApplication;
public AppModule(Application application) {
mApplication = application;
}
@Provides
@Singleton
Application providesApplication() {
return mApplication;
}
}
房间模块
package jh.projects.wodm8.di;
import android.app.Application;
import androidx.room.Room;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
import jh.projects.wodm8.data.WorkoutDao;
import jh.projects.wodm8.repository.DemoDatabase;
import jh.projects.wodm8.repository.WorkoutDataSource;
import jh.projects.wodm8.repository.WorkoutRepository;
@Module
public class RoomModule{
private DemoDatabase demoDatabase;
public RoomModule(Application mApplication) {
demoDatabase = Room.databaseBuilder(mApplication, DemoDatabase.class, "demo-db").allowMainThreadQueries().build();
}
@Singleton
@Provides
DemoDatabase providesRoomDatabase() {
return demoDatabase;
}
@Singleton
@Provides
WorkoutDao providesWorkoutDao(DemoDatabase demoDatabase) {
return demoDatabase.getWorkoutDao();
}
@Singleton
@Provides
WorkoutRepository providesWorkoutRepository(WorkoutDao workoutDao) {
return new WorkoutDataSource(workoutDao);
}
}
WorkoutDataSource
package jh.projects.wodm8.repository;
import androidx.lifecycle.LiveData;
import java.util.List;
import javax.inject.Inject;
import jh.projects.wodm8.data.Workout;
import jh.projects.wodm8.data.WorkoutDao;
public class WorkoutDataSource implements WorkoutRepository {
private WorkoutDao workoutDao;
@Inject
public WorkoutDataSource(WorkoutDao workoutDao) {
this.workoutDao = workoutDao;
}
@Override
public LiveData<Workout> findById(int id) {
return workoutDao.findById(id);
}
@Override
public LiveData<List<Workout>> findAll() {
return workoutDao.findAll();
}
@Override
public void insert(Workout workout) {
workoutDao.insert(workout);
}
@Override
public int delete(Workout workout) {
return workoutDao.delete(workout);
}
}
WorkoutRepository
package jh.projects.wodm8.repository;
import androidx.lifecycle.LiveData;
import java.util.List;
import jh.projects.wodm8.data.Workout;
public interface WorkoutRepository {
LiveData<Workout> findById(int id);
LiveData<List<Workout>> findAll();
void insert(Workout workout);
int delete(Workout workout);
}
主要Activity 包裹 jh.projects.wodm8.view;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.Observer;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import java.util.List;
import javax.inject.Inject;
import jh.projects.wodm8.R;
import jh.projects.wodm8.data.Workout;
import jh.projects.wodm8.di.AppModule;
import jh.projects.wodm8.di.DaggerAppComponent;
import jh.projects.wodm8.di.RoomModule;
import jh.projects.wodm8.repository.WorkoutRepository;
public class MainActivity extends AppCompatActivity {
@Inject
public WorkoutRepository workoutRepository;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent intent = new Intent(view.getContext(), AddWorkoutActivity.class);
startActivity(intent);
}
});
DaggerAppComponent.builder()
.appModule(new AppModule(getApplication()))
.roomModule(new RoomModule(getApplication()))
.build()
.inject(this);
workoutRepository.findAll().observe(this, new Observer<List<Workout>>() {
@Override
public void onChanged(@Nullable List<Workout> products) {
Toast.makeText(MainActivity.this, String.format("Product size: %s", products.size()), Toast.LENGTH_SHORT).show();
}
});
}
}
添加锻炼Activity
package jh.projects.wodm8.view;
import androidx.appcompat.app.AppCompatActivity;
import jh.projects.wodm8.R;
import jh.projects.wodm8.data.Workout;
import jh.projects.wodm8.di.AppModule;
import jh.projects.wodm8.di.DaggerAppComponent;
import jh.projects.wodm8.di.RoomModule;
import jh.projects.wodm8.repository.DemoDatabase;
import jh.projects.wodm8.repository.WorkoutRepository;
import android.app.Application;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import javax.inject.Inject;
public class AddWorkoutActivity extends AppCompatActivity {
@Inject
public WorkoutRepository workoutRepository;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_workout);
final Button button = findViewById(R.id.saveWorkout);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Workout workout = new Workout();
EditText txtTitle = (EditText) findViewById(R.id.workoutTitleText);
workout.setTitle(txtTitle.getText().toString());
try {
workoutRepository.insert(workout);
} catch (Exception e) {
Log.v("AddWorkout", e.getMessage());
}
Toast.makeText(AddWorkoutActivity.this, "Inserted", Toast.LENGTH_SHORT).show();
}
});
}
}
// 编辑: 感谢 a_local_nobody 提供以 Dagger 开头的链接: https://youtu.be/Qwk7ESmaCq0
我找到了另一个从 dagger 开始的资源,这对我也有帮助: https://www.raywenderlich.com/262-dependency-injection-in-android-with-dagger-2-and-kotlin#toc-anchor-005
给你一个更完整的答案,取自这个在线资源 https://github.com/MindorksOpenSource/android-dagger2-example/blob/master/app/src/main/java/com/mindorks/example/android_dagger2_example/DemoApplication.java
(我只是简单地回顾一下,以便您更好地理解)
创建一个扩展应用程序的应用程序 class 并实现它:
@Override
public void onCreate() {
super.onCreate();
applicationComponent = DaggerApplicationComponent
.builder()
.applicationModule(new ApplicationModule(this))
.build();
applicationComponent.inject(this);
}
尽管如此,您必须定义自己的 applicationComponent,这里只是简单介绍一下。
在那之后,你应该能够在几个不同的地方使用你的存储库,在你需要的地方使用 @Inject
的注释,只记得在你需要的地方实际调用注入,利用
getActivityComponent().inject(this);
或 AndroidInjection.inject(this)
,希望这个 github 示例和教程足以回答您的一些问题