[英]Android MVVM - How to reference Activity in ViewModel
MVVM architecture, MVVM架构,
this is my View (Activity):这是我的观点(活动):
private MyApp app;
private MainActivityVM viewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
app = (MyApp) this.getApplication();
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
MainActivityVM.Factory factory = new MainActivityVM.Factory(app);
final MainActivityVM model = ViewModelProviders.of(this, factory)
.get(MainActivityVM.class);
viewModel = model;
binding.setVm(viewModel);
viewModel.onCreate();
and View Model:和查看模型:
public class MainActivityVM extends AndroidViewModel implements ViewModel {
public MainActivityVM(@NonNull Application application) {
super(application);
}
@Override public void onCreate() {
model = new MyService();
model.getData(); /* <-- how do i pass the activity here? */
}
@Override public void onPause() { }
@Override public void onResume() { }
@Override public void onDestroy() { }
public static class Factory extends ViewModelProvider.NewInstanceFactory {
@NonNull
private final Application mApplication;
public Factory(@NonNull Application application) {
mApplication = application;
}
@Override
public <T extends android.arch.lifecycle.ViewModel> T create(Class<T> modelClass) {
return (T) new MainActivityVM(mApplication);
}
}
}
and Model:和型号:
public class myService{
public getData(){
if(permissionacquired(){
getdata()
}else{
requestPermission();
}
}
private void requestPermission() {
PermissionKey permKey = new PermissionKey(HealthConstants.StepCount.HEALTH_DATA_TYPE, PermissionType.READ);
HealthPermissionManager pmsManager = new HealthPermissionManager(mStore);
try {
// Show user permission UI for allowing user to change options
/* BELOW CODE REQUIRE Activity reference to PASS */
pmsManager.requestPermissions(Collections.singleton(permKey), MainActivity.this).setResultListener(result -> {
/* ABOVE CODE REQUIRE Activity reference to PASS */
Log.d(APP_TAG, "Permission callback is received.");
Map<PermissionKey, Boolean> resultMap = result.getResultMap();
if (resultMap.containsValue(Boolean.FALSE)) {
updateStepCountView("");
showPermissionAlarmDialog();
} else {
// Get the current step count and display it
mReporter.start(mStepCountObserver);
}
});
} catch (Exception e) { Log.e(APP_TAG, "Permission setting fails.", e); }
}
}
EDIT: if you see my request permission in my Model, the API require activity to be pass - how can i pass activity reference to the request permission?编辑:如果您在我的模型中看到我的请求权限,则 API 需要传递活动 - 我如何将活动引用传递给请求权限?
I have a get permission method that comes from Model.我有一个来自模型的获取权限方法。 this get permission method from my service provider require activity eg requestPermission(Activity)
这个从我的服务提供商那里获得许可的方法需要活动,例如requestPermission(Activity)
so in my ModelView, i have the model object which is the dataService from another source.所以在我的 ModelView 中,我有一个模型对象,它是来自另一个来源的 dataService。
then, how I can reference Activity in my ViewModel so I can call: model.requestPermission(Activity);
然后,我如何在我的 ViewModel 中引用 Activity 以便我可以调用: model.requestPermission(Activity);
in my ViewModel?在我的视图模型中?
understanding from here that:从这里理解:
Caution : A ViewModel must never reference a view, Lifecycle, or any class that may hold a reference to the activity context.注意:ViewModel 绝不能引用视图、生命周期或任何可能持有对活动上下文的引用的类。
只要您在 onCreate() 方法中需要权限,您就可以将带有权限请求的逻辑移动到活动中,并将请求结果传递到视图模型中。
In my case I also added Activity
into ViewModel
for permissions and strings, but it's not a good idea.就我而言,我还将Activity
添加到ViewModel
以获取权限和字符串,但这不是一个好主意。 When I disabled location permission in one Fragment
, an application crashed, because it restarted, then restored FragmentManager
with fragment stack and later started MainActivity
.当我在一个Fragment
禁用位置权限时,应用程序崩溃,因为它重新启动,然后使用片段堆栈恢复FragmentManager
,然后启动MainActivity
。 So ViewModel
got location status too early (in constructor) and threw an exception.因此ViewModel
过早地(在构造函数中)获得了位置状态并引发了异常。 But when I moved getting location status to a function, then the application restarted normally.但是当我将获取位置状态移动到一个函数时,应用程序会正常重新启动。
So, using Dagger, you can write something like:因此,使用 Dagger,您可以编写如下内容:
AppModule:
@JvmStatic
@Provides
fun provideActivity(app: MainApplication): AppCompatActivity = app.mainActivity
In MainApplication
hold mainActivity
and in MainActivity
set in onCreate
:在MainApplication
持有mainActivity
并在MainActivity
设置onCreate
:
application.mainActivity = this
In onDestroy
:在onDestroy
:
application.mainActivity = null
In any ViewModel
add:在任何ViewModel
添加:
class SomeViewModel @Inject constructor(
private val activity: Provider<AppCompatActivity>
)
Then use it: activity.get().getString(R.string.some_string)
.然后使用它: activity.get().getString(R.string.some_string)
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.