JSON loader with event bus, cache, and session
The solution I developed was to inject the dependencies into the job queue instead of the jobs. This way the injection only has to happen once and can be accomplished nicely using Dagger 2 (note: because I was using the android-priority-jobqueue library I had to wrap it in my own class to allow for this functionality).

This is my Dagger module:

import android.app.Application;

import com.treemetrics.taskmanager3.util.AppCache;
import com.treemetrics.taskmanager3.work.eventbus.EventBus;
import com.treemetrics.taskmanager3.work.jobqueue.JobQueue;

import javax.inject.Singleton;

import dagger.Module;
import dagger.Provides;

@Module
public class AppModule {

  private final Application mApplication;

  public AppModule(final Application application) {
    mApplication = application;
  }

  @Provides
  @Singleton
  Application providesApplication() {
    return mApplication;
  }

  @Provides
  @Singleton
  EventBus providesEventBus() {
    return new EventBus();
  }

  @Provides
  @Singleton
  AppCache providesCache() {
    return new AppCache();
  }

  @Provides
  @Singleton
  JobQueue providesJobQueue(final Application app, final EventBus bus, final AppCache cache) {
    return new JobQueue(app, bus, cache);
  }

}


Dagger component:

import javax.inject.Singleton;

import dagger.Component;

@Singleton
@Component(modules = AppModule.class)
public interface AppComponent {

  void inject(MainActivity activity);

}


My wrapper class for the android-priority-jobqueue JobManager class which accepts the dependencies:

import android.content.Context;
import android.support.annotation.Nullable;

import com.birbit.android.jobqueue.JobManager;
import com.birbit.android.jobqueue.config.Configuration;
import com.treemetrics.taskmanager3.util.AppCache;
import com.treemetrics.taskmanager3.work.eventbus.EventBus;

public class JobQueue {

  private static final int DEF_PRIORITY = 1;

  private final Context mContext;
  private final JobManager mJobManager;
  private final EventBus mEventBus;
  private final AppCache mAppCache;

  public JobQueue(final Context context, final EventBus eventBus, final AppCache appCache) {
    mContext = context;
    final Configuration jobManagerConfig = new Configuration.Builder(context).build();
    mJobManager = new JobManager(jobManagerConfig);
    mEventBus = eventBus;
    mAppCache = appCache;
  }

  public void addJob(final Job job) {
    addJob(job, null);
  }

  public void addJob(final Job job, @Nullable final CharSequence groupId) {
    final String groupIdStr = (groupId != null) ? groupId.toString() : null;
    final BirbitJob birbitJob = getBirbitJob(job, DEF_PRIORITY, groupIdStr);
    mJobManager.addJobInBackground(birbitJob);
  }

  private BirbitJob getBirbitJob(final Job job, final int priority, @Nullable final String groupId) {
    return new BirbitJob(job, mContext, mEventBus, mAppCache, priority, groupId);
  }

}


I also have a new Job interface which my JobQueue wrapper class accepts instead of the Job class from the android-priority-jobqueue library. These jobs when submitted to my new JobQueue get translated to "birbit jobs" (the job class which the library accepts) and have the dependencies injected into them at that time. Here is my new Job interface and the BirbitJob class which is used to translate my jobs into the jobs accepted by android-priority-jobqueue.

(Notice the dependencies are provided in the onRun method.)

import android.content.Context;

import com.treemetrics.taskmanager3.util.AppCache;
import com.treemetrics.taskmanager3.work.eventbus.EventBus;

public interface Job {

  void onRun(Context context, EventBus bus, AppCache cache) throws Throwable;

  void onCancel(Throwable throwable, EventBus bus);

}


My translator job class BirbitJob:

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

import com.birbit.android.jobqueue.Params;
import com.birbit.android.jobqueue.RetryConstraint;
import com.treemetrics.taskmanager3.util.AppCache;
import com.treemetrics.taskmanager3.work.eventbus.EventBus;

class BirbitJob extends com.birbit.android.jobqueue.Job {

  private final Job mJob;

  private final Context mContext;
  private final EventBus mEventBus;
  private final AppCache mAppCache;

  public BirbitJob(final Job job,
                   final Context context,
                   final EventBus eventBus,
                   final AppCache appCache,
                   final int priority) {
    this(job, context, eventBus, appCache, priority, null);
  }

  public BirbitJob(final Job job,
                   final Context context,
                   final EventBus eventBus,
                   final AppCache appCache,
                   final int priority,
                   final String groupId) {
    super(new Params(priority).requireNetwork().groupBy(groupId));
    mJob = job;
    mContext = context;
    mEventBus = eventBus;
    mAppCache = appCache;
  }

  @Override
  public void onAdded() {
  }

  @Override
  public void onRun() throws Throwable {
    mJob.onRun(mContext, mEventBus, mAppCache);
  }

  @Override
  protected void onCancel(final int cancelReason, @Nullable final Throwable throwable) {
    mJob.onCancel(throwable, mEventBus);
  }

  @Override
  protected RetryConstraint shouldReRunOnThrowable(
      @NonNull final Throwable throwable, final int runCount, final int maxRunCount) {
    return RetryConstraint.CANCEL;
  }

}