这里写目录标题
ViewModel
ViewModel 类旨在以注重生命周期的方式存储和管理界面相关的数据。ViewModel 类让数据可在发生屏幕旋转等配置更改后继续留存。
它和onSaveInstanceState方法相比更有优势,因为onSaveInstanceState方法只不适合大量数据的恢复操作,只能恢复少量并且被序列化和反序列化的数据,而ViewModel不仅支持大量数据,还不需要序列化、反序列化操作。
生命周期
MainActivity
public class MainActivity extends AppCompatActivity {
MyViewModel myViewModel;
TextView textView;
Button button1;
Button button2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.textView);
button1 = findViewById(R.id.button);
button2 = findViewById(R.id.button2);
//使用ViewwModel
myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
textView.setText(String.valueOf(myViewModel.number));
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
myViewModel.number++;
textView.setText(String.valueOf(myViewModel.number));
});
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
myViewModel.number+=2;
textView.setText(String.valueOf(myViewModel.number));
});
}
}
MyViewModel
package com.example.studyui;
import androidx.lifecycle.ViewModel;
public class MyViewModel extends ViewModel {
public int number;
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
}
LiveData
使用LiveData优点:
-
保证用户界面与数据状态匹配
LiveData遵循观察者模式。在生命周期状态更改时LiveData会通知Observer对象。您可以升级代码在observer对象中更新UI,不必每次数据改变时手动更新UI,观察者可以在每次更改时更新UI。 -
没有内存泄漏
观察者与Lifecycle对象绑定,并在具有生命周期的对象被destroyed后自行清理。 -
停止activities不会导致崩溃
如果观察者的生命周期处于非活动状态,例如在后退堆栈中的活动,则不会收到任何LiveData事件。 -
无需手动处理生命周期
UI组件只是观察相关数据,不会停止或恢复观察。LiveData自动管理所有这些操作,因为在观察时它实时响应相关的生命周期状态的变化。 -
始终保持最新的数据
如果生命周期变为非活动状态,它将在再次变为活动状态时接收到最新的数据。例如,后台活动在返回到前台后立即收到最新数据。 -
正确的配置更改
如果由于配置更改(如设备旋转)而重新创建活动或片段,则会立即收到最新的可用数据。 -
共享资源
可以使用单例模式来扩展LiveData对象来包装系统服务,以便它们可以在应用程序中共享。LiveData对象一旦连接到系统服务,然后其他任何需要系统资源的观察者只需要观看该LiveData 对象就可以。
MainActivity
public class MainActivity extends AppCompatActivity {
MyViewModel myViewModel;
ViewModelWithLifeData viewModelWithLifeData;
TextView textView;
Button button1;
Button button2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.textView);
button1 = findViewById(R.id.button);
button2 = findViewById(R.id.button2);
//使用ViewwModel
//myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
//textView.setText(String.valueOf(myViewModel.number));
//使用LifeData,绑定控制器
viewModelWithLifeData = ViewModelProviders.of(this).get(ViewModelWithLifeData.class);
viewModelWithLifeData.getLikedData().observe(this, new Observer<Integer>() {
@Override
public void onChanged(Integer integer) {
textView.setText(String.valueOf(integer));
}
});
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// myViewModel.number++;
// textView.setText(String.valueOf(myViewModel.number));
viewModelWithLifeData.addLikedData(1);
}
});
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// myViewModel.number+=2;
// textView.setText(String.valueOf(myViewModel.number));
viewModelWithLifeData.addLikedData(-1);
}
});
}
}
ViewModelWithLifeData
package com.example.studyui;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
public class ViewModelWithLifeData extends ViewModel {
private MutableLiveData<Integer> LikedData;
public MutableLiveData<Integer> getLikedData() {
// if (LikedData == null){
// LikedData = new MutableLiveData<>();
// LikedData.setValue(0);
// }
return LikedData;
}
ViewModelWithLifeData(){
LikedData = new MutableLiveData<>();
LikedData.setValue(0);
}
public void addLikedData(int n){
LikedData.setValue(LikedData.getValue()+n);
}
}
DataBanding数据绑定
绑定
activity_main
在gradle中添加最后一句:
然后切换至binding layout:
然后就会变成这样:
MainActivity
public class MainActivity extends AppCompatActivity {
MyViewModel myViewModel;
ViewModelWithLifeData viewModelWithLifeData;
//TextView textView;
//Button button1;
//Button button2;
ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//setContentView(R.layout.activity_main);
//无需findviewbyid,直接会绑定到ActivityMainBinding对象里
binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
//textView = findViewById(R.id.textView);
//button1 = findViewById(R.id.button);
//button2 = findViewById(R.id.button2);
//使用ViewwModel
myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
//textView.setText(String.valueOf(myViewModel.number));
//DataBinding
myViewModel.getNumber().observe(this, new Observer<Integer>() {
@Override
public void onChanged(Integer integer) {
binding.textView.setText(String.valueOf(integer));
}
});
//使用LifeData,绑定控制器
// viewModelWithLifeData = ViewModelProviders.of(this).get(ViewModelWithLifeData.class);
// viewModelWithLifeData.getLikedData().observe(this, new Observer<Integer>() {
// @Override
// public void onChanged(Integer integer) {
// textView.setText(String.valueOf(integer));
// }
// });
binding.button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// myViewModel.number++;
// textView.setText(String.valueOf(myViewModel.number));
//viewModelWithLifeData.addLikedData(1);
myViewModel.add();
}
});
binding.button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// myViewModel.number+=2;
// textView.setText(String.valueOf(myViewModel.number));
viewModelWithLifeData.addLikedData(-1);
}
});
}
}
反向绑定
activity_main
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="data"
type="com.example.studyui.MyViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
//回绑更新数据
android:text="@{String.valueOf(data.number)}"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.217" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="好评"
//呼叫函数
android:onClick="@{()->data.add()}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.4" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="差评"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.8"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.4" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
MainActivity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
binding.setData(myViewModel);
binding.setLifecycleOwner(this);
}
ViewModelSavedState
打开Don’t…选项,模拟进入后台即杀死程序
方法1
MainActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
if(savedInstanceState!=null){
//将数据取出放入KEY_NUMBER
myViewModel.getNumber().setValue(savedInstanceState.getInt(KEY_NUMBER));
}
binding.setData(myViewModel);
binding.setLifecycleOwner(this);
@Override
public void onSaveInstanceState(@NonNull Bundle outState, @NonNull PersistableBundle outPersistentState) {
super.onSaveInstanceState(outState, outPersistentState);
outState.putInt(KEY_NUMBER,myViewModel.getNumber().getValue());
方法2
在MyViewModel类中添加SavedStateHandle类对象,用此对象提供数据
MyViewModel
public class MyViewModel extends ViewModel {
/*public int number;
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}*/
private MutableLiveData<Integer> number;
private SavedStateHandle handle;
public MyViewModel(SavedStateHandle handle){
this.handle = handle;
}
public MutableLiveData<Integer> getNumber(){
/*if(number == null){
number = new MutableLiveData<>();
number.setValue(0);
}
return number;*/
if(!handle.contains(MainActivity.KEY_NUMBER)){
handle.set(MainActivity.KEY_NUMBER,0);
}
return handle.getLiveData(MainActivity.KEY_NUMBER);
}
public void add(){
//number.setValue(number.getValue()+1);
getNumber().setValue(getNumber().getValue()+1);
}
}
能访问SharedPerferences的ViewModel
导包:
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0-rc02'
MainActivity
ublic class MainActivity extends AppCompatActivity {
MyViewModel myViewModel;
ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//myViewModel.application = getApplication();
binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
myViewModel = ViewModelProviders.of(this, new SavedStateViewModelFactory(getApplication(), this)).get(MyViewModel.class);
binding.setData(myViewModel);
binding.setLifecycleOwner(this);
myViewModel.load();
}
@Override
protected void onPause() {
super.onPause();
myViewModel.save();
}
}
MyViewModel
public class MyViewModel extends AndroidViewModel {
Application application;
SavedStateHandle handle;
String key = getApplication().getResources().getString(R.string.data_key);
String shpName = getApplication().getResources().getString(R.string.shp_name);
public MyViewModel(@NonNull Application application, SavedStateHandle handel) {
super(application);
this.handle = handel;
if(!handel.contains(key)){
load();
}
}
public LiveData<Integer> getNumber(){
return handle.getLiveData(key);
}
public void load() {
SharedPreferences shp = getApplication().getSharedPreferences(shpName, Context.MODE_PRIVATE);
int x = shp.getInt(key,0);
//读取
handle.set(key,x);
}
public void save(){
SharedPreferences shp = getApplication().getSharedPreferences(shpName,Context.MODE_PRIVATE);
SharedPreferences.Editor editor = shp.edit();
editor.putInt(key,getNumber().getValue());
editor.apply();
}
public void add(int x){
handle.set(key,getNumber().getValue()+x);
//不建议,开销大
//save();
}
}
格式化
Navigation
(1)切换页面
MainActivity
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
NavController controller = Navigation.findNavController(this,R.id.fragment);
NavigationUI.setupActionBarWithNavController(this,controller);
}
@Override
public boolean onSupportNavigateUp() {
NavController controller = Navigation.findNavController(this,R.id.fragment);
return controller.navigateUp();
// return super.onSupportNavigateUp();
}
}
HomeFragment
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Button button;
button = getView().findViewById(R.id.button3);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
NavController controller = Navigation.findNavController(view);
controller.navigate(R.id.action_homeFragment_to_detailFragment);
}
});
}
DetailFragment
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getView().findViewById(R.id.button).setOnClickListener(Navigation.createNavigateOnClickListener(R.id.action_detailFragment_to_homeFragment));
}
nav布局
(2)页面之间数据传递(静态)
添加Arguments
DetailFragment
@Override
public void onActivityCreated( Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
TextView textView = getView().findViewById(R.id.textView);
textView.setText(getArguments().getString("name"));
}
(2)页面之间数据传递(动态)
HomeFragment
@Override
public void onActivityCreated( Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getView().findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
EditText editText = getView().findViewById(R.id.editTextTextPersonName);
String str = editText.getText().toString();
if (TextUtils.isEmpty(str)){
Toast.makeText(getActivity(), "请输入名字", Toast.LENGTH_SHORT).show();
}
NavController controller = Navigation.findNavController(view);
controller.navigate(R.id.detailFragment);
//推送
Bundle bundle = new Bundle();
bundle.putString("my_name",str);
Toast.makeText(getActivity(), "请输入名字", Toast.LENGTH_SHORT).show();
}
});
}
DetailFragment
@Override
public void onActivityCreated( Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
String str = getArguments().getString("name");
String str2 = getArguments().getString("my_name");
TextView textView = getView().findViewById(R.id.textView);
textView.setText(str2);
}