我正在尝试使用Dagger 2集成Retrofit 2和Android Priority Job Queue。
我可能在这里使用了错误的模式(我是Java和Android的新手),但是我试图从一个对象中访问Dagger创建的Retrofit实例,该对象将被序列化然后在执行前反序列化(Android作业队列序列化持久保存到磁盘的作业。 Retrofit实例由Application Dagger组件创建,因为我在其中一个依赖项中使用SharedPreferences。
由于Retrofit本身无法序列化,因此我无法将Retrofit传递给作业。
应用程序也无法序列化,因此我无法在作业运行时从作业中引用Application Dagger组件(因为我不能像{I}一样注入活动,因为Application对象不能在反序列化的工作中不存在。)
我想使用应用程序其余部分使用的Retrofit实例来提高效率,而不是仅为作业创建另一个实例。它甚至可能吗?
我不确定使用((MyApplication) myApplication).component().inject(this);
或工厂可能会有所帮助,因为现在我的理解已经超出了我的想法,但如果情况确实如此,我会喜欢暗示如何构建事物!
编辑:这是如何使用Android优先级作业队列创建作业的。我修改了一个样本,以表明我希望注射方式如何工作。该作业在Provider<T>
上序列化,并在使用onAdded()
运行之前进行反序列化:
onRun()
答案 0 :(得分:7)
这是我能够管理的最简单的解决方案。
首先,创建一个BaseJob
类。这将是注射目标:
public abstract class BaseJob extends Job {
// annotate fields that should be injected and made available to subclasses
@Inject MyService service;
protected BaseJob(Params params) {
super(params);
}
}
它已声明abstract
,因此无需覆盖Job
类中声明的任何抽象方法。相反,方法将在从BaseJob
继承的作业中被覆盖。
创建一个继承自BaseJob
的作业。注入BaseJob
的任何字段都可以使用:
public class MyActualJob extends BaseJob {
public static final int PRIORITY = 1;
public MyActualJob() {
super(new Params(PRIORITY).requireNetwork().persist());
}
@Override
public void onAdded() {
// job added to queue
}
@Override
public void onRun() throws Throwable {
// do the work
// service will be injected into BaseJob, so you can use it here
final Call<User> call = service.getUser();
call.execute();
}
@Override
protected void onCancel() {
// clean up
}
}
最后,为确保相关内容,请在DependencyInjector
创建时添加JobManager
。这注入了工作BaseJob
:
DependencyInjector dependencyInjector = new DependencyInjector() {
@Override
public void inject(Job job) {
// this line depends on how your Dagger components are setup;
// the important part is to cast job to BaseJob
((MyApplication) app).component().inject((BaseJob) job);
}
};
Configuration configuration = new Configuration.Builder(getApplicationContext())
.injector(dependencyInjector)
.build();
JobManager jobManager = new JobManager(getApplicationContext(), configuration);
为什么不跳过BaseJob
并直接注入MyActualJob
?这将有效,但是如果有多个作业是注入目标,我相信您必须使用instanceof
来检查创建的作业类型,并在创建时将job
转换为正确的类{ {1}}:
DependencyInjector
在我的情况下,大多数(如果不是所有)作业都需要访问相同的全局对象,因此将DependencyInjector dependencyInjector = new DependencyInjector() {
@Override
public void inject(Job job) {
if (job instanceof MyActualJob) {
((MyApplication) app).component().inject((MyActualJob) job);
} else if (job instanceof MyRealJob) {
((MyApplication) app).component().inject((MyRealJob) job);
} else if (job instanceof MyBetterJob) {
((MyApplication) app).component().inject((MyBetterJob) job);
}
}
};
子类化为更清晰,并将其用作唯一的注入目标。