[英]How to implement ViewModelProvider after ViewModelProviders deprecated in JAVA
I've tried to use CustomViewModel to keep information when Activity destroy and create as view changes.我尝试使用 CustomViewModel 在 Activity 销毁并创建为视图更改时保留信息。
public class MyViewModel extends ViewModel {
private MutableLiveData<Long> startTime;
public MutableLiveData<Long> getStartTime(){
if(startTime == null) {
startTime = new MutableLiveData<Long>((long) 0);
}
return this.startTime;
}
public void setStartTime(MutableLiveData<Long> startTime) {
this.startTime = startTime;
}
}
This is custom ViewModel to keep time information even after Activity recreated.这是自定义 ViewModel,即使在 Activity 重新创建后也能保留时间信息。
public class ViewModelActivity extends Activity implements ViewModelStoreOwner, LifecycleOwner{
private static String TAG = "ViewModelActivity";
private MyViewModel model;
private ViewModelProvider.AndroidViewModelFactory viewModelFactory;
private ViewModelStore viewModelStore = new ViewModelStore();
private LifecycleRegistry lifecycleRegistry;
private Chronometer chronometer;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_viewmodel);
chronometer = (Chronometer) findViewById(R.id.chronometer);
if(viewModelFactory == null){
viewModelFactory = ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication());
}
model = new ViewModelProvider(this, viewModelFactory).get(MyViewModel.class);
final Observer<Long> timeObserver = new Observer<Long>(){
@Override
public void onChanged(Long time) {
chronometer.setBase(time);
}
};
model.getStartTime().observe(this, timeObserver);
lifecycleRegistry = new LifecycleRegistry(this);
lifecycleRegistry.addObserver(new CustomLifeCycleObserver());
lifecycleRegistry.setCurrentState(Lifecycle.State.CREATED);
chronometer.start();
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.e(TAG, "onDestroy");
}
@NonNull
@Override
public ViewModelStore getViewModelStore() {
return viewModelStore;
}
@NonNull
@Override
public Lifecycle getLifecycle() {
return lifecycleRegistry;
}
}
Instead of using ViewModelProviders, I tried to use ViewModelProvider with help of Google Developer Docs with link as below.我没有使用 ViewModelProviders,而是尝试在 Google Developer Docs 的帮助下使用 ViewModelProvider,链接如下。
https://developer.android.com/topic/libraries/architecture/viewmodel?hl=en#java https://developer.android.com/topic/libraries/architecture/viewmodel?hl=en#java
https://developer.android.com/topic/libraries/architecture/livedata?hl=ko https://developer.android.com/topic/libraries/architecture/livedata?hl=ko
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
android:layout_height="match_parent">
<Chronometer
android:id="@+id/chronometer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"/>
</RelativeLayout>
layout only contains Cronometer to show time.布局仅包含计时表来显示时间。 However, I could not solve this prob.但是,我无法解决这个问题。
java.lang.RuntimeException: Unable to start activity ComponentInfo{wizley.android.playground/wizley.android.playground.viewmodel.ViewModelActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'androidx.lifecycle.Lifecycle$State androidx.lifecycle.Lifecycle.getCurrentState()' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3333)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3477)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2043)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7464)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:549)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:955)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'androidx.lifecycle.Lifecycle$State androidx.lifecycle.Lifecycle.getCurrentState()' on a null object reference
at androidx.lifecycle.LiveData.observe(LiveData.java:190)
at wizley.android.playground.viewmodel.ViewModelActivity.onCreate(ViewModelActivity.java:52)
at android.app.Activity.performCreate(Activity.java:7990)
at android.app.Activity.performCreate(Activity.java:7979)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3308)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3477)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2043)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:216)
at android.app.ActivityThread.main(ActivityThread.java:7464)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:549)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:955)
In other posts, they did not implemented LifeCycleOwner but ViewModel observe method needs LifeCycleOwner to be implemented for first parameter.在其他帖子中,他们没有实现 LifeCycleOwner,但 ViewModel 观察方法需要为第一个参数实现 LifeCycleOwner。
I think I got something wrong, but couldn't solve it on my own.我想我出了点问题,但我自己无法解决。
As Cong Hai said, AppCompatActiviy has Lifecycleowner, so I changed my code like this.正如丛海所说,AppCompatActiviy 有 Lifecycleowner,所以我就这样改了代码。
public class MyViewModel extends ViewModel {
private long startTime = SystemClock.elapsedRealtime();
private long timetick = 0;
public long getStartTime() {
return startTime;
}
public long getTimeTick() {
return this.timetick;
}
public void setTimeTick(long timetick) {
this.timetick = timetick;
}
}
Activity as below.活动如下。
public class ViewModelChronometerActivity extends AppCompatActivity {
private static String TAG = "ViewModelActivity";
private MyViewModel model;
private Chronometer chronometer;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_viewmodel_chronometer);
chronometer = (Chronometer) findViewById(R.id.chronometer);
model = new ViewModelProvider(this,
ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication())).get(MyViewModel.class);
Log.e(TAG, String.valueOf(model.getTimeTick()));
chronometer.setBase(model.getStartTime());
chronometer.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() {
@Override
public void onChronometerTick(Chronometer chronometer) {
model.setTimeTick(model.getTimeTick()+1);
Log.e(TAG, String.valueOf(model.getTimeTick()));
}
});
chronometer.start();
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.e(TAG, "onDestroy");
if(isFinishing()){
Log.e(TAG, "isFinishing");
} else {
Log.e(TAG, "Rotating orientation");
}
}
}
as a result, I could retain elapsedtime info with timtetick.因此,我可以使用 timtetick 保留经过的时间信息。
2020-06-17 16:06:52.147 29172-29172/wizley.android.playground E/ViewModelActivity: 0
2020-06-17 16:06:52.179 29172-29172/wizley.android.playground E/ViewModelActivity: 1
2020-06-17 16:06:53.181 29172-29172/wizley.android.playground E/ViewModelActivity: 2
2020-06-17 16:06:54.185 29172-29172/wizley.android.playground E/ViewModelActivity: 3
2020-06-17 16:06:55.007 29172-29172/wizley.android.playground E/ViewModelActivity: onDestroy
2020-06-17 16:06:55.007 29172-29172/wizley.android.playground E/ViewModelActivity: Rotating orientation
2020-06-17 16:06:55.068 29172-29172/wizley.android.playground E/ViewModelActivity: 3
2020-06-17 16:06:55.082 29172-29172/wizley.android.playground E/ViewModelActivity: 4
2020-06-17 16:06:56.086 29172-29172/wizley.android.playground E/ViewModelActivity: 5
2020-06-17 16:06:57.090 29172-29172/wizley.android.playground E/ViewModelActivity: 6
And below is example of MutableLiveData with observer.下面是带有观察者的 MutableLiveData 示例。
public class MyViewModel extends ViewModel {
private long startTime = SystemClock.elapsedRealtime();
private MutableLiveData<Long> timetick;
public MyViewModel(){
timetick = new MutableLiveData<>();
timetick.setValue((long)0);
}
public long getStartTime() {
return startTime;
}
public long getTimeTick() {
return this.timetick.getValue();
}
public MutableLiveData<Long> getTick(){
return this.timetick;
}
public void setTimeTick(long timetick) {
this.timetick.setValue(timetick);
}
public void increaseTick(){
setTimeTick(timetick.getValue()+1);
}
}
Activity with observer to print log.与观察者一起打印日志的活动。
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_viewmodel_chronometer);
chronometer = (Chronometer) findViewById(R.id.chronometer);
model = new ViewModelProvider(this,
ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication())).get(MyViewModel.class);
Log.e(TAG, String.valueOf(model.getTimeTick()));
chronometer.setBase(model.getStartTime());
chronometer.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() {
@Override
public void onChronometerTick(Chronometer chronometer) {
model.setTimeTick(model.getTimeTick()+1);
}
});
final Observer<Long> tickObserver = new Observer<Long>(){
@Override
public void onChanged(Long aLong) {
Log.e(TAG, String.valueOf(model.getTimeTick()));
}
};
model.getTick().observe(this, tickObserver);
chronometer.start();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.