简单使用LiveData+ViewModel

因公司项目技术需求,开始使用LiveData+ViewModel 架构,这东西是Google 2017 IO大会新发布的官方推荐架构(Lifecycle,LiveData,ViewModel,Room,Paging,Navigation)中的一部分。关于使用LiveData+ViewModel的优点就不详细解析了,主要为以下几点:
(1)数据绑定,数据改变时,UI同步跟着改变。
(2)LiveData内部使用Lifecycle管理Activity或fragment的生命周期,只在UI活跃情况下才更新数据,不活跃情况下不更新
(3)Lifecycle管理生命周期,可避免内存泄露

具体使用:
(1)引入工程
工程的build.gradle

allprojects {
    repositories {
        google()
        jcenter()
    }
}

app 的build.gradle

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

(2)创建ViewModel

public class UserModel extends ViewModel {

    private MutableLiveData userLiveData = new MutableLiveData<>();

    public void setUserLiveData(User user) {
        this.userLiveData.setValue(user);
    }

    public MutableLiveData getUserLiveData() {
        return userLiveData;
    }

}
public class User {

    private String name;
    private int age;
    private String sex;
    private String hobby;

    public User(String name, int age, String sex, String hobby) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.hobby = hobby;
    }
    //getter and setter
    .......
}

(3)在Activity或fragment订阅数据

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private TextView mTextViewName;
    private TextView mTextViewAge;
    private TextView mTextViewSex;
    private TextView mTextViewHobby;
    private UserModel mUserModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.button_edit_name).setOnClickListener(this);
        mTextViewName = findViewById(R.id.text_view_name);
        mTextViewAge = findViewById(R.id.text_view_age);
        mTextViewSex = findViewById(R.id.text_view_sex);
        mTextViewHobby = findViewById(R.id.text_view_hobby);
        mUserModel = ViewModelProviders.of(this).get(UserModel.class);

        User user = new User("超人", 10, "男", "飞来飞去");

        //初始化数据
        mUserModel.setUserLiveData(user);
        //订阅数据
        mUserModel.getUserLiveData().observe(this, new Observer() {
            @Override
            public void onChanged(@Nullable User user) {
                mTextViewName.setText("姓名:" + user.getName());
                mTextViewAge.setText("年龄:" + user.getAge());
                mTextViewSex.setText("性别:" + user.getSex());
                mTextViewHobby.setText("爱好:" + user.getHobby());
            }
        });
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button_edit_name:
                mUserModel.getUserLiveData().postValue(new User("奥特曼", 20, "女", "跳来跳去"));
                break;
        }
    }
}

效果就不作展示了,具体点击按钮就能改变数据,相应的数据变化后会调用onChanged函数

使用起来相对很简单,但细心的人会注意要,上面每修改一次数据,就new一个对象出来,这在项目中是不正常的。按正常思维来说,只要直接修改对象中的数据,就能达到变化才对。所以对上面代码进行修改。

(4)修改后的ViewModel

public class UserModel3 extends ViewModel {

    private MutableLiveData userLiveData = new MutableLiveData<>();

    public void setUserLiveData(User user) {
        this.userLiveData.setValue(user);
    }

    public MutableLiveData getUserLiveData() {
        return userLiveData;
    }

    public void setValueName(String name) {
        this.userLiveData.getValue().setName(name);
        this.userLiveData.postValue(userLiveData.getValue());
    }

    public void setValueAge(int age) {
        this.userLiveData.getValue().setAge(age);
        this.userLiveData.postValue(userLiveData.getValue());
    }

    public void setValueSex(String sex) {
        this.userLiveData.getValue().setSex(sex);
        this.userLiveData.postValue(userLiveData.getValue());
    }

    public void setValueHobby(String hobby) {
        this.userLiveData.getValue().setHobby(hobby);
        this.userLiveData.postValue(userLiveData.getValue());
    }
}

(5)使用修改后的ViewModel

public class MainActivity2 extends AppCompatActivity implements View.OnClickListener {

    private TextView mTextViewName;
    private TextView mTextViewAge;
    private TextView mTextViewSex;
    private TextView mTextViewHobby;

    private UserModel3 mUserModel3;

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

        findViewById(R.id.button_edit_name).setOnClickListener(this);
        findViewById(R.id.button_edit_age).setOnClickListener(this);
        findViewById(R.id.button_edit_sex).setOnClickListener(this);
        findViewById(R.id.button_edit_hobby).setOnClickListener(this);

        mTextViewName = findViewById(R.id.text_view_name);
        mTextViewAge = findViewById(R.id.text_view_age);
        mTextViewSex = findViewById(R.id.text_view_sex);
        mTextViewHobby = findViewById(R.id.text_view_hobby);
        mUserModel3 = ViewModelProviders.of(this).get(UserModel3.class);

        User user = new User("超人", 10, "男", "飞来飞去");

        mUserModel3.setUserLiveData(user);
        mUserModel3.getUserLiveData().observe(this, new Observer() {
            @Override
            public void onChanged(@Nullable User user) {
                mTextViewName.setText("姓名:" + user.getName());
                mTextViewAge.setText("年龄:" + user.getAge());
                mTextViewSex.setText("性别:" + user.getSex());
                mTextViewHobby.setText("爱好:" + user.getHobby());
            }
        });
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button_edit_name:
                mUserModel3.setValueName("奥特曼");
                break;
            case R.id.button_edit_age:
                mUserModel3.setValueAge(mUserModel3.getUserLiveData().getValue().getAge() + 1);
                break;
            case R.id.button_edit_sex:
                mUserModel3.setValueSex("妹子");
                break;
            case R.id.button_edit_hobby:
                mUserModel3.setValueHobby("妹子+运动");
                break;
        }
    }
}

可以看出在新的UserModel3中,调用set...方法是先对象属性,再把修改后的对象重新赋值,这样避免频繁创建对象。

最后再简单看看LiveData的源码,源码不多,400行左右,比较容易看明白。

从更新数据调用postValue开始:

protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }
   private final Runnable mPostValueRunnable = new Runnable() {
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            //noinspection unchecked
            setValue((T) newValue);    //最后还是调用setValue
        }
    };
    @MainThread
    protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;  //数据版本加一
        mData = value;  
        dispatchingValue(null);  //通知订阅者更新数据
    }
    private void dispatchingValue(@Nullable ObserverWrapper initiator) {
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
            if (initiator != null) {
                considerNotify(initiator);
                initiator = null;
            } else {
                for (Iterator, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                     //把所有订阅者找出来迭代通知
                    considerNotify(iterator.next().getValue()); 
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }
    private void considerNotify(ObserverWrapper observer) {
        if (!observer.mActive) {
            return;
        }
     
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        if (observer.mLastVersion >= mVersion) {  //判断数据是不是更新了
            return;
        }
        observer.mLastVersion = mVersion;
        //noinspection unchecked
        observer.mObserver.onChanged((T) mData);    //在这里调用onChange更新数据
    }

你可能感兴趣的:(简单使用LiveData+ViewModel)