java - 如何使用 Dagger 2 将对象注入(inject)到 Android 优先作业队列中?

标签 java android serialization dagger dagger-2

我正在尝试使用 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/

相关文章:

java - jackson 为所有日期字段设置全局日期格式

python - 如何将 networkx (python) 节点序列化为 json 格式?

java - 如何在 Linux 中设置规范的主机名?

java - 即使实例化后对象仍为 Null

java - 如何在 Java 中比较字符串?

android - 从 Android ZXing IntentIntegrator 中提取结果

java - 对象输入流 : StreamCorruptedException

android - 如何获取在位图 Canvas 中绘制的签名的 X 和 Y 坐标

android - 如何检测JPG是否是RGB(或CMYK)格式?

android - 如何通过 bundle 发送对象