Dagger 2を使用して、Retrofit2とAndroidPriority JobQueueを統合しようとしています。
ここで間違ったパターンを使用している可能性があります(JavaとAndroidは初めてです)が、実行前にシリアル化されてから逆シリアル化されるオブジェクトからDaggerで作成されたRetrofitインスタンスにアクセスしようとしています(Android Job Queueはシリアル化されます)ディスクに永続化されるジョブ)。依存関係の1つでSharedPreferencesを使用しているため、RetrofitインスタンスはApplicationDaggerコンポーネントによって作成されます。
Retrofit自体はシリアル化できないため、作成時にRetrofitをジョブに渡すことができません。
アプリケーションもシリアル化できないため、実行時にジョブからApplication Daggerコンポーネントを参照できません(((MyApplication) myApplication).component().inject(this);
逆シリアル化されたジョブにApplicationオブジェクトが存在しないため、Activitiesから実行できるように注入できないためです。 )
仕事のためだけに別のインスタンスを作成するのではなく、効率のためにアプリの残りの部分で使用されるRetrofitインスタンスを使用したいと思います。それも可能ですか?
使用するProvider<T>
か、ファクトリが役立つかどうかは今のところ私の理解を超えているのでわかりませんが、その場合は、物事を構造化する方法についてのヒントが欲しいです!
編集:これは、Android Priority JobQueueを使用してジョブを作成する方法です。注入をどのように機能させたいかを示すためにサンプルを変更しました。ジョブは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
クラスを作成します。これが注入ターゲットになります。
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
し、正しいクラスにキャストする必要があると思います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
化してそれを唯一のインジェクションターゲットとして使用する方がクリーンです。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加