【问题标题】:Dependency Injection in multiple Activities with Dagger and Room使用 Dagger 和 Room 在多个活动中进行依赖注入
【发布时间】:2019-07-15 11:37:05
【问题描述】:

我是来自 c# 背景的 Android 新手,并且遇到了 dagger 的依赖注入。我设法创建了一个简单的示例,但想知道如何在另一个活动中使用我的存储库(我在这里尝试使用存储库模式)。所以我的结构如下: 当我尝试在我的 MainActivity 类中创建锻炼时,它工作得很好。所以我在我的 AddWorkoutActivity 类中添加了以下行

@Inject
public WorkoutRepository workoutRepository;

但是当我尝试保存锻炼时,我总是在锻炼存储库上得到一个空引用错误,所以我确实错过了一些了解 DI 在这里如何工作的东西。也许有人可以给我一个提示,以便我的存储库在我的 Activity 中以正确的方式实例化。

// 编辑: 我认为问题是我在 MainActivity 类的 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);
    }
}

锻炼数据源

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

}

主活动 包 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();
            }
        });
    }
}

添加锻炼活动

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

【问题讨论】:

  • 我意识到这并不能回答你的问题,但是看看这组教程,它可能对你学习 dagger for android 非常有用,你会在之后获得它的基础知识前 3 或 4 个,希望对您有所帮助youtu.be/Qwk7ESmaCq0
  • 只是一个旁注,这是我从中学习 dagger 的地方,它确实为您提供了对其工作原理的一些很好的概述,如果您最终发现这些教程很有用,请考虑给我的评论点赞 :)万事如意
  • 感谢您的评论,也许我应该退后一步,了解更多基础知识。我一定会试试这个并观看视频。谢谢
  • 好的,我提交了一些答案,希望这至少对你有所帮助,花一些时间阅读这些教程和我发给你的 repo,如果它至少给我的答案一个赞成票如果你找到你要找的东西,有点帮助或标记为答案,祝你编码愉快:)

标签: android dependency-injection android-room dagger


【解决方案1】:

给你一个更完整的答案,取自这个在线资源https://github.com/MindorksOpenSource/android-dagger2-example/blob/master/app/src/main/java/com/mindorks/example/android_dagger2_example/DemoApplication.java

(我只是简单地回顾一下,让你更好地理解)

创建一个扩展应用程序的应用程序类并实现它:

     @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 示例和教程足以回答你的一些问题

【讨论】:

  • 谢谢你。这有助于我更清楚地理解它。它还没有解决我的问题,但正如我之前提到的,我认为我必须从一个更简单的例子开始;-)
  • 没问题@jhen,对于每个刚开始的人来说,匕首都非常复杂(感觉有很多事情要做)但是一旦你有了一个工作示例,你就可以随时使用它,所以我肯定会推荐从头开始,所有最好的和快乐的编码:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多