ViewModel的简单使用

  • Post author:
  • Post category:其他


关于ViewModel来说,其实还是蛮简单的。从ViewModel官方的描述来看ViewModel的存在,解决了俩大问题:

1.1、解决问题1

我们都知道,当我们的Activity/Fragment因为某些因素被销毁重建时,我们的成员变量便失去了意义。因此我们常常需要通过 onSaveInstanceState()和onCreate()/onSaveInstanceState(Bundle)完成对数据的恢复(通常还要保证其正确的序列化)。并且对于大型数据来书,便有些乏力,比如:List、Bitmap…

而ViewModel就是解决此问题。

1.2、解决问题2

另一个问题是Activity/Fragment经常需要进行一些异步操作。一旦涉及到异步,我们都明白这里存在内存泄漏的可能性。因此我们保证Activity/Fragment在销毁后及时清理异步操作,以避免潜在的内存泄漏。

ViewModel并没有自动帮我们解决这个问题,而是通过onCleared()交给我们业务自己重写去处理。

1.3、使用

build.gradle:

implementation "android.arch.lifecycle:extensions:1.1.1"

TimerViewModel.java

package com.jxd.studyone.viewmodel;

import android.util.Log;

import androidx.lifecycle.ViewModel;

import java.util.Timer;
import java.util.TimerTask;

public class TimerViewModel extends ViewModel
{
    private String TAG = this.getClass().getName();
    private Timer timer;
    private int currentSecond;

    /**
     * 开始计时
     * */
    public void startTiming()
    {
        if (timer == null)
        {
            currentSecond = 0;
            timer = new Timer();
            TimerTask timerTask = new TimerTask()
            {
                @Override
                public void run()
                {
                    currentSecond++;
                    if(onTimeChangeListener != null)
                    {
                        onTimeChangeListener.onTimeChanged(currentSecond);
                    }
                }
            };
            timer.schedule(timerTask, 1000, 1000);//延迟3秒执行
        }
    }

    /**
     * 通过接口的方式,完成对调用者的通知,这种方式不是太好,更好的方式是通过LiveData组件来实现
     * */
    public interface OnTimeChangeListener
    {
        void onTimeChanged(int second);
    }

    private OnTimeChangeListener onTimeChangeListener;

    public void setOnTimeChangeListener(OnTimeChangeListener onTimeChangeListener)
    {
        this.onTimeChangeListener = onTimeChangeListener;
    }

    /**
     * 由于屏幕旋转导致的Activity重建,该方法不会被调用
     *
     * 只有ViewModel已经没有任何Activity与之有关联,系统则会调用该方法,你可以在此清理资源
     * */
    @Override
    protected void onCleared()
    {
        super.onCleared();
        Log.d(TAG, "onCleared()");
        timer.cancel();
    }
}

ViewModelActivity.java

package com.jxd.studyone.viewmodel;

import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.ViewModelProviders;

import android.os.Bundle;
import android.widget.TextView;

import com.jxd.studyone.R;

public class ViewModelActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_view_model);
        iniComponent();
    }

    private void iniComponent()
    {
        final TextView tvTime = findViewById(R.id.tv_time);
        //通过ViewModelProviders得到ViewModel,如果ViewModel不存在就创建一个新的,如果已经存在就直接返回已经存在的
        TimerViewModel timerViewModel = ViewModelProviders.of(this).get(TimerViewModel.class);
        timerViewModel.setOnTimeChangeListener(new TimerViewModel.OnTimeChangeListener()
        {
            @Override
            public void onTimeChanged(final int second)
            {
                //更新UI界面
                runOnUiThread(new Runnable()
                {
                    @Override
                    public void run()
                    {
                        tvTime.setText("TIME:" + second);
                    }
                });
            }
        });

        timerViewModel.startTiming();
    }
}

可以看到的是,当屏幕旋转时,数据并没有收到影响。



版权声明:本文为u012539700原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。