Does the presenter having knowledge of the Activity / Context a bad idea in the MVP pattern?

前端 未结 3 624
無奈伤痛
無奈伤痛 2020-12-07 09:20

I\'ve been playing around with the MVP pattern for a few weeks now and I\'ve come to the point where I need context to start a service and access Shared P

3条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-12-07 09:51

    It has been some time since you asked this question but I thought it would be useful to provide an answer anyway. I would strongly suggest that the presenter should have no concept of the Android Context (or any other Android classes). By completely separating your Presenter code from the Android system code you are able to test it on the JVM without the complication of mocking system components.

    To achieve this I think you have three options.

    Access SharedPreferences from the View

    This is my least favourite of the three as accessing SharedPreferences is not a view action. However it does keep the Android system code in the Activity away from the Presenter. In your view interface have a method:

    boolean isLoggedIn();
    

    which can be called from the presenter.

    Inject SharedPreferences Using Dagger

    As you are already using Dagger to inject the event bus you could add SharedPreferences to your ObjectGraph and as such would get a SharedPreferences instance which has been constructed using the ApplicationContext. This was you get the them without having to pass a Context into your presenter.

    The downside of this approach is that you are still passing in an Android system class (SharedPreferences) and would have to mock it when you wanted to test the Presenter.

    Create a SharePreferencesRepository Interface

    This is my preferred method for accessing SharedPreferences data from within a Presenter. Basically you treat SharedPreferences as a model and have a repository interface for it.

    Your interface would be similar to:

    public interface SharedPreferencesRepository {
    
        boolean isLoggedIn();
    }
    

    You can then have a concrete implementation of this:

    public class SharedPreferencesRepositoryImpl implements SharedPreferencesRepository {
    
        private SharedPreferences prefs;
    
        public SharedPreferencesRepositoryImpl(Context context) {
    
            prefs = PreferenceManager.getDefaultSharedPreferences(context);
        }
    
        @Override
        public boolean isLoggedIn() {
    
            return prefs.getBoolean(Constants.IS_LOGGED_IN, false);
        }
    
    }
    

    It is the SharedPreferencesRepository interface that you then inject with Dagger into your Presenter. This way a very simple mock can be provided at runtime during tests. During normal operation the concrete implementation is provided.

提交回复
热议问题