您当前的位置:首页 > 电脑百科 > 程序开发 > 移动端 > Android

Android MVVM架构

时间:2023-03-01 13:22:20  来源:智云站长  作者:

1.MVC,MVP,MVVVM

1.1什么是MVVM

1.MVVM,是Model-View-ViewModel的简写,是M-V-VM三部分组成。它本质上就是MVC 的改进 版。MVVM 就是将其中的View 的状态和行为抽象化,其中ViewModel将视图 UI 和业务逻辑分 开,它可以取出 Model 的数据同时帮忙处理 View 中由于需要展示内容而涉及的业务逻辑。

2.MVVM采用双向数据绑定,view中数据变化将自动反映到viewmodel上,反之,model中数据变化 也将会自动展示在页面上。把Model和View关联起来的就是ViewModel。ViewModel负责把Model 的数据同步到View显示出来,还负责把View的修改同步回Model。

3.MVVM核心思想,是关注model的变化,让MVVM框架利用自己的机制自动更新DOM,也就是所 谓的数据-视图分离,数据不会影响视图。

如图(重点):

 

 1.2 Android MVVM

MVVM分为Model,View,ViewModel 三个部分

Model:数据层,包含数据实体和对数据实体的操作,和MVP的model没有区别。

View: 界面层,对应于Activity,XML,负责数据显示以及用户交互。相比MVP的view,这里面的 view视图数据一般是在xml中使用DataBinding进来双向绑定数据的。    

ViewModel:关联层,作为中间桥梁 去通知model数据层处理数据业务,并将结果回调给 UI 层处 理 UI 逻辑。ViewModel中只有activity持有vm引用,vm是不持有view的引用的,所以vm的构造方 法中不能传入视图相关的对象。所以重点在于怎么通知view,可以通过观察者回调的方式。但是现 在一般是结合Jetpack来进行view的更新的。

2.MVVM项目框架

如图:

 3 MVVM核心构成

3.1 DataBinding (重点)(详细讲解)

数据和UI双向绑定

3.2 LifeCycle

界面生命周期感知

3.3 ViewModel

业务逻辑

3.4 LiveData

可观察数据项

3.5 MVVM项目框架搭建 通用性的快速开发框架 可应用各项目中

4 DataBinding

4.1 DataBinding的简介

1.Data binding 在2015年7月发布的android Studio v1.3.0 版本上引入,在2016年4月Android Studio v2.0.0 上正式支持。目前为止,Data Binding 已经支持双向绑定了,实在2016年的google I/O大会上发布的。现在已经很普及啦,在项目中也在慢慢使用。

 2.I/O大会上发布的。现在已经很普及啦,在项目中也在慢慢使用。 Databinding 是一个实现数据和UI绑定的框架,是一个实现 MVVM 模式的工具,有了 Data Binding,在Android中也可以很方便的实现MVVM开发模式。会JAVA web开发的会更好的理解在 xml中绑定数据的模式,在web开发中也是使用@{}来实现数据的显示的。

3.Data Binding 是一个support库,最低支持到Android 2.1(API Level 7+)。使用 DataBing,Gradle的Android Plugin需要在1.5.0-alpha1以上。

4.Data Binding 之前我们不可避免地要编写大量的毫无营养的代码,如 findViewById()、 setText(),setVisibility(),setEnabled() 或 setOnClickListener() 等,通过 Data Binding , 我们可 以通过声明式布局以精简的代码来绑定应用程序逻辑和布局,这样就不用编写大量的毫无营养的代 码了。

缺点:

1. ViewModel与View一一对应;

2. 使用起来灵活性比较低;

3. Model属性发生变化时,ViewDatabinding采用异步更新数据,对于现实大量数据的ListView,会 有一定延迟,在实践测试中发现,Databing效率较低,对于负责的界面不太适用;

4. 自动生成大量代码和属性字段:ViewDataBinding 实现类 DataBinderMApper 等。

4.2使用DataBinding

具体步骤:

1.构建环境(Build Environment)

在build.gradle中添加如下代码:

 

Java
dataBinding {
        enabled = true
    }

2. 数据绑定布局文件

数据绑定的布局文件和我们以前经常写的布局文件稍有不同,并从布局的根标记开始,后面依次是数据 元素和视图根元素,即根布局是 layout,接下来是 data 节点,variable 节点,示例如下:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="user"
            type="com.hp.mvvmdemo.model.User" />
        <variable
            name="handler"
            type="com.hp.mvvmdemo.view.activity.MAInActivity.Handler" />
    </data>

    <LinearLayout
        android:gravity="center"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            android:id="@+id/tv_show"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World!" />

        <TextView
            android:layout_marginTop="30dp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="20dp"
            android:text="@{user.username}" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="20dp"
            android:text="@{user.password}" />

        <Button
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:onClick="@{()->handler.onClick()}"/>

    </LinearLayout>


