簡體   English   中英

MVVM - 如何將上下文傳遞到存儲庫 class?

[英]MVVM - how do I pass context to the repository class?

我正在嘗試學習 MVVM,但遇到了一些我不知道如何解決的問題。 我想創建一個存儲庫,它將在后台線程中獲取用戶坐標。 事情是為了讓它工作,我必須為它傳遞上下文,但我不知道如何為存儲庫傳遞上下文。 我不能像在某些活動 class 中那樣輕易地通過它。

存儲庫

    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);
                }
            }
        }
    }
}

如果您不想使用依賴注入,請考慮這一點。

這是一個最小的例子,留下了很多可供改進的東西!

在這個例子中,我們不會傳遞Context ,因為這可能導致 memory 泄漏(如果沒有徹底處理),但在 Activity 中創建FusedLocationProviderClient並將其傳遞給 ViewModel 和存儲庫。

注意:避免將 Android 相關的東西(如ContextView等)傳遞給您的 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
  }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM