如何在android中使用Dagger在类中进行单例注入
Posted
技术标签:
【中文标题】如何在android中使用Dagger在类中进行单例注入【英文标题】:How to get a singleton injection in a class with Dagger in android 【发布时间】:2021-12-13 01:00:12 【问题描述】:有负责管理数据库的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;
...
有一个 BackendImp 类(无 Fragment 或 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);
应用模块:
@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 ());
和应用组件
@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/System.err:java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“void com.service.DataAccessInterface.saveCar(Car)”
编辑:
基于 Nitrodon 在 cmets 中的问题: BackendImp 函数是从 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);
还有工人:
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;
【问题讨论】:
你如何获得BackendImp
的实例?
非常好的观察。我没想到它会影响。我在 MainApp 中获得了一个新的 backendImp,然后我用它来调用它的函数。 backendService = new BackendImp ();那是问题吗?我该怎么做?我将使用缺少的代码编辑问题
【参考方案1】:
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 为你创建它。
为此,将BackendImp
本身放置在应用程序组件中,为其提供@Singleton
范围和@Inject
构造函数:
@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).
【讨论】:
“将 BackendImp 本身放在应用程序组件中”是什么意思。全班?您能否提供一些参考,这将有助于更好地理解您的答案。以上是关于如何在android中使用Dagger在类中进行单例注入的主要内容,如果未能解决你的问题,请参考以下文章