Android架构组件:MVVM模式的实战应用与数据绑定技巧

MVVM框架 在WPF开发中,经典的编程模式是MVVM,是为WPF量身定做的模式,该模式充分利用了WPF的数据绑定机制,最大限度地降低了Xmal文件和CS文件的耦合度,也就是UI显示和逻辑代码的耦合度,如需要更换界面时,逻辑代码修改很少,甚至不用修改。 与WinForm开发相比,我们一般在后置代码中会使用控件的名字来操作控件的属性来更新UI,而在WPF中通常是通过数据绑定来更新UI;在响应用户操作上,WinForm是通过控件的事件来处理,而WPF可以使用命令绑定的方式来处理,耦合度将降低。 一、MVVM框架简介 1. 什 阅读详情

Android架构组件:MVVM模式的实战应用与数据绑定技巧

目录

Android架构组件:MVVM模式的实战应用与数据绑定技巧

引言

1. MVVM模式概述

1.1 MVVM的定义

1.2 MVVM的优点

2. Android架构组件与MVVM

2.1 ViewModel

2.2 LiveData

2.3 DataBinding

3. 实战应用示例:Todo List 应用

3.1 项目概述

3.2 创建项目

4. 数据绑定技巧

4.1 使用 BindingAdapter

4.2 双向绑定

4.3 使用 LiveData 进行 UI 更新

5. 最佳实践与优化

5.1 避免 ViewModel 过度膨胀

5.2 使用 Repository 模式

5.3 处理配置更改

5.4 结合其他架构组件

6. 总结



引言

在现代 Android 开发中,架构组件的使用已成为构建高质量、可维护应用的标准。MVVM(Model-View-ViewModel)模式因其良好的分离关注点和简洁的数据绑定特性,被广泛应用于 Android 开发中。本博客将深入探讨 MVVM 模式的实战应用与数据绑定技巧,包括其基本概念、实际应用示例、最佳实践以及如何利用 Android 架构组件提高开发效率。

1. MVVM模式概述

1.1 MVVM的定义

MVVM(Model-View-ViewModel)是一种设计模式,旨在将应用程序的 UI(View)与业务逻辑和数据(Model)进行分离。MVVM 模式由以下三部分组成:

  • Model:代表应用的数据模型和业务逻辑。Model 负责数据的获取、处理和存储。
  • View:负责显示数据并处理用户交互。View 通常是 Activity 或 Fragment。
  • ViewModel:充当 Model 和 View 之间的中介。ViewModel 处理 UI 逻辑、数据转换,并通过数据绑定将数据传递给 View。

1.2 MVVM的优点

  • 分离关注点:将 UI 逻辑与业务逻辑分离,提高了代码的可维护性和测试性。
  • 数据绑定:通过数据绑定库,ViewModel 可以直接与 View 进行数据绑定,减少了手动更新 UI 的需求。
  • 提高测试性:将业务逻辑与 UI 逻辑分离,使得 ViewModel 更容易进行单元测试。

2. Android架构组件与MVVM

Android 提供了一些架构组件(如 LiveData、ViewModel 和 DataBinding)来支持 MVVM 模式的实现。这些组件使得开发者能够更高效地实现 MVVM 模式。

2.1 ViewModel

ViewModel 组件用于存储和管理与 UI 相关的数据,并处理与 UI 相关的逻辑。ViewModel 的生命周期与 UI 控件的生命周期无关,这使得它能够在配置更改(如屏幕旋转)时保持数据。

ViewModel 的使用示例:

 

java

public class UserViewModel extends ViewModel {
    private MutableLiveData<User> user;

    public LiveData<User> getUser() {
        if (user == null) {
            user = new MutableLiveData<>();
            loadUser();
        }
        return user;
    }

    private void loadUser() {
        // Load user data from repository
        // user.setValue(loadedUser);
    }
}

java

在 Activity 或 Fragment 中使用 ViewModel:

 

java

public class UserActivity extends AppCompatActivity {
    private UserViewModel userViewModel;

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

        userViewModel = new ViewModelProvider(this).get(UserViewModel.class);
        userViewModel.getUser().observe(this, user -> {
            // Update UI with user data
        });
    }
}

java

2.2 LiveData

LiveData 是一种可观察的数据容器,它能够在数据发生变化时自动通知观察者。LiveData 的主要特点是生命周期感知,这意味着它会在生命周期结束时自动停止发送更新,从而避免了内存泄漏和崩溃。

LiveData 的使用示例:

 

java

public class UserRepository {
    private MutableLiveData<User> userLiveData = new MutableLiveData<>();

    public LiveData<User> getUser() {
        return userLiveData;
    }

    public void fetchUser() {
        // Fetch user data and post value
        // userLiveData.postValue(fetchedUser);
    }
}

java

在 ViewModel 中使用 LiveData:

 

java

public class UserViewModel extends ViewModel {
    private UserRepository userRepository;
    private LiveData<User> user;

    public UserViewModel() {
        userRepository = new UserRepository();
        user = userRepository.getUser();
        userRepository.fetchUser();
    }

    public LiveData<User> getUser() {
        return user;
    }
}

java

2.3 DataBinding

DataBinding 是一种用于简化 UI 绑定和数据交换的库。它允许你在 XML 布局文件中直接绑定数据,减少了在代码中手动更新 UI 的需要。

启用 DataBinding: 在 build.gradle 文件中启用 DataBinding:

 

groovy

android {
    ...
    dataBinding {
        enabled = true
    }
}

创建 DataBinding 布局文件:

 

xml

<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="userViewModel"
            type="com.example.UserViewModel" />
    </data>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/userName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{userViewModel.user.name}" />

    </RelativeLayout>
</layout>

xml

在 Activity 或 Fragment 中绑定数据:

 

java

public class UserActivity extends AppCompatActivity {
    private UserViewModel userViewModel;
    private ActivityUserBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_user);
        userViewModel = new ViewModelProvider(this).get(UserViewModel.class);
        binding.setUserViewModel(userViewModel);
        binding.setLifecycleOwner(this);
    }
}

java

3. 实战应用示例:Todo List 应用

3.1 项目概述

本示例展示了如何使用 MVVM 模式和 Android 架构组件实现一个简单的 Todo List 应用。该应用允许用户添加、删除和查看待办事项。

3.2 创建项目

1. 创建模型类:

 

java

public class Todo {
    private String title;
    private boolean isCompleted;

    // Constructor, getters, and setters
}

2. 创建 ViewModel:

 

java

public class TodoViewModel extends ViewModel {
    private MutableLiveData<List<Todo>> todos;

    public TodoViewModel() {
        todos = new MutableLiveData<>(new ArrayList<>());
    }

    public LiveData<List<Todo>> getTodos() {
        return todos;
    }

    public void addTodo(String title) {
        List<Todo> currentTodos = todos.getValue();
        currentTodos.add(new Todo(title, false));
        todos.setValue(currentTodos);
    }

    public void removeTodo(int position) {
        List<Todo> currentTodos = todos.getValue();
        if (position >= 0 && position < currentTodos.size()) {
            currentTodos.remove(position);
            todos.setValue(currentTodos);
        }
    }
}

java

3. 创建布局文件(activity_main.xml):

 

xml

<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="todoViewModel"
            type="com.example.TodoViewModel" />
    </data>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <EditText
            android:id="@+id/todoInput"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="Enter a todo" />

        <Button
            android:id="@+id/addButton"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Add Todo" />

        <ListView
            android:id="@+id/todoList"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@id/addButton" />

    </RelativeLayout>
</layout>

xml

4. 创建适配器:

 

java

public class TodoAdapter extends ArrayAdapter<Todo> {
    public TodoAdapter(Context context, List<Todo> todos) {
        super(context, 0, todos);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            convertView = LayoutInflater.from(getContext()).inflate(R.layout.item_todo, parent, false);
        }

        Todo todo = getItem(position);
        TextView titleTextView = convertView.findViewById(R.id.todoTitle);
        CheckBox completedCheckBox = convertView.findViewById(R.id.todoCompleted);

        titleTextView.setText(todo.getTitle());
        completedCheckBox.setChecked(todo.isCompleted());

        return convertView;
    }
}

java

5. 创建 Activity:

 

java

        todoViewModel = new ViewModelProvider(this).get(TodoViewModel.class);
        binding.setTodoViewModel(todoViewModel);
        binding.setLifecycleOwner(this);

        // Initialize ListView and Adapter
        ListView todoListView = findViewById(R.id.todoList);
        todoAdapter = new TodoAdapter(this, new ArrayList<>());
        todoListView.setAdapter(todoAdapter);

        // Observe changes to the todos LiveData
        todoViewModel.getTodos().observe(this, todos -> {
            todoAdapter.clear();
            todoAdapter.addAll(todos);
            todoAdapter.notifyDataSetChanged();
        });

        // Handle add button click
        binding.addButton.setOnClickListener(v -> {
            String todoTitle = binding.todoInput.getText().toString();
            if (!todoTitle.isEmpty()) {
                todoViewModel.addTodo(todoTitle);
                binding.todoInput.setText("");
            }
        });

        // Handle item click (for example, to remove an item)
        todoListView.setOnItemClickListener((parent, view, position, id) -> {
            todoViewModel.removeTodo(position);
        });
    }
}

java

6. 创建布局文件(item_todo.xml):

 

xml

<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="todo"
            type="com.example.Todo" />
    </data>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="16dp">

        <TextView
            android:id="@+id/todoTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{todo.title}" />

        <CheckBox
            android:id="@+id/todoCompleted"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentEnd="true"
            android:checked="@{todo.completed}" />
    </RelativeLayout>
</layout>

xml

4. 数据绑定技巧

数据绑定是 MVVM 模式中的一个重要组成部分,它可以减少模板代码并简化 UI 的更新过程。以下是一些数据绑定的技巧和最佳实践:

4.1 使用 BindingAdapter

BindingAdapter 允许你创建自定义的数据绑定属性和方法,以简化 UI 的更新。例如,假设你有一个自定义的视图组件,需要根据某些条件设置样式或属性,可以使用 BindingAdapter 来处理:

 

java

public class BindingAdapters {
    @BindingAdapter("app:completed")
    public static void setCompleted(CheckBox checkBox, boolean completed) {
        checkBox.setChecked(completed);
    }
}

在布局文件中使用自定义属性:

 

xml

<CheckBox
    android:id="@+id/todoCompleted"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:completed="@{todo.completed}" />
4.2 双向绑定

双向绑定允许 ViewModel 和 View 之间的数据同步。当 View 中的数据发生变化时,ViewModel 也会自动更新。例如,你可以实现双向绑定来同步 EditText 和 ViewModel 的数据:

ViewModel 中的数据:

 

java

public class UserViewModel extends ViewModel {
    public final ObservableField<String> userName = new ObservableField<>();
}

布局文件中的双向绑定:

 

xml

<EditText
    android:id="@+id/userNameInput"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@={userViewModel.userName}" />
4.3 使用 LiveData 进行 UI 更新

使用 LiveData 进行 UI 更新时,可以避免直接操作 UI 线程,从而减少潜在的线程问题。确保你的 ViewModel 中的 LiveData 对象在数据变化时能够通知观察者:

 

java

public class UserViewModel extends ViewModel {
    private MutableLiveData<User> user = new MutableLiveData<>();

    public LiveData<User> getUser() {
        return user;
    }

    public void updateUser(User newUser) {
        user.setValue(newUser);
    }
}

java

在布局文件中观察 LiveData:

 

xml

<TextView
    android:id="@+id/userName"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@{userViewModel.user.name}" />

5. 最佳实践与优化

5.1 避免 ViewModel 过度膨胀

ViewModel 主要用于处理 UI 逻辑和数据,因此它应该保持精简。如果 ViewModel 变得过于复杂,可以考虑将逻辑分离到不同的 ViewModel 或使用其他架构组件(如 UseCase 或 Repository)来处理复杂的业务逻辑。

5.2 使用 Repository 模式

Repository 模式是一种常用的架构模式,用于将数据访问逻辑从 ViewModel 中分离出去。Repository 负责从多个数据源(如网络、数据库)获取数据,并将数据提供给 ViewModel。

创建 Repository:

 

java

public class UserRepository {
    private UserDao userDao;
    private ApiService apiService;

    public UserRepository(UserDao userDao, ApiService apiService) {
        this.userDao = userDao;
        this.apiService = apiService;
    }

    public LiveData<User> getUser(int userId) {
        // Fetch user from local database or remote API
    }
}

java

在 ViewModel 中使用 Repository:

 

java

public class UserViewModel extends ViewModel {
    private UserRepository userRepository;
    private LiveData<User> user;

    public UserViewModel(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public LiveData<User> getUser(int userId) {
        return userRepository.getUser(userId);
    }
}

java

5.3 处理配置更改

ViewModel 在配置更改(如屏幕旋转)时保持数据,因此可以避免重复加载数据。然而,对于复杂的场景(如大数据集),需要使用 SavedStateHandle 来保存状态,以确保在配置更改后数据不会丢失。

使用 SavedStateHandle:

 

java

public class UserViewModel extends ViewModel {
    private SavedStateHandle stateHandle;

    public UserViewModel(SavedStateHandle stateHandle) {
        this.stateHandle = stateHandle;
    }

    public LiveData<User> getUser() {
        return stateHandle.getLiveData("user");
    }

    public void setUser(User user) {
        stateHandle.set("user", user);
    }
}

java

5.4 结合其他架构组件

MVVM 模式与其他 Android 架构组件(如 Room、Retrofit)结合使用,可以构建更强大和灵活的应用。例如,使用 Room 进行本地数据库操作,使用 Retrofit 进行网络请求,并通过 ViewModel 和 LiveData 管理数据。

使用 Room 进行数据库操作:

 

java

@Dao
public interface UserDao {
    @Query("SELECT * FROM user WHERE id = :userId")
    LiveData<User> getUser(int userId);
}

使用 Retrofit 进行网络请求:

 

java

public interface ApiService {
    @GET("users/{id}")
    Call<User> getUser(@Path("id") int userId);
}

6. 总结

MVVM 模式结合 Android 架构组件(如 ViewModel、LiveData 和 DataBinding)提供了一种高效的方式来组织和管理 Android 应用的代码。通过分离 UI 逻辑和业务逻辑、利用数据绑定减少模板代码、以及使用 LiveData 实现数据观察和更新,开发者能够构建可维护、高性能的应用。

在实际应用中,使用 MVVM 模式和 Android 架构组件能够显著提高开发效率,降低代码复杂度,并增强应用的测试性。随着 Android 生态系统的不断演进,掌握这些技术和最佳实践将有助于开发者在现代软件开发中保持竞争力。

Android应用架构-MVVM模式 随着Android应用开发技术的不断发展和成熟,很开发者越来越关注着Android应用架构的设计。目前,Android的应用架构主要有MVC、MVP和MVVM模式,我们就来说一下MVVM模式。MVVM模式有三层:Model层主要负责数据的提供,View层主要负责界面的显示,ViewModel层主要负责业务逻辑的处理。各个层职责单一不同,但他们都结构清晰,应用起来十分的便捷更多Android进阶指南 可以扫码 解锁《Android十大板块文档》1.Android车载应用开发系统学习指南(附项目实战) 阅读详情

相关推荐

安卓(Android)平台上的MVVM架构:关键知识点、优劣分析及实践示例

本文旨在探讨安卓平台上广泛应用的Model-View-ViewModel(MVVM)架构模式的核心概念、主要优点与潜在不足,并通过实际示例代码阐明其在实际项目中的应用方式。MVVM作为一款推动关注点分离和提高软件质量的架构方案,在安卓应用开发中起着至关重要的作用。

wlred1980的博客 1832

Android mvvm使用流程

ViewModelProvider初始化时如果不传递 ViewModelProvider.Factory,则ViewModelProvider内部会使用默认的 Factory,getTestLiveData 返回LiveData提供 数据给ViewModel,ViewModel 及view层获取到LiveData即监听数据的变化。ViewModel 类提供了一种保存和管理界面相关数据的机制,并确保这些数据在配置更改(如设备旋转)时不会丢失或重新创建。3.创建view类UiTestActivity。

kk3087961的博客 1076

Android架构组件: MVVM模式的实战应用与数据绑定技巧

Model(模型):负责数据处理和业务逻辑,与数据源(数据库、API等)交互。View(视图):UI层,展示数据并响应用户交互。ViewModel(视图模型):持有并处理View所需的数据,响应UI逻辑。**数据绑定(Data Binding)**技术允许开发者直接在布局文件中绑定ViewModel中的数据,减少繁琐的UI更新代码。MVVM模式和数据绑定极大提高了Android应用开发的效率和代码可维护性。通过解耦UI和业务逻辑,开发者可以轻松处理复杂的应用状态。

好看资源网的博客 1713

Android技术框架篇(三):MVVM框架

MVVM框架的介绍

看,好自为之的博客!!! 1万+

Android架构组件:MVVM模式的实战应用与数据绑定技巧

MVVM(Model-View-ViewModel)是一种软件架构模式,旨在将用户界面(UI)与业务逻辑分离。在Android开发中,MVVM模式通过使用数据绑定库,使得View和ViewModel之间的通信更加简洁和高效。Model: 数据模型,负责数据的存储和处理。View: 用户界面,通常是Activity或Fragment。ViewModel: 连接Model和View的桥梁,负责处理业务逻辑并提供数据给View。

AI逍遥子 1580

基于CRU和WorldClim的高分辨率(1km)气候数据生成

基于CRU和WorldClim的高分辨率(1km)气候数据生成

lhq7842955的博客 1692

Android MVVM详解

一、MVVM是什么? (1).Model:数据层,包含数据实体和对数据实体的操作 (2).View:界面层,对应于Activity,XML,View,负责数据显示以及用户交互。 (3).ViewModel:关联层,将Model和View进行绑定,Model或者View更改时,实时刷新对方。

Mubly的博客 9995

PSpice 导入 LTspice 仿真实验 --(如何解决PSpice模型无法使用的错误)

参考了网上第三方器件导入LTspice的博客和资料,不论是哪个公司下载的SPICE模型导入LTspice的方法都类似。如果遇到导入报错的情况可以先看一下报错提示,如果通过语法修改实现功能的则说明可以进行仿真,当然性能可能与官方给的模型存在一点出入,但做一个基本的功能验证本人认为还是可以的,总比做出板子用不了或者完全不匹配的要好一些。

伊丽莎白的学习之路 8998

Android架构组件:MVVM模式的实战应用与数据绑定技巧|Android架构|MVVM模式|数据绑定

在现代Android应用开发中,选择合适的架构模式至关重要。MVVM(Model-View-ViewModel)作为一种优秀的架构模式,以其高效的代码组织和解耦能力,成为了开发者的首选。通过将UI逻辑与业务逻辑分离,MVVM不仅提升了应用的可维护性和扩展性,还增强了开发效率。本文将详细探讨MVVM模式在Android架构中的实战应用,并结合数据绑定(Data Binding)技术,展示如何构建清晰、健壮且高效的Android应用。

2510

EWF写保护功能详解:从安装到实战操作指南

本文详细介绍了EWF写保护功能的安装与实战操作指南。EWF(Enhanced Write Filter)通过重定向写入操作保护硬盘分区,特别适合需要长期稳定运行的系统场景。文章涵盖从安装准备、图形界面操作到命令行高级管理的全流程,并提供了常见问题的解决方案,帮助用户轻松掌握这一实用工具。

weixin_28710999的博客 446

docker部署neo4j,设置密码。Neo.ClientError.Security.Unauthorized: The client is unauthorized due to authenti

卷,设置NEO4J_AUTH将不会起作用,因为该数据库已经配置了身份验证。Neo4j Docker 服务将会启动,但您需要使用已与该数据库关联的用户名和密码才能登录。这里,使用了环境变量NEO4J_AUTH,设置了用户名为neo4j,密码为neo4jneo4j。这个命令还是比较全的,包括设置密码,设置端口,挂载外部的数据目录等。原因嘛,就是使用docker创建的neo4j,登录不上。把👆提到的外挂的数据,都清空了,再重新来一遍。有一种情况下,这样设置密码,并不会成功。如果不出意外,目前就算大功告成了。

xiezhipu的博客 563
上一篇: 2024年学习编程语言的最佳选择
下一篇: 深度学习算法讲解与应用
HYP_Coder
博客等级 码龄2年 1685粉丝 103原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值