在Android中的MVVM中的上下文

时间:2017-10-03 05:48:32

标签: android mvvm

我已经开始为Android应用程序开发MVVM架构。我怀疑是否将上下文传递给视图模型是正确的?如果没有,那么我的视图模型如何在需要时可以访问上下文。

我正在做以下事情:

  1. 使用某些EditText提供数据。
  2. 将此数据发送到View模型。
  3. 查看模型将此数据发送到存储库
  4. 将此数据存储到设备的共享首选项的存储库。
  5. 由于共享首选项需要上下文来实例化对象。

    我是这个架构的新手,任何指导对我都有帮助,提前谢谢。

6 个答案:

答案 0 :(得分:6)

我认为ApplicationContext的使用是可以的,您可以从AndroidViewModel扩展ViewModel,并且只要需要引用上下文,就可以使用getApplication()方法。

更好的是,如果你使用匕首,你根本不需要这个,你只需要在你需要的地方注入你的ApplicationContext。它可以在您的视图模型或处理共享首选项等的实用程序类中。

答案 1 :(得分:4)

这是Android社区长期争论不休的讨论。当我们提到MVC时,很明显模型(也就是数据保持对象)是M,Controllers = C用于Activity类(在iOS中它们实际上称为UIViewControllers),而用于Android中View的V是XML文件本身。现在有些人会争论代表什么的建筑细分。但是,让我们超越这个并讨论MVVM。

MVVM已经存在很多年了。过去曾经有过一些尝试通过第三方绑定工具将它带到Android,但它最终会变得更加hacky然后值得。

最近随着原生数据绑定的发布,Android终于能够做一些有点干净的MVVM实现。所以这里有几个选项。你可以做到

  

M =模型(数据保持对象)

     

V = Views(表示UI的XML文件本身)

     

VM =这是争论的地方。

有人说为了成为一个“真正的”ViewModel,必须与Presentation层真正分离,而Activity类本身具有生命周期回调,因此不值得被称为ViewModel。

其他(自包含)会指出,为了处理从ViewModel触发的大多数操作,必须具有onActivityResult,onNewIntent,onBroadcastReceived,onPause或其他生命周期处理的意识,以适当地管理用户体验。所以在我的团队中,我们将Activity视为ViewModel。否则,你将活动传递给一个视图模型并将两者紧密耦合在一起,造成巨大的可怕维护代码噩梦。

所以,如果您想要我的意见,请坚持将Activity视为您的ViewModel。像在WPF中的任何其他绑定技术(如INotifyPropertyChanged)一样,将数据提供给ViewModel。你可以通过Binding来实现。

我做了两件事来实现这一目标。我在XML布局中有一个Activity变量,用于在onCreate中注入绑定设置,该设置为viewModel中的任何可观察属性(即活动)提供XML直接绑定权限。然后我注入了我需要使用的任何变量,例如,你可能有一个WeatherModel填充一个预测,该预测存在于你也将在onCreate中设置的Activity中,以允许XML访问它的ViewModel(aka activity)它是viewModel的对象。

另一种方法是制作一个ViewModel对象并将其注入活动的onCreate中的XML中,然后继续从活动中来回调用viewmodel以处理操作和生命周期,并随意管理那个噩梦哈哈,我用这种方式完成了一个完整的项目,到最后,我重新编写了一切,以避免编码工作的重复和可怕的来回重复。

Goodluck,我希望有所帮助。

答案 2 :(得分:2)

一个非常好的问题,它并不像看起来那么简单! You can see an example from Google team here

他们在工厂的帮助下解决了这个问题。 它传递(当然)应用程序上下文(不是活动上下文!)。

一个小问题 - 以及如此多的样板代码!

我的决定:

public class MainApplication extends Application {
public void onCreate() {
AppSharedPref sharedPref = AppSharedPref.getInstance(PreferenceManager.getDefaultSharedPreferences(this));
AppRepository.getInstance(sharedPref);

存储库是单一的(为简洁起见,会跳过很多代码):

public class AppRepository implements AppDataSource {
public static AppRepository getInstance(@NonNull AppSharedPref sharedPref) {
if (INSTANCE == null) {
   INSTANCE = new AppRepository(sharedPref);
}
return INSTANCE;
}

在ViewModel调用中:

public class MyViewModel extends AndroidViewModel {

// constructor
public MyViewModel(@NonNull Application application) {
   repository = AppRepository.getInstance(.....);
}

答案 3 :(得分:0)

在这种情况下,您应该使用AndroidViewModel类或在您的ViewModel实现中继续引用Application上下文。 ViewModel类旨在通过其生命周期在Activity的不同实例之间保持数据持久,并且存储对Activity实例上下文之一的引用确实没有用。

答案 4 :(得分:0)

查看Dagger 2!

是的,您绝对不应该将git fetch origin master git rebase origin/master git push origin master 传递给Activityxml。这将使您的ViewModel不会比我们试图从此体系结构转移的2000行活动更好。 MVVM项目中的解决方案是用ViewModel注入SharedPreferences。您也可以使用Dagger,但是在项目中是否需要ApplicationContext的多个实例?

我们有一个SharedPreferences的实用程序类,很高兴让它保持单例并在需要的地方注入。

答案 5 :(得分:0)

我在应用程序中使用了MVVM。我总是尽量不要在视图模型中使用上下文。我还遇到了SharedPreferences的问题,它需要上下文来访问首选项文件。我不使用Dagger的解决方案之一是创建一个Preference实用程序类,该类将引用应用程序上下文。您可以在Application类中初始化此实用工具类。您可以通过实用程序类提供的公共静态方法来引用共享首选项。您可以从存储库类中直接调用实用程序类。我更喜欢在存储库类中包含与数据存储有关的所有逻辑,这就是为什么我在存储库类中调用sharedpreference实用程序类。

PreferenceManager.java

public class PreferenceManager {
private static SharedPreferences mSharedpreferences;
private PreferenceManager() {}
public static void initialize(Context context) {
    mSharedpreferences= context.getSharedPreferences(context.getPackageName(), 
    Context.MODE_PRIVATE);
}
public static SharedPreferences getSharedPreferences() {
    return mSharedpreferences;
}
}

App.java

public class App extends Application {
@Override
public void onCreate() {
    PreferenceManager.initialize(this);
}
}

Repository.java

public class Repository {
public void someMethod() {
    PreferenceManager.getSharedPreferences.edit.putBoolean("sample", true).apply();
}