-
建议先了解《Lifecycle原理、源码解析》
-
LiveData是一种具有生命周期感知能力的可观察数据持有类
-
LiveData可以保证屏幕上的显示内容和数据一直保持同步
-
特点:
-
1.LiveData了解UI界面的状态,如果activity不在屏幕上显示,livedata不会触发没必要的界面更新,如果activity已经被销毁,会自动清空与observer的连接,意外的调用就不会发生
-
2.LiveData是一个LifecycleOwner,他可以直接感知activity或fragment的生命周期
使用
- 项目中livedata一般都存放在ViewModel中,以保证app配置变更时,数据不会丢失
- 使用注意:
setValue只能在主线程运行
postValue只能在子线程中运行
方式一
- 定义一个viewmodel保存名字
package com.example.livedatademo;import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;public class NameViewModel extends ViewModel {private MutableLiveData<String> currentName;public MutableLiveData<String> getCurrentName(){if(currentName==null){currentName=new MutableLiveData<>();}return currentName;}
}
- 在activity里面监听名字变化然后刷新数据
package com.example.livedatademo;import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;public class NameActivity extends AppCompatActivity {private NameViewModel model;private TextView nameTextView;private Button btn;private int i=0;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_name);nameTextView=findViewById(R.id.tvText);btn=findViewById(R.id.btn);//需要一个观察者来观察数据Observer observer=new Observer<String>(){@Overridepublic void onChanged(String s) {nameTextView.setText(s);}};//获取到viewmodelmodel= ViewModelProviders.of(this).get(NameViewModel.class);//取出livedata完成订阅model.getCurrentName().observe(this,observer);btn.setOnClickListener(new View.OnClickListener(){@Overridepublic void onClick(View v) {String anotherName="Gavin"+(i++);model.getCurrentName().setValue(anotherName);}});}
}
方式二
- 定义一个总线LiveDataBus,统一处理
package com.example.livedatademo.databus;import androidx.lifecycle.MutableLiveData;import java.util.HashMap;
import java.util.Map;public class LiveDataBus {//存放订阅者private Map<String, MutableLiveData<Object>> bus;private static LiveDataBus liveDataBus = new LiveDataBus();private LiveDataBus() {bus = new HashMap();}public static LiveDataBus getInstance() {return liveDataBus;}//注册订阅者public synchronized <T> MutableLiveData<T> with(String key, Class<T> type) {if(!bus.containsKey(key)){bus.put(key,new MutableLiveData<Object>());}return (MutableLiveData<T>)bus.get(key);}
}
- 在TestLiveDataBusActivity里面监听数据变化
package com.example.livedatademo;import android.content.Intent;
import android.os.Bundle;
import android.view.View;import androidx.appcompat.app.AppCompatActivity;import com.example.livedatademo.databus.LiveDataBus;public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}public void click(View view) {if (view.getId() == R.id.btn) {Intent intent = new Intent(this, NameActivity.class);startActivity(intent);} else if (view.getId() == R.id.btn2) {Intent intent = new Intent(this, TestLiveDataBusActivity.class);startActivity(intent);new Thread(){@Overridepublic void run() {for (int i = 0; i < 10; i++) {//发送消息LiveDataBus.getInstance().with("data", String.class).postValue("Gavin");try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}}}}.start();}}}
- TestLiveDataBusActivity
package com.example.livedatademo;import android.os.Bundle;
import android.widget.Toast;import androidx.appcompat.app.AppCompatActivity;
import androidx.lifecycle.Observer;import com.example.livedatademo.databus.LiveDataBus;public class TestLiveDataBusActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_livedatabus);LiveDataBus.getInstance().with("data", String.class).observe(this, new Observer<String>() {@Overridepublic void onChanged(String s) {if(s!=null)Toast.makeText(TestLiveDataBusActivity.this, s, Toast.LENGTH_SHORT).show();}});}
}
什么是LiveData的粘性事件(数据倒灌)?
- 在上面的使用方式二中,让R.id.btn2的点击事件里面先更新livedata的数据,然后再创建TestLiveDataBusActivity,会发现TestLiveDataBusActivity还是收到了旧数据通知(还没创建activity前的数据)
- 修改后的代码如下
Intent intent = new Intent(this, TestLiveDataBusActivity.class);
//先更新数据
new Thread(){@Overridepublic void run() {for (int i = 0; i < 10; i++) {//发送消息LiveDataBus.getInstance().with("data", String.class).postValue("Gavin");try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}}}
}.start();
//再创建activity
startActivity(intent);