</layout>

3.在MainActivity.java中获取bingding对象

Java
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.activity_main);
        ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
       

    }

4.4databinding点击事件

xml:

 

 activity:

 5.单向绑定

5.1单个值的绑定:

1.集成DataDinding 添加 dataBinding.enabled true 和 dataBinding { enabled = true }

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

2.实现xml:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
    <variable
        name="title"
        type="java.lang.String" />
</data>
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <TextView
        android:textColor="#000000"
        android:id="@+id/tvTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@{title}"/>
</LinearLayout>
</layout>

5.2对象的绑定:

1.xml:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
    <variable name="user" type="com.example.User"/>
</data>
<LinearLayout
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@{user.firstName}"/>
    <TextView android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@{user.lastName}"/>
</LinearLayout>
</layout>

2.实体类:

Java
public class User {
    private final String firstName;
    private final String lastName;
    public User(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
    public String getFirstName() {
        return this.firstName;
    }
    public String getLastName() {
        return this.lastName;
    }
}

3.databinding:

Java
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        MainActivityBinding binding = DataBindingUtil.setContentView(this,
                R.layout.main_activity);
        User user = new User("Test", "User");
        binding.setUser(user);
    }

6.双向绑定

双向绑定是指其中任意一个变化后都会同步更新到另一个。双向绑定使用@={}表达式来实现 4.5.1 目前已经支持双向绑定的列表

 7.从网页获取图片

整体架构

 

导入要使用的依赖:

build.gradle        

Java
implementation 'com.squareup.picasso:picasso:2.71828'
    //for rxjava
    implementation 'io.reactivex.rxjava2:rxjava:2.2.6'
    //for rxandroid
    implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
    //衔接 Retrofit & RxJava,此处一定要注意使用RxJava2的版本
    implementation 'com.squareup.retrofit2:adapter-rxjava2:2.5.0'
    //添加Retrofit依赖
    implementation 'com.squareup.retrofit2:retrofit:2.5.0'
    //添加Gson解析
    implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
    //添加图片加载库依赖
    implementation 'com.Github.bumptech.glide:glide:4.12.0'

xml层:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="imgurl"
            type="String" />
        <variable
            name="localurl"
            type="int" />
        <variable
            name="mainviewmodel"
            type="com.hp.day48stage01.viewmodel.MainViewModel" />
    </data>
    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".view.activity.MainActivity">

        <ImageView
            app.NETImage="@{imgurl}"
            app:localImage="@{localurl}"
            android:id="@+id/imageView"
            android:layout_width="300dp"
            android:layout_height="300dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:srcCompat="@drawable/ic_launcher_background" />

        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="64dp"
            android:text="点击见美女"
            android:onClick="@{()->mainviewmodel.onChange()}"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="@+id/imageView"
            app:layout_constraintHorizontal_bias="0.495"
            app:layout_constraintStart_toStartOf="@+id/imageView"
            app:layout_constraintTop_toBottomOf="@+id/imageView"
            app:layout_constraintVertical_bias="0.029" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

编写实体类:

ModelGril.java

Java
public class ModelGirl {
    private boolean success;
    private String imgurl;
    private Info info;

