Android開發 LiveData與MutableLiveData詳解


前言

  LiveData與ViewMode是經常搭配在一起使用的,但是為了不太混亂,我還是拆分開來說明,此篇博客只講解 LiveData 與 MutableLiveData的概念與使用方式(但是會涉及到ViewMode的部分代碼).

LiveData是干什么的?

  由於LiveData和MutableLiveData都是一個概念的東西(只是作用范圍不同)所以就不重復解釋了,直接理解LiveData就可以明白MutableLiveData

  直接理解LiveData的字面意思是前台數據,其實這其實是很准確的表達.下面我們來說說LiveData的幾個特征:

1.首先LiveData其實與數據實體類(POJO類)是一樣的東西,它負責暫存數據.

2.其次LiveData其實也是一個觀察者模式的數據實體類,它可以跟它注冊的觀察者回調數據是否已經更新.

3.LiveData還能知曉它綁定的Activity或者Fragment的生命周期,它只會給前台活動的activity回調(這個很厲害).這樣你可以放心的在它的回調方法里直接將數據添加到View,而不用擔心會不會報錯.(你也可以不用費心費力判斷Fragment是否還存活)

LiveData與MutableLiveData區別

LiveData與MutableLiveData的其實在概念上是一模一樣的.唯一幾個的區別如下:

1.MutableLiveData的父類是LiveData

2.LiveData在實體類里可以通知指定某個字段的數據更新.

3.MutableLiveData則是完全是整個實體類或者數據類型變化后才通知.不會細節到某個字段

 

LiveData簡單使用Demo

創建LiveData

public class DemoData extends LiveData<DemoData> {
    private int tag1;
    private int tag2;
    
    public int getTag1() {
        return tag1;

    }
    public void setTag1(int tag1) {
        this.tag1 = tag1;
        postValue(this);
    }

    public int getTag2() {
        return tag2;
    }

    public void setTag2(int tag2) {
        this.tag2 = tag2;
        postValue(this);
    }
}

很簡單,只要繼承LiveData並且在泛型里寫下你的實體類,唯一需要注意的,postValue(this);這個方法是用於回調數據更新的方法. 你可以在你需要被觀察的數據里添加.

創建ViewModel

我們需要在ViewModel實例化DemoData這個類. ViewModel(這個會在另一篇博客介紹)這個是用於管理多個Activity或者Fragment數據的類。ViewModel是MVVM的概念。你可以百度一下,google提供這套東西就是為了MVVM。

public class DemoViewModel extends ViewModel {
    // TODO: Implement the ViewModel
    private DemoData mDemoData = new DemoData();

    public DemoData getDemoData() {
        return mDemoData;
    }
}

在Activity或者Fragment綁定

public class Demo2Activity extends AppCompatActivity {
    private static final String TAG = "Demo2Activity";
    private Button mBtnAddData;
    private DemoViewModel mDemoViewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_demo2);
        mBtnAddData = findViewById(R.id.btn_add_data);
        mDemoViewModel = ViewModelProviders.of(this).get(DemoViewModel.class);//獲取ViewModel,讓ViewModel與此activity綁定
        mDemoViewModel.getDemoData().observe(this, new Observer<DemoData>() { //注冊觀察者,觀察數據的變化
            @Override
            public void onChanged(DemoData demoData) {
                Log.e(TAG, "onChanged: 數據有更新");
            }
        });
        
        mBtnAddData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.e(TAG, "onClick: 已經點擊");
                mDemoViewModel.getDemoData().setTag1(123); //這里手動用按鍵點擊更新數據

            }
        });
    }
}

當我們點擊按鍵后就會有數據更新后的回調觸發:

2019-09-18 19:45:53.821 6649-6649/demo.yt.com.demo E/Demo2Activity: onClick: 已經點擊
2019-09-18 19:45:53.824 6649-6649/demo.yt.com.demo E/Demo2Activity: onChanged: 數據有更新

前面提過了,但是這里還是需要重新提一下! 注意! 這個數據只給前台的活動回調.

 

MutableLiveData簡單使用Demo

   前面已經解釋了,所以我們這邊直接看代碼

創建MutableLiveData

public class DemoViewModel extends ViewModel {
    // TODO: Implement the ViewModel
    private MutableLiveData<String> myString = new MutableLiveData<>();

    public MutableLiveData<String> getMyString(){
        return myString;
    }

    public void setMyString(String string) {
        this.myString.setValue(string);
    }
}

因為MutableLiveData只是作用於變量所以我們直接就可以在ViewModel里實例化它,並且在泛型里標注變量的類型.

public class MutableLiveData<T> extends LiveData<T> {
    @Override
    public void postValue(T value) {
        super.postValue(value);
    }

    @Override
    public void setValue(T value) {
        super.setValue(value);
    }
}

 

在Activity或者Fragment綁定

public class Demo1Activity extends AppCompatActivity {
    private static final String TAG = "Demo1Activity";
    private DemoViewModel mDemoViewModel;
    private Button mBtn1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_demo);
        mBtn1 = findViewById(R.id.btn_1);
        mDemoViewModel = ViewModelProviders.of(this).get(DemoViewModel.class);//獲取ViewModel,讓ViewModel與此activity綁定
        mDemoViewModel.getMyString().observe(this, new Observer<String>() { //注冊觀察者
            @Override
            public void onChanged(String s) {
                Log.e(TAG, "onChanged: 值有變化="+s);
            }
        });

        mBtn1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mDemoViewModel.setMyString("測試"); //用手動按鍵點擊改變值


            }
        });
    }
}

 結果:

2019-09-18 19:59:38.294 6961-6961/demo.yt.com.demo E/Demo1Activity: onChanged: 值有變化=測試

API全解

postValue()

  可能你已經在上面看到幾次調用此方法了。postValue的特性如下:

  1.此方法可以在其他線程中調用

  2.如果在主線程執行發布的任務之前多次調用此方法,則僅將分配最后一個值。

  3.如果同時調用 .postValue(“a”)和.setValue(“b”),一定是值b被值a覆蓋。

setValue()

  setValue()的特性如下:

  1.此方法只能在主線程里調用

getValue()

  返回當前值。 注意,在后台線程上調用此方法並不能保證將接收到最新的值。

removeObserver(@NonNull final Observer<? super T> observer) 

  移除指定的觀察者

例子:

        Observer<String> observer = new Observer<String>() {
            @Override
            public void onChanged(String s) {
                mText.setText("內容改變=" + s);
            }
        };
        mMainViewModel.getContent().observe(this, observer);//綁定
        mMainViewModel.getContent().removeObserver(observer);//解除

removeObservers(@NonNull final LifecycleOwner owner)

  移除當前Activity或者Fragment的全部觀察者

mMainViewModel.getContent().removeObservers(this);

 hasActiveObservers()

  如果此LiveData具有活動(Activity或者Fragment在前台,當前屏幕顯示)的觀察者,則返回true。其實如果這個數據的觀察者在最前台就返回true,否則false。

hasObservers()

  如果此LiveData具有觀察者,則返回true。

 

observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer)

  設置此LiveData數據當前activity或者Fragment的觀察者,會給此activity或者Fragment在前台時回調數據。

 

observeForever(@NonNull Observer<? super T> observer)

  1.設置永遠觀察者,永遠不會被自動刪除。您需要手動調用removeObserver(Observer)以停止觀察此LiveData,

  2.設置后此LiveData,一直處於活動狀態,不管是否在前台哪里都會獲得回調。

 

END


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM