如何使用Dagger 2将对象注入Android优先级作业队列?

sna*_*109 6 java serialization android dagger dagger-2

我正在尝试使用Dagger 2集成Retrofit 2和Android Priority Job Queue.

很可能我在这里使用了错误的花样(我是新来的Java和Android),但我想从将要执行之前系列化然后反序列化对象访问匕首创建的改造实例(Android的作业队列连载持久存储到磁盘的作业).Retrofit实例由Application Dagger组件创建,因为我在其中一个依赖项中使用SharedPreferences.

我无法在创建时将Retrofit传递给作业,因为Retrofit本身无法序列化.

应用程序也无法序列,因此当它运行(因为我不能用我注入无法从工作中引用应用程序组件匕首((MyApplication) myApplication).component().inject(this);就像我可以做的活动,因为应用程序对象不反序列化的工作存在. )

我想使用应用程序其余部分使用的Retrofit实例来提高效率,而不是仅为作业创建另一个实例.它甚至可能吗?

我不确定使用Provider<T>或工厂是否可以提供帮助,因为这是我现在所不能理解的,但如果是这样的话,我会喜欢暗示如何构建事物!

编辑:这是如何使用Android优先级作业队列创建作业.我修改了一个样本,以表明我希望注射方式如何工作.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
    }
}
Run Code Online (Sandbox Code Playgroud)

sna*_*109 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

它已声明,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
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,为了确保事情联系起来,加入DependencyInjectorJobManager在创建时它.这注入了工作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);
Run Code Online (Sandbox Code Playgroud)

为什么不跳过使用BaseJob并直接注入MyActualJob?这将有效,但是如果有多个作业是注入目标,我相信你必须使用它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);
        }
    }
};
Run Code Online (Sandbox Code Playgroud)

在我的情况下,大多数(如果不是所有)作业都需要访问相同的全局对象,因此子类更清晰BaseJob并将其用作唯一的注入目标.