如何在android中使用Dagger获得类中的单例注入



有一个DataAccessInterface类负责管理数据库:

public class DataAccessInterface {
private DaoSession daoSession;
public DataAccessInterface () {
}
...
public void saveCar (Car car) {
daoSession.getCarDao (). insert (car);
}
}

DataAccessInterface注入在几个fragment中成功使用。例子:

public class LoginFragment extends BaseFragment {
@Inject
DataAccessInterface dataAccessInterface;
...
public boolean initDatabase () throws SyncDataBaseException {
try {
dataAccessInterface.openSession (currentUser.getUsername ());
} catch (Exception e) {
throw new SyncDataBaseException ();
}
return true;
}
...
}
有一个backendip类(No Fragment or Activity)在后台查询rest服务并将响应保存在数据库中。注入不起作用,它总是null:
public class BackendImp {
@Inject
DataAccessInterface dataAccessInterface;
public void save () {
Car car = unloadCar ()
dataAccessInterface.saveCar (car);
}

AbstractActivityComponent看起来像这样

@PerActivity
@Component (dependencies = ApplicationComponent.class, modules = ActivityModule.class)
public interface AbstractActivityComponent {
Activity activity ();
final class Initializer {
public static AbstractActivityComponent init (Activity activity) {
return DaggerAbstractActivityComponent.builder ()
.applicationComponent (DaggerManager.getInstance (). appComponent ())
.activityModule (new ActivityModule (activity))
.build ();
}
}
void inject (LoginFragment inject);
void inject (BackendImp inject);
}

ApplicationModule:

@Module
public class ApplicationModule {
private final Application application;
private final User currentUser;
public ApplicationModule (Application application) {
this.application = application;
this.currentUser = getUser ();
}
@Provides
@Singleton
DataAccessInterface dataAccessInterface () {
return new DataAccessInterface (userProfile ());
}
}

和ApplicationComponent

@Singleton
@Component(modules = ApplicationModule.class)
public interface ApplicationComponent {
void inject(Application application);
final class Initializer {
public static ApplicationComponent init(Application app) {
return DaggerApplicationComponent.builder()
.applicationModule(new ApplicationModule(app))
.build();
}
}
Application application();
Context context();
DataAccessInterface dataAccessInterface();
}

错误:W/系统。错误:java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法'void com.service.DataAccessInterface.saveCar(Car)'

编辑:

根据评论中Nitrodon的问题:backendip函数是从Worker调用的,因为它们将每小时执行一次。我想要一个单一的实例,所以我做了以下可能是错误的:

public class MainApp extends Application {
public static BackendService backendService;
@Override
public void onCreate () {

super.onCreate ();
backendService = new BackendImp ();
}
public static void callWorker () {
...

workManager.enqueue (updateWorkRequest);
}

And the Worker:

public class updateWorker extends Worker {
...
@Override
public Result doWork () {
Result result = Result.retry ();
try {
backend = MainApp.backendService;
backend.save ();
result = Result.success ();
} catch (Exception e) {
result = Result.retry ();
}
return result;
}

Dagger不钩入构造函数调用。你必须告诉Dagger把依赖项注入到BackendImp中。

您的活动组件中有一个inject(BackendImp inject)方法。这是可行的,但它位于错误的位置,因此您的应用程序类无法访问它。将此方法放入应用程序组件中可以工作:

@Override
public void onCreate () {

super.onCreate ();
backendService = new BackendImp();
// I assume you created the application component somewhere in here.
component.inject(backendService);
}

但是,在可以避免的情况下,通常不鼓励使用成员注入方法。在Activity子类中没有其他选择,因为它们是由框架实例化的,但是像BackendImp这样的东西完全在你的控制之下,所以你可以并且应该让Dagger为你创建它。

要做到这一点,通过赋予@Singleton作用域和@Inject构造函数,将BackendImp本身置于应用程序组件中:
@Singleton
public class BackendImp {
final DataAccessInterface dataAccessInterface;
@Inject
BackendImp(DataAccessInterface dataAccessInterface) {
this.dataAccessInterface = dataAccessInterface;
}
// ...
}
@Singleton
@Component(modules = ApplicationModule.class)
public interface ApplicationComponent {
// ...
// Use this in your application instead of new BackendImp()
BackendImp backendImp(); 
// Many tutorials instead suggest making an @Inject field in
// your application and calling inject(application).
}

最新更新