简体   繁体   English

如何在 JAVA 中弃用 ViewModelProviders 后实现 ViewModelProvider

[英]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.

相关问题 ViewModelProvider.of 和 ViewModelProvider 在 Android Java 中均已弃用 - ViewModelProvider.of and ViewModelProvider both are deprecated in Android Java 不推荐使用“ViewModelProviders”。 Java解决方案? - 'ViewModelProviders' is deprecated. Java solution? ViewModelProviders 和 ViewModelProvider 类有什么区别? - What is the difference between ViewModelProviders and ViewModelProvider class? ViewModelProviders 在 1.1.0 中已弃用 - ViewModelProviders is deprecated in 1.1.0 已弃用的 ViewModelProviders 的替代方案? - Alternative for deprecated ViewModelProviders? 由于不推荐使用 ViewModelProviders.of(),我应该如何创建 ViewModel 的 object? - As ViewModelProviders.of() is deprecated, how should I create object of ViewModel? 如何在 Java 中使用 androidx.lifecycle.ViewModelProvider - How to use the androidx.lifecycle.ViewModelProvider in Java 我应该使用 ViewModelProvider 而不是 ViewModelProviders 吗? 如果是这样,为什么? - Should I be using ViewModelProvider instead of ViewModelProviders? If so, why? 为什么 ViewModelProviders 已被弃用? - Why has ViewModelProviders been deprecated? 'ViewModelProviders' 已弃用。 升级生命周期扩展后:2.1.0 到 2.2.0-alpha05 - 'ViewModelProviders' is deprecated. After upgrading lifecycle-extensions:2.1.0 to 2.2.0-alpha05
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM