Android Clean Architecture - correct way to access Resource strings

Viewed 985

I like Clean architecture however something that has always troubled me is the access to Resource files across layers.

I know that layers other than the View layer shouldn't have references to anything related to Android SDK. But there are times where specific texts need to be managed and it becomes a headache the further the layer goes.

Specifically, I have the following scenario which made me uncertain on how to implement correctly:

When the screen is opened, a warning message should be presented. This warning message may be retrieved from a remote source according to a flag or taken from a local string if the flag is off.

As I understand, the presenter shouldn't mind the value of the flag and simply call UseCase.getWarningMessage(). Going deeper, the UseCase should probably only take the flag value and send it to the repository (I'm still not sure if the flag should be instead accessed directly in the Repository).

After that, the repository would check the flag and retrieve the remote message or simply take it from the local strings.

At this point, how could the repository take the Resource string? Should dependency be sent all the way to the Repository layer in case it needs access to resources? Should the presenter instead be the responsibility of managing the flag to know if warning messages should be retrieved remotely or locally?

1 Answers

"...layers other than the View layer shouldn't have references to anything related to Android SDK." is simply wrong. If some module/class depends on some other module/class, it depends on that module/class. No way around it.

What you should not do with Android is that your non-UI modules should not keep references of UI related objects (Activities, fragments, views) that otherwise prevent them from being garbage collected. However, when you need a Context in classes with application scope - like repository classes which are implemented in the way recommended by android - it is totally OK to use application Contexts.

EDIT Since you ask that question, I am assuming you are not using a dependency injection framework.

You probably follow developer guides, and implementing your repository as an Singleton. Now a simple way of passing an ApplicationContext instance could be: 1. Define a static field of type android.app.Application inside your repository class. Provide a setter to inject that dependency.

public class MyRepo {
   private static Application application;
   ..................

   public static void injectApplication(Application app) {
        if(null == application) {
            application = app;
        }
   }
}

May be you can document your class on to call this new method prior to any getInstance() method usage.

  1. Extend android.app.Application class. Override onCreate() and inject 'this' to repository.
public class MyApp extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        MyRepo.injectApplication(this);
    }
.........
}
  1. Do not forget to modify your manifest file for your new Application class.
Related