我正在尝试使用 Dagger 2 集成 Retrofit 2 和 Android Priority Job Queue。
很可能我在这里使用了错误的模式(我是 Java 和 Android 的新手),但我正在尝试从一个将被序列化然后在执行前反序列化的对象访问 Dagger 创建的 Retrofit 实例(Android作业队列序列化持久保存到磁盘的作业)。 Retrofit 实例由 Application Dagger 组件创建,因为我在其依赖项之一中使用了 SharedPreferences。
我无法在创建作业时将 Retrofit 传递给作业,因为 Retrofit 本身无法序列化。
应用程序也无法序列化,因此我无法在作业运行时从作业中引用 Application Dagger 组件(因为我无法像从 Activity 中那样注入(inject) ((MyApplication) myApplication).component().inject(this);
,因为应用程序对象不存在于反序列化作业中。)
我想使用应用程序其余部分使用的 Retrofit 实例来提高效率,而不是仅为该作业创建另一个实例。有可能吗?
我不确定是否使用 Provider<T>
或工厂可能会有所帮助,因为这超出了我现在的理解范围,但如果是这样的话,我很想得到有关如何构建事物的提示!
编辑:这就是您使用 Android 优先作业队列创建作业的方式。我已经修改了一个样本以表明我希望注入(inject)如何工作。该作业在 onAdded()
上连载并在使用 onRun()
运行之前反序列化:
// A job to send a tweet
public class PostTweetJob extends Job {
@Inject MyService webservice;
public static final int PRIORITY = 1;
private String text;
public PostTweetJob(String text) {
// This job requires network connectivity,
// and should be persisted in case the application exits before job is completed.
super(new Params(PRIORITY).requireNetwork().persist());
}
@Override
public void onAdded() {
// Job has been saved to disk.
}
@Override
public void onRun() throws Throwable {
// Job logic goes here
webservice.postTweet(text);
}
@Override
protected void onCancel() {
// Clean up
}
}
最佳答案
这是我可以管理的最简单的解决方案。
首先,创建一个BaseJob
类。这将是注入(inject)目标:
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
的作业。注入(inject)到 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
}
}
最后,为了确保一切都连接起来,在创建 JobManager
时添加一个 DependencyInjector
。这会注入(inject)作业的 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
并直接注入(inject) MyActualJob
?这将起作用,但是如果有多个作业是注入(inject)目标,我相信您必须使用 instanceof
来检查正在创建哪种作业并将 job
转换为创建 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);
}
}
};
在我的例子中,大多数(如果不是全部)作业都需要访问相同的全局对象,因此将 BaseJob
子类化并将其用作唯一的注入(inject)目标会更清晰。
关于java - 如何使用 Dagger 2 将对象注入(inject)到 Android 优先作业队列中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35022074/