How can I insert an object into the Android priority queue using dagger 2?

I am trying to integrate Retrofit 2 and Android priority ordering with Dagger 2.

I'm probably using the wrong template here (I'm new to Java and Android), but I'm trying to access the Retrofit instance created by Dagger from an object that will be serialized and then deserialized before execution (Android Job Queue serializes jobs stored on drive). A Retrofit instance is created by the Application Dagger component because I use SharedPreferences in one of its dependencies.

I can not pass Retofit to the task when it is created, because the modification itself cannot be serialized.

The application also cannot be serialized, so I cannot reference the Application Dagger component from the task when it is launched (since I cannot insert ((MyApplication) myApplication).component().inject(this); how can I do from Activity because the Application object does not exist in deserialized work.)

I want to use the Retrofit instance used by the rest of the application to improve performance, instead of creating another instance just for the job. Is it possible?

I'm not sure if using Provider<T> or Factory can help because it is impossible to understand now, but I would like to know how to structure things if this happens!

EDIT:. How do you create a task in the Android priority queue. I modified the pattern to indicate how I would like the injection to work. The onAdded() serialized to onAdded() and deserialized to run using 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 } } 
+5
source share
1 answer

Here is the simplest solution that I could handle.

First create the BaseJob class. This will be the goal of the injection:

 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); } } 

He declared abstract , so there is no need to override any abstract methods declared in the Job class. Instead, methods will be overridden in jobs that inherit from BaseJob .

Create a task that inherits from BaseJob . Any fields entered in BaseJob are available for use:

 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 } } 

Finally, to make sure everything is connected, add a DependencyInjector to the JobManager when you create it. This introduces BaseJob into the job:

 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); 

Why not skip using BaseJob and paste directly into MyActualJob ? This will work, however, if there are several tasks that are the purpose of the injection, I believe that you will need to use instanceof to check which work was created, and give Job correct class when creating the 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); } } }; 

In my case, most, if not all tasks, need access to the same global objects, so it cleans up to a subclass of BaseJob and uses it as the sole purpose of the injection.

+6
source

Source: https://habr.com/ru/post/1241545/


All Articles