    @Override
    public String toString() {
        return "MobileGirl{" +
                "success=" + success +
                ", imgurl='" + imgurl + ''' +
                ", info=" + info +
                '}';
    }

    public boolean isSuccess() {
        return success;
    }

    public void setSuccess(boolean success) {
        this.success = success;
    }

    public String getImgurl() {
        return imgurl;
    }

    public void setImgurl(String imgurl) {
        this.imgurl = imgurl;
    }

    public Info getInfo() {
        return info;
    }

    public void setInfo(Info info) {
        this.info = info;
    }

    public static class Info{
        private int width;
        private int height;
        private String type;

        public int getWidth() {
            return width;
        }

        public void setWidth(int width) {
            this.width = width;
        }

        public int getHeight() {
            return height;
        }

        public void setHeight(int height) {
            this.height = height;
        }

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }
    }

}

编写网络接口:

Java
public interface GetImage_Interface {
    @GET("api/mobil.girl?type=json")
    Observable<ModelGirl> getPic();
}

适配器:

Java
public class ImageBindingAdapter {



    @BindingAdapter(value = {"netImage","localImage"},requireAll = false)
    public static void setImage(ImageView imageView,String url,int path){

        if (url != null && !"".equals(imageView)) {
            /*Glide.with(imageView.getContext())
                    .load(url)
                    .override(300,300)
                    .centerCrop()
                    .into(imageView);*/
            Picasso.get().load(url).placeholder(R.mipmap.jiazai).into(imageView);
        }else {
            imageView.setImageResource(path);
        }
    }

}
MainViewModel
Java
public class MainViewModel {
    private String imgurl;

    private ModelGirl modelGirl;

    private ActivityMainBinding binding;

    private final String TAG = "MainViewModel";

    public ModelGirl getModelGirl() {
        return modelGirl;
    }

    public void setModelGirl(ModelGirl modelGirl) {
        this.modelGirl = modelGirl;
    }

    public MainViewModel() {

    }

    public MainViewModel(ActivityMainBinding binding,String imgurl) {
        this.binding = binding;
        this.imgurl = imgurl;
        initGirl();
    }

    private void initGirl() {

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("https://api.vvhan.com/")
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();

        GetImage_Interface request = retrofit.create(GetImage_Interface.class);

        Observable<ModelGirl> observable = request.getPic();

        observable.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<ModelGirl>() {
                    @Override
                    public void accept(ModelGirl modelGirl) throws Exception {
                        Log.i(TAG,"连接成功");
                        //Log.i(TAG, modelGirl.toString());
                        imgurl = modelGirl.getImgurl();
                        binding.setImgurl(imgurl);
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {
                        Log.i(TAG,"连接失败");
                    }
                });
    }
    public void onChange(){
        initGirl();
    }
}
MainActivity:
Java
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        ActivityMainBinding binding = DataBindingUtil.setContentView(this,R.layout.activity_main);

        binding.setMainviewmodel(new MainViewModel(binding,""));

    }
}

 



Tags:Android   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
Android Emulator黑屏怎么办 Android模拟器黑屏解决方法
Android Emulator黑屏问题困扰了非常多的玩家,Android Emulator作为一款安卓模拟器,可以让你在电脑上运行和浏览安卓应用程序,但是程序本身不是很稳定,很容易会出现黑屏,启动不了...【详细内容】
2024-03-04  Search: Android  点击:(37)  评论:(0)  加入收藏
Android 谷歌三件套:解锁谷歌生态!
大家是不是遇到这个情况?当我们需要下载一些国外的游戏或者软件的时候,需要在手机里面安装Google Play商店,然后通过Google Play商店下载国外软件!为了帮助大家使用上各种好用的...【详细内容】
2024-01-02  Search: Android  点击:(113)  评论:(0)  加入收藏
Android开发中常见的Hook技术有哪些?
Hook技术介绍Hook技术是一种在软件开发中常见的技术,它允许开发者在特定的事件发生时插入自定义的代码逻辑。常见的应用场景包括在函数调用前后执行特定的操作,或者在特定的事...【详细内容】
2023-12-25  Search: Android  点击:(85)  评论:(0)  加入收藏
在Android应用开发中使用NFC功能
NFC介绍NFC是指“近场通讯”(Near Field Communication),它是一种短距离无线通信技术,允许设备在非接触或极短距离内进行通信。NFC通常用于移动支付、门禁系统、智能标签和其他...【详细内容】
2023-12-22  Search: Android  点击:(102)  评论:(0)  加入收藏
关于Android图像Bitmap类,你要知道的一切
Bitmap介绍Bitmap是一种图像文件格式,它由像素阵列组成,每个像素都有自己的颜色信息。在计算机图形学中,Bitmap图像可以被描述为一个二维的矩阵,其中每个元素代表一个像素的颜色...【详细内容】
2023-12-19  Search: Android  点击:(99)  评论:(0)  加入收藏
Android开发中如何进行单元测试?
单元测试介绍单元测试是软件开发中的一种测试方法,用于验证代码中的最小可测试单元(通常是函数或方法)是否按预期工作。单元测试通常由开发人员编写,旨在隔离和测试代码的特定部...【详细内容】
2023-12-11  Search: Android  点击:(167)  评论:(0)  加入收藏
我的手机我做主,如何为Android手机应用换图标?
作为一名Android用户,你是否曾经为自己的手机桌面感到单调而乏味?虽然Android系统的桌面定制性已经非常强大,但有时候我们还是希望能够在细节上做出一些改变,尤其是对于那些每天...【详细内容】
2023-12-10  Search: Android  点击:(61)  评论:(0)  加入收藏
了解Android系统架构中的HAL硬件抽象层
在Android系统中,HAL的存在使得不同厂商的硬件可以统一被上层的应用程序调用,从而提高了系统的兼容性和可移植性。HAL还可以帮助开发者更方便地开发应用程序,因为他们不需要为...【详细内容】
2023-12-06  Search: Android  点击:(203)  评论:(0)  加入收藏
谷歌 CEO 皮查伊建议 Android 用户不要侧载应用,称非常危险
iOS和Android的一个显著差异是,Android支持用户从第三方渠道安装应用程序(即“侧载”)。然而,谷歌似乎并不希望用户这样做。最近,在与Epic Store的法律诉讼中,谷歌首席执行官桑达...【详细内容】
2023-11-20  Search: Android  点击:(167)  评论:(0)  加入收藏
Android数据对象序列化原理与应用
序列化与反序列化「序列化」是将对象转换为可以存储或传输的格式的过程。在计算机科学中,对象通常是指内存中的数据结构,如数组、列表、字典等。通过序列化,可以将这些对象转换...【详细内容】
2023-11-14  Search: Android  点击:(273)  评论:(0)  加入收藏
▌简易百科推荐
Android Emulator黑屏怎么办 Android模拟器黑屏解决方法
Android Emulator黑屏问题困扰了非常多的玩家,Android Emulator作为一款安卓模拟器,可以让你在电脑上运行和浏览安卓应用程序,但是程序本身不是很稳定,很容易会出现黑屏,启动不了...【详细内容】
2024-03-04  18183游戏网    Tags:Android Emulator   点击:(37)  评论:(0)  加入收藏
Android开发中常见的Hook技术有哪些?
Hook技术介绍Hook技术是一种在软件开发中常见的技术,它允许开发者在特定的事件发生时插入自定义的代码逻辑。常见的应用场景包括在函数调用前后执行特定的操作,或者在特定的事...【详细内容】
2023-12-25  沐雨花飞蝶  微信公众号  Tags:Android   点击:(85)  评论:(0)  加入收藏
在Android应用开发中使用NFC功能
NFC介绍NFC是指“近场通讯”(Near Field Communication),它是一种短距离无线通信技术,允许设备在非接触或极短距离内进行通信。NFC通常用于移动支付、门禁系统、智能标签和其他...【详细内容】
2023-12-22  沐雨花飞蝶  微信公众号  Tags:Android   点击:(102)  评论:(0)  加入收藏
关于Android图像Bitmap类,你要知道的一切
Bitmap介绍Bitmap是一种图像文件格式,它由像素阵列组成,每个像素都有自己的颜色信息。在计算机图形学中,Bitmap图像可以被描述为一个二维的矩阵,其中每个元素代表一个像素的颜色...【详细内容】
2023-12-19  沐雨花飞蝶  微信公众号  Tags:Android   点击:(99)  评论:(0)  加入收藏
Android开发中如何进行单元测试?
单元测试介绍单元测试是软件开发中的一种测试方法,用于验证代码中的最小可测试单元(通常是函数或方法)是否按预期工作。单元测试通常由开发人员编写,旨在隔离和测试代码的特定部...【详细内容】
2023-12-11  沐雨花飞蝶  微信公众号  Tags:Android   点击:(167)  评论:(0)  加入收藏
一篇聊聊Jetpack Room实现数据存储持久性
Room介绍Room 是 Android Jetpack 组件库中的一部分,它是用于在 Android 应用中进行本地数据库访问和管理的库。Room 提供了一个抽象层,使开发者能够更轻松地访问 SQLite 数据...【详细内容】
2023-12-08  沐雨花飞蝶  微信公众号  Tags:Jetpack   点击:(143)  评论:(0)  加入收藏
了解Android系统架构中的HAL硬件抽象层
在Android系统中,HAL的存在使得不同厂商的硬件可以统一被上层的应用程序调用,从而提高了系统的兼容性和可移植性。HAL还可以帮助开发者更方便地开发应用程序,因为他们不需要为...【详细内容】
2023-12-06  沐雨花飞蝶  微信公众号  Tags:Android   点击:(203)  评论:(0)  加入收藏
我们一起聊聊 IntentService 与 Service 的区别?
Service介绍Service组件是Android应用开发中的四大组件之一,用于在后台执行长时间运行的操作或处理远程请求。它可以在没有用户界面的情况下执行任务,并且可以与其他应用组件...【详细内容】
2023-12-06  沐雨花飞蝶  微信公众号  Tags:IntentService   点击:(170)  评论:(0)  加入收藏
Android数据对象序列化原理与应用
序列化与反序列化「序列化」是将对象转换为可以存储或传输的格式的过程。在计算机科学中,对象通常是指内存中的数据结构,如数组、列表、字典等。通过序列化,可以将这些对象转换...【详细内容】
2023-11-14  沐雨花飞蝶  微信公众号  Tags:Android   点击:(273)  评论:(0)  加入收藏
你了解Android中的SELinux吗?
SELinux介绍SELinux(Security-Enhanced Linux)是一种安全增强的Linux操作系统,它通过强制访问控制(MAC)机制来提供更高级别的系统安全保护。相比于传统的Linux访问控制机制(DAC),SEL...【详细内容】
2023-11-09  沐雨花飞蝶  微信公众号  Tags:Android   点击:(264)  评论:(0)  加入收藏
站内最新
站内热门
站内头条