要实现的功能:
实现一个列表,其中显示班级学号姓名,提供添加功能,如需要删去某一项,长按该项,通过弹出菜单显示删除功能。
先理解两个概念
MVVM是Model-View-的简写。它本质上就是MVC 的改进版。MVVM 就是将其中的View 的状态和行为抽象化,让我们将视图 UI 和业务逻辑分
DataBinding 是谷歌官方发布的一个框架,顾名思义即为数据绑定,是 MVVM 模式在 Android 上的一种实现,用于降低布局和逻辑的耦合性,使代码逻辑更加清晰
接下来进入正题
首先要启用databinding:
启用 DataBinding 的方法是在对应 Model 的 build.gradle 文件里加入以下代码,同步后就能引入对 DataBinding 的支持
android {
dataBinding {
enabled = true
}
}
之后在xml文件中鼠标移动到layout那行,出现黄色小灯泡提示框,点击并在下拉列表中点击第一个选项,将布局文件转换为databinding layout。
总体界面设计:
全局采用LinearLayout,内部三个TextView作为标签,三个EditText作为输入框,一个Button作为添加按钮,按钮下方三个TextView成一排作为列表标签,之后放入一个ListView存放列表数据
main.xml文件中用@={}的方式双向绑定EditText内容和数据,用@{()->}的方式绑定按钮动作函数
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="data"
type="com.example.experience_three.Student" />
data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="center_horizontal">
<TextView
android:layout_width="50sp"
android:layout_height="wrap_content"
android:text="班级:"
android:textSize="18sp"/>
<EditText
android:layout_width="200sp"
android:layout_height="wrap_content"
android:text="@={data.cls}"
android:id="@+id/et_class"
android:textSize="18sp"
/>
LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="center_horizontal">
<TextView
android:layout_width="50sp"
android:layout_height="wrap_content"
android:text="学号:"
android:textSize="18sp"/>
<EditText
android:layout_width="200sp"
android:layout_height="wrap_content"
android:text="@={data.NO}"
android:id="@+id/et_id"
android:textSize="18sp"/>
LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="center_horizontal">
<TextView
android:layout_width="50sp"
android:layout_height="wrap_content"
android:text="姓名:"
android:textSize="18sp"/>
<EditText
android:layout_width="200sp"
android:layout_height="wrap_content"
android:text="@={data.name}"
android:id="@+id/et_name"
android:textSize="18sp"/>
LinearLayout>
<Button
android:id="@+id/add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="添加"
android:onClick="@{()->data.setLs()}"
android:layout_gravity="center_horizontal" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="center_horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="班级"
android:layout_weight="1"
android:textSize="18sp"
android:textAlignment="center"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="学号"
android:layout_weight="1"
android:textSize="18sp"
android:textAlignment="center"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="姓名"
android:layout_weight="1"
android:textSize="18sp"
android:textAlignment="center"/>
LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_gravity="center_horizontal">
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/lv"
android:textAlignment="center" />
LinearLayout>
LinearLayout>
layout>
在res的menu文件夹下新建一个Delete.xml,存放弹出的删除按钮样式
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<item android:title="删除"
android:id="@+id/delete"/>
menu>
功能实现
设置了MainActivity和Student两个类
MainActivity主要用来初始化界面和设置按钮的响应函数
package com.example.experience_three;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.PopupMenu;
import androidx.databinding.DataBindingUtil;
import com.example.experience_three.databinding.MainBinding;
public class MainActivity extends AppCompatActivity {
private Student student;
private MainBinding binding;
public ArrayAdapter<String> adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this,R.layout.main);//绑定布局文件
student = new Student();//新建Student对象
binding.setData(student);//设置数据
binding.setLifecycleOwner(this);//绑定生命周期
adapter=new ArrayAdapter<>(this,android.R.layout.simple_expandable_list_item_1,student.getLs());//新建适配器
binding.lv.setAdapter(adapter);//添加适配器
binding.lv.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(final AdapterView<?> adapterView, View view, final int i, long l) {//为item添加点击事件监听器
PopupMenu menu = new PopupMenu(MainActivity.this,view);
MenuInflater inflater = menu.getMenuInflater();
inflater.inflate(R.menu.delete,menu.getMenu());
menu.show();
menu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem menuItem) {//长按menu删除
adapter.remove(adapter.getItem(i));
return false;
}
});
return false;
}
});
}
}
Student类继承BaseObserable类,主要负责存储数据和动作函数
package com.example.experience_three;
import androidx.databinding.BaseObservable;
import androidx.databinding.Bindable;
import java.util.ArrayList;
public class Student extends BaseObservable {
public String name,NO,cls;
public ArrayList<String> ls = new ArrayList<>();
public void setLs() {
if(name!=null&&NO!=null&&cls!=null&&!name.equals("")&&!NO.equals("")&&!cls.equals(""))
ls.add(cls+" "+NO+" "+name);
}
}
可以看出,Student类中的变量都被main.xml用@的方式双向绑定,并且在这些数据在任何一方面更新时会自动反映到另一方上,而不用在mainactivity中专门加监听数据更改的事件,这就是mvvm和mvc的区别之处,这样大大减少了mainActivity中的代码冗余,有效降低了代码的耦合度。