Model receive context on Android MVP

Asked

Viewed 69 times

2

I have a sqlite database, to use precise context, however, sending the context to the presenter and then pro model would be a violation of MVP, because it is part of the view, is part of Android. How I would use context without violating MVP?

In case, pass to the presenter would be like this:

interface Model {
    String getUser();
    String getPassword();
}

interface View {
    void showToast(String message);
    void emptyUsuarioEditText();
    void emptyPasswordEditText();
    Context getContext();
}

interface Presenter {
    void login(String user, String password);
    Context getContext();
}

1 answer

2


Actually, you don’t need a Context proper. What you need is a reference to a class that extends SQLiteOpenHelper.

Let’s say, a class Database:

public class Database extends SQLiteOpenHelper {
...
}

This class, in turn, needs a Context.

There are several different ways you pass a reference to this Database for your model. You can create a method static in your class Application that returns to you an instance of the class Database.

public class MyApplication extends Application {
    private static MyApplication sInstance;

    @Override
    public void onCreate() {
        super.onCreate();
        sInstance = this;
    }

    public static Database getDatabase() {
        return new Database(getContext());
    }

    public static Context getContext() {
       return sInstance.getApplicationContext();
    }
}

So just do it in your Model (or Presenter and send it to the Model):

MyApplication.getDatabase();

Although it works I don’t really like this approach. I don’t think it’s right to do it in the Application class.

So you could have a class, say: Injection. Where you perform "DI in hand".

public final class Injection {

    private Injection() {
        throw new IllegalStateException(Injection.class.getSimpleName() + " cannot be instantiated!");
    }

    public static Database provideDatabase() {
        return new Database(MyApplication.getContext());
    }
}

Another alternative is if you use Dagger, for example, let it do the class automatic dependency injection Database in his Model.

  • I read about the solution of the application, and they say it is bad because it disturbs the test, and it is a bit tricky (by what they say)... I also can not use Dagger

  • If I send the Database class to the presenter, am I violating the MVP as well? Not only sqlite, but there are other things that use context, like sharedpreference...

  • @Elipe.rce Fetch the Context of Application using the class Injection is not gambiarra. Often we need to do this because we need something that exists throughout the application. That’s why it’s where we start some libs, like Dagger. And that doesn’t make Dagger gambiarra. You should only know how to use at the right times.

  • is that many responses in stackoverflow point out that keeping the context static in the application is not a good solution (see comments): https://stackoverflow.com/questions/39100105/need-context-in-model-in-mvp and comments pointing out that it is wrong

  • @Elipe.rce On the SharedPreferences: what we need to make clear is this: you don’t need the Context for these tasks and should not pass it to the Model. Create an abstraction for the preferences and pass the instance of that class. Again, you can create it at Injection by recovering the Context of Application. Or even create it in the Presenter, passing the Context for the class Injection need not seek the Application.

  • @Felipe.rce Yes. If you don’t want to go down this path, pass Context to Presenter and Presenter to Injection. That way you don’t need to pass it to the Model and also didn’t recover from the Application.

  • you speak pass the context through the interface or the constructor?

  • Leave this method only Context getContext(); in your View. So you can call it the Presenter and create the class Database, for example. Or you can even send the class Database already created by the builder of Presenter (maid in View using the `Injection).

  • I found the idea of sending the Database class more interesting, because then I won’t be sending something from Android to the presenter

  • @Felipe.rce Ok, it’s a good approach. But don’t install it directly in the View. Abstraction for a class Injection (or something like that) and you’ll have a better and more decoupled implementation. ;)

Show 5 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.