【问题标题】:How to pass context to repository in MVP pattern如何以 MVP 模式将上下文传递给存储库
【发布时间】:2018-05-03 12:28:54
【问题描述】:

我一直在学习和整合MVP pattern,有几个问题。

我从这张图中了解到的是,

Activity 将创建Presenter 的实例,并将其引用和model 对象传递给演示者

MainPresenter mainPresenter = new MainPresenter(this, new MainModel());

接下来,如果 Presenter 需要从本地或远程存储或获取任何数据,它会询问模型。

然后模型将要求存储库存储和检索数据。

我遵循了一些教程,这就是我实现该模式的方式。

界面

public interface MainActivityMVP {

    public interface Model{

    }

    public interface View{
        boolean isPnTokenRegistered();
    }

    public interface Presenter{

    }
}

活动

MainPresenter mainPresenter = new MainPresenter(this, new MainModel());
mainPresenter.sendDataToServer();

演示者

public void sendDataToServer() {

    //  Here i need to ask `model` to check 
        do network operation and save data in preference
}

现在的问题是我需要上下文来访问sharedPreference,但我没有在任何地方通过context。我也不想使用static context。我想知道将上下文传递给 MVP 模式的正确方法。

【问题讨论】:

  • 使用应用类
  • @quicklearner,我不想用这种方法,还有其他方法吗?还是应用程序类是唯一可能的方法?
  • 我认为这是一个更好的方法:),它不会返回 null 直到应用程序被杀死
  • 让我们等待一些其他答案,如果没有得到任何其他解决方案,我会采用这种方法:)。谢谢

标签: android performance android-layout android-fragments android-mvp


【解决方案1】:

好吧,最好的方法是将您的首选项类包装在一个辅助类中,并使用Dagger 将其注入您需要的任何地方,这样您的演示者/模型就不需要了解上下文。 例如,我有一个提供各种单例的应用程序模块,其中之一是我的 Preferences Util 类,它处理共享首选项。

@Provides
@Singleton
public PreferencesUtil providesPreferences(Application application) {
    return new PreferencesUtil(application);
}

现在,只要我想使用它,我只需 @Inject 它:

@Inject
PreferencesUtil prefs;

我认为学习曲线是值得的,因为您的 MVP 项目将更加解耦。

但是,如果您愿意忘记“Presenter 不知道 Android 上下文”规则,您可以简单地将 getContext 方法添加到您的视图界面并从视图中获取上下文:

public interface MainActivityMVP {

    public interface Model{

    }

    public interface View{
        boolean isPnTokenRegistered();
        Context getContext();
    }

    public interface Presenter{

    }
}

然后:

public void sendDataToServer() {
      Context context = view.getContext();
}

我见过有人这样实现 MVP,但我个人更喜欢使用 Dagger。

您还可以按照 cmets 中的建议使用应用程序上下文。

【讨论】:

  • 谢谢@Levi,我在某处读到Presenter 中不应该有任何context 的引用如果我不使用匕首并遵循第二种方法,我将有上下文参考在Presenter,我将把它从演示者传递给模型。
  • 为什么不用匕首?我试过但找不到详细解释 dagger2 的初学者级教程,或者可能是我太笨了:(
  • 是的,学习曲线相当陡峭,这与你是否愚蠢无关,别担心。但是关于AFAIK的答案,您有三个选择1)使用匕首,2)处理演示者内部的上下文3)使用应用程序上下文
  • 感谢@Levi,我会尝试研究 Dagger,但目前我想最合适的选项是 Use application context。使用此选项,presenter 将没有任何上下文引用,并且存储库将在需要时使用它,当我学习 dagger 时,我将升级这些类。我有点害怕,如果使用application context 是正确的方法。
  • 好吧 :) 祝你好运,匕首很大,但一旦你掌握了(你会在某个时候)它真的很有帮助:)
【解决方案2】:

你离你要找的东西还很远。你有一个模型接口,所以你有一个实现这个接口的类,可能是这样的:

MainModel implements MainActivityMVP.Model{
    SharedPreferences mPrefs;

    MainModel(Context context){
        mPrefs =context.getSharedPreferences("preferences",Context.MODE_PRIVATE);
    }
}

因此,您只需将该引用传递给您的演示者,但您可以接收 MainActivityMVP.Model 而不是接收 MainModel 类。

MainActivityMVP.Presenter mainPresenter = new MainPresenter(this, new MainModel(getContext()));

MainPresenter implements MainActivityMVP.Presenter{

     MainActivityMVP.View mView;
     MainActivityMVP.Model mModel;

     MainPresenter(MainActivityMVP.View view, MainActivityMVP.Model model){
           mView = view;
           mModel = model;
     }
}

通过这种方式,您的演示者中没有任何上下文引用,并且引用在您的 MainModel 中,而不是在您的 MainActivityMVP.Model 中。

将任何公共方法添加到您的演示者/视图/模型接口中。你应该有这样的东西:

public interface MainActivityMVP {

    public interface Model{
        void saveOnSharedPreferences();
    }

    public interface View{
        boolean isPnTokenRegistered();
    }

    public interface Presenter{
        void sendDataToServer();
    }
}

【讨论】:

    猜你喜欢
    • 2021-04-06
    • 1970-01-01
    • 2011-10-27
    • 1970-01-01
    • 2021-01-29
    • 2021-11-07
    • 1970-01-01
    • 1970-01-01
    • 2015-06-29
    相关资源
    最近更新 更多