繁体   English   中英

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

[英]How to implement ViewModelProvider after ViewModelProviders deprecated in JAVA

我尝试使用 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;
    }
}

这是自定义 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;
    }

}

我没有使用 ViewModelProviders,而是尝试在 Google Developer Docs 的帮助下使用 ViewModelProvider,链接如下。

https://developer.android.com/topic/libraries/architecture/viewmodel?hl=en#java

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>

布局仅包含计时表来显示时间。 但是,我无法解决这个问题。

    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) 

在其他帖子中,他们没有实现 LifeCycleOwner,但 ViewModel 观察方法需要为第一个参数实现 LifeCycleOwner。

我想我出了点问题,但我自己无法解决。

正如丛海所说,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;
    }
}

活动如下。

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

}

因此,我可以使用 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

下面是带有观察者的 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);
    }
}

与观察者一起打印日志的活动。

    @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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM