MVVM - 如何将上下文传递给存储库类?
Posted
技术标签:
【中文标题】MVVM - 如何将上下文传递给存储库类?【英文标题】:MVVM - how do I pass context to the repository class? 【发布时间】:2021-04-06 22:36:03 【问题描述】:我正在尝试学习 MVVM,但遇到了一些我不知道如何解决的问题。我想创建一个存储库,它将在后台线程中获取用户坐标。事情是为了让它工作,我必须为它传递上下文,但我不知道如何为存储库传递上下文。我不能像在某些活动课程中那样轻松地通过它。
存储库
public class LocationRepository
private void test()
FusedLocationProviderClient client = LocationServices.getFusedLocationProviderClient(CONTEXT);
if (ContextCompat.checkSelfPermission(CONTEXT, Manifest.permission.INTERNET) == PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(CONTEXT, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(CONTEXT, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED)
client.getLastLocation().addOnSuccessListener(CONTEXT, new OnSuccessListener<Location>()
@Override
public void onSuccess(Location location)
if (location != null)
//TODO
);
else
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
requestPermissions(new String[]
Manifest.permission.INTERNET, Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION
, 1);
【问题讨论】:
您不需要传递上下文来创建FusedLocationProviderClient
。您应该通过构造函数传递/注入FusedLocationProviderClient
。使用 DependencyInjection,您可以创建一次FusedLocationProviderClient
(来自 ApplicationContext)并将其传递给需要它的任何人。否则,您可以将上下文从 Activity/Fragment 传递到 ViewModel 到 Repository。
目前我没有使用任何 DependencyInjection。您指的第二种方式实际上是下面的答案吗?
【参考方案1】:
如果您不想使用依赖注入,请考虑这一点。
这是一个最小的示例,留下了许多有待改进的地方!
在这个例子中,我们不会传递Context
,因为这会导致内存泄漏(如果没有彻底处理),而是在 Activity 中创建 FusedLocationProviderClient
并将其传递给 ViewModel 和 Repository。
注意:避免将与 android 相关的内容(例如 Context
、View
等)传递到您的 ViewModel 和较低层。它将使测试和重构更容易,因为您对 Android 的依赖更少。
在您的 Activity 中,您将获得您的 ViewModel 并创建您的 FusedLocationProviderClient
:
public class YourActivity : Activity()
private FusedLocationProviderClient locationProvider = LocationServices.getFusedLocationProviderClient(this.applicationContext);
// Either you pass FusedLocationProviderClient via constructor to the ViewModel, or via a setter later
private YourViewModel viewModel = // ...
override void onCreate()
super.onCreate();
// if you wanna set the locationProvider via setter
viewModel.setLocationProvider(locationProvider); // this should not leak when the activity finishes as there is no reference to the Activity or its view
然后在您的 ViewModel 中,您可以通过 Constructor 或 setter 获得 locationProvider
:
public class YourViewModel extends ViewModel
// You can either create a new LocationRepository in the viewModel,
// or you can pass an instance via Constructor (which I recommend for better testability)
// or you pass it via a setter
private LocationRepository locationRepository;
public YourViewModel(FusedLocationProviderClient locationProvider)
locationRepository = new LocationRepository(locationProvider);
// alternatively using a setter
public void setFusedLocationProviderClient(FusedLocationProviderClient locationProvider)
locationRepository = new LocationRepository(locationProvider);
// this function calls your repository
public void foo()
// ensure LocationRepository is initialized or you will get a Nullpointer here,
// or check if (locationRepository != null) ... before accessing it
localRepository.test()
@Override
public void onCleared()
// do cleanup
// stop ongoing work (in your repository)
// unregister listeners (in your repository)
public class LocationRepository
private FusedLocationProviderClient locationProvider;
public LocationRepository(FusedLocationProviderClient locationProvider)
this.locationProvider = locationProvider;
public void test()
// ... now you can use FusedLocationProviderClient (without the need of having a context
【讨论】:
感谢您的帮助。非常感谢。以上是关于MVVM - 如何将上下文传递给存储库类?的主要内容,如果未能解决你的问题,请参考以下文章