I have an Android application which needs to retrieve JSON files from a server and then display the information in my app. To accomplish this I have the following architecture:
- The main activity adds a job to the job queue requesting certain information from the server.
- The job gets run, retrieving the specified information and caching it in case the same request is made again in the future.
- The job on completion adds an event containing the information to the event bus.
- The event bus then relays the event back to the main activity which renders the information.
While I was developing other parts of the application I simply provided the job queue, event bus and cache via constants, i.e.
public class Dependencies {
public static final JobQueue JOB_QUEUE = new JobQueue();
public static final EventBus EVENT_BUS = new EventBus();
public static final Cache CACHE = new Cache();
}
I knew at some point I wanted to use dependency injection (via the Dagger 2 library) to improve the style and make my code more modular and testable. I have now begun the process of migrating my code over to this style but I am discovering some problems. Here is my new code (some parts omitted):
public class MainActivity extends Activity {
@Inject EventBus mEventBus;
@Inject JobQueue mJobQueue;
@Inject Cache mCache;
private Session mSession;
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/*
* Dagger 2 injection
* */
((MyApplication) getApplication()).getDependenciesComponent().inject(this);
final HttpUser httpUser = new HttpUser("[email protected]", "xxxxxxxx");
startSession(httpUser);
}
@Override
protected void onResume() {
super.onResume();
mEventBus.register(this);
}
@Override
protected void onPause() {
super.onPause();
mEventBus.unregister(this);
}
@Subscribe
public void onSessionStarted(final SessionStartedEvent sessionStartedEvent) {
final boolean didExceptionOccur = sessionStartedEvent.didExceptionOccur();
if(didExceptionOccur) {
final Throwable throwable = sessionStartedEvent.getThrowable();
handleSessionStartFailedThrowable(throwable);
}else {
mSession = sessionStartedEvent.get();
loadTasks(mSession);
}
}
@Subscribe
public void onTasksLoaded(final TasksLoadedEvent tasksLoadedEvent) {
final boolean didExceptionOccur = tasksLoadedEvent.didExceptionOccur();
if(didExceptionOccur) {
final Throwable throwable = tasksLoadedEvent.getThrowable();
handleLoadTasksFailed(throwable);
}else {
final Task[] tasks = tasksLoadedEvent.get();
final String taskArrayStr = Arrays.toString(tasks);
Log.i(TAG, "tasks loaded: " + taskArrayStr);
setTasksOnFragments(tasks);
}
}
private void startSession(final HttpUser httpUser) {
final Job startSessionJob = new StartSessionJob(this, mEventBus, httpUser);
mJobQueue.addJobInBackground(startSessionJob);
Log.d(TAG, "added start session job to job queue");
}
private void loadTasks(final Session Session) {
final Job loadTasksJob = new LoadTasksJob(this, mEventBus, mCache, session);
mJobQueue.addJobInBackground(loadTasksJob);
Log.d(TAG, "added load tasks job to job queue");
}
}
My primary focus here is on the job objects. Whereas before I would simply access the job queue, event bus, and cache from the static singletons, I now have to inject those dependencies into their constructors. As you can see for the "load tasks" job
final Job loadTasksJob = new LoadTasksJob(this, mEventBus, mCache, session);
I now have a four argument constructor, whereas before it was only two. I have read in "Clean Code" that a 4-arg constructor is an abomination and typically a sign you need to refactor your code. Is this the case here, am I doing something wrong structuring my code in this way?