Android MVP - Share Preference

Viewed 902

I started to learn MVP but I have a few questions related the SharedPreferences, as far as I know if I want to save a value in the sharedPreferences I need to pass this value to the presenter and the presenter calls the model to save the value, the same logic I would apply if I want to get or remove a value from the sharedPreference, but how is the best way to do that if I shouldn't pass the Context?

I sae a few code and the people used to pass the Context in the constructor method direct to the Model, but I still don't think that's a good idea.

Do you guys have any ideas?

Thanks, Thales

2 Answers

Android specific imports should never exist in the Presenter if you want to keep it unit testable.

What you can do is, make an abstraction layer above SharedPreferences let's call it Cache, it would be an interface with all the needed caching methods, you would then provide a concrete implementation of it using SharedPreferences.

Here is a quick illustration of the idea:

interface Cache {
// Your caching methods
}

class CacheImpl implements Cache {

    private SharedPreferences sharedPrefs;

    public CacheImpl(Context context) {
        // Takes a context to init sharedPrefs.
    }

    // implements all of Cache's methods
}

Then you would pass a reference for that implementation to the Presenter's constructor (better yet using DI to inject it to your presenters constructor):

Cache cache = new CacheImpl(myContext); // Naturally that would be an activity context
MyPresenter presenter = new MyPresenter(cache);

Then in your presenter you would receive that instance in the constructor:

private Cache cache;

public MyPresenter(Cache cache) {
    this.cache = cache;
}

You can then use the cache variable without knowing about it's concrete implementation nor should you provide it a context.

Create a Storage class Object inside View and pass the context inside Storage Class constructor.

Then pass this storage class object in presenter (constructor) from View class.

Then whenever you need to save or get some data from your presenter - Then simply call the method of storage class from the object you have passed.

This way you will not need to send the context to your presenter.

View class

public class ViewClass extends ActionBarActivity {

    private MyPresenter presenter;
    private MyStorage storage;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        storage = new MyStorage(this);
        presenter = new MyPresenter(this,storage);
    }

}

MyStorage Class

public class MyStorage {

    private Context mContext;

    public MyStorage(Context context) {
        this.mContext = context;
    }

    public void saveData(String data){

    }

    public String getData(){
        return "";
    }
}

MyPresenter class

public class MyPresenter {
    private final ViewClass mView;
    private final MyStorage mStorage;

    public MyPresenter(ViewClass viewClass, MyStorage storage) {
        this.mView = viewClass;
        this.mStorage = storage;
    }
}
Related