广告
返回顶部
首页 > 资讯 > 移动开发 >Android快速搭建MVVM框架
  • 146
分享到

Android快速搭建MVVM框架

mvvmAndroid 2022-06-06 13:06:28 146人浏览 薄情痞子
摘要

架构上面是从一个开源项目中了解到的框架结构,以最简洁的方式搭建一个app的基础框架。框架的几个特点是:通过Jetpack的Navigation构建单Activity多Fragment结构,我们知道Activity是属于比较重的组件,而Fra

架构

上面是从一个开源项目中了解到的框架结构,以最简洁的方式搭建一个app的基础框架。

框架的几个特点是:

通过Jetpack的Navigation构建单Activity多Fragment结构,我们知道Activity是属于比较重的组件,而Fragment是比较轻量化的,因此这种结构对界面性能方面有很大影响 通过koin这个依赖注入框架来管理ViewModel等实例的生命周期,早期的ssh框架也是因为spring这个依赖注入特性而更加出名 使用当前比较优秀的数据请求框架来负责各种类型数据的处理 麻雀虽小,五脏俱全,任何一个app都离不开这些基础的架构,而上面的框架搭建起来很简洁,后期维护也很清晰

 

具体剖析一、Navigation

简介:

Navigation是Jetpack四大组件中的其中一个,目前也比较稳定了

我们都知道fragment有非常多的优势,它本身是一个VIew派生而来的控件,嵌套灵活,渲染所消耗的资源明显小于activity,数据的传递也更加方便,当然它的优点并不止这些。

但是在应用开发的过程中,开发者们也发现了不少这种做法带来的坑。例如需要维护复杂的fragment回退栈、使用不当的情况下经常出现fragment重叠、经常由于activity已经销毁导致使用上下文crash、等等等等的问题。

navigation就是为了解决这些问题而出现的,用于实现单activity多fragment形式的官方解决方案

使用样例:

1)先配置跳转信息,在res/navigation目录下新建一个navigation.xml,配置如下内容:


上面fragment和activity标签就是代表需要跳转的具体类,action标签代表一个具体的跳转信息,argument代表的是跳转到这个类时可以传递的参数定义

2)界面跳转,比如上面的TabFragment跳转到BrowserActivity时可以这样操作:

Navigation.findNavController(homeRecycleView).navigate(TabFragmentDirections.actionTabToBrowser().setUrl("Http://www.baidu.com"))

而BrowserActivity里面只要两行代码就能获取到参数:

val args by navArgs()
val url = args.url

要使用上面的argument必须在gradle里面引入safeArgs相关依赖,如下:

1)App的build.gradle文件添加:

apply plugin: 'Androidx.navigation.safeargs'

2)Project的build.gradle文件中添加:

dependencies {
        classpath 'com.android.tools.build:gradle:3.6.2'
        classpath "org.jetbrains.Kotlin:kotlin-gradle-plugin:$kotlin_version"
        classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.2.1"
    }

当然也可以不使用argument标签来进行参数传递,不过这个标签的好处就是对类型做了限定,所以也是safe argument的由来,个人感觉另一个好处就是每个界面传递的参数一目了然,不会漏掉或者传错

findNavController传入的参数可以是Activity或者View,最终逻辑都是寻找到NavHostFragment,然后获取它的mNavController,这样做得好处是我们只要传递给它一个view就能进行跳转了,源码如下:

private static NavController findViewNavController(@NonNull View view) {
        while (view != null) {
            NavController controller = getViewNavController(view);
            if (controller != null) {
                return controller;
            }
            ViewParent parent = view.getParent();
            view = parent instanceof View ? (View) parent : null;
        }
        return null;
}

从上面大概可以了解到使用Navigation进行fragment管理的好处不仅是对各种异常情况的处理,代码也会简洁很多,而且参数传递也多了一些特性

 

二、koin框架

简介:

Koin框架,适用于使用Kotlin开发 ,是一款轻量级的依赖注入框架,无代理,无代码生成,无反射。相对于dagger 而言更加适合Kotlin语言

使用样例:

1)app的build.gradle中引入依赖:

dependencies {
    // Koin for Android
    implementation 'org.koin:koin-android:2.0.1'
    // or Koin for Lifecycle scoping
    implementation 'org.koin:koin-androidx-scope:2.0.1'
    // or Koin for Android Architecture ViewModel
    implementation 'org.koin:koin-androidx-viewmodel:2.0.1'
}

2)初始化,在Application onCreate中注册组件:

override fun onCreate() {
        super.onCreate()
        startKoin {
            androidContext(this@App)
            //注册组件
            modules(appModule)
        }
   }

3)module定义:

val viewModelModule = module {
    viewModel { LoginViewModel(get(),get()) }
   }
val repositoryModule = module {
   single { SquareRepository() }
   single { HomeRepository() }
   single { ServiceImpl1() }
   single(named(name = "test")) { ServiceImpl2() }
   single{ (view : View) -> Presenter(view) }
}
val appModule = listOf(viewModelModule, repositoryModule)

module定义的原理其实就是注册类的定义,这样在依赖注入的时候才能根据你要的类型来构建对应的实例

4)依赖注入:

val service : Service by inject() //默认注入的是 ServiceImpl1
val service : Service by inject(name = "test") //注入的是ServiceImpl2
val presenter : Presenter by inject { parametersOf(view) }
val loginViewModel:LoginViewModel by viewModel()

上面的依赖注入by inject是koin框架会根据注册类的定义构建一个实例,by viewModel()比较特殊,因为viewModel是和activity或者fragment的生命周期绑定的,所以这边注入也是注入到当前的fragment或者activity,可以看段代码:

fun  Koin.getViewModel(parameters: ViewModelParameters): T {
    val vmStore: ViewModelStore = parameters.owner.getViewModelStore(parameters)
    val viewModelProvider = rootScope.createViewModelProvider(vmStore, parameters)
    return viewModelProvider.getInstance(parameters)
}
fun  LifecycleOwner.getViewModelStore(
        parameters: ViewModelParameters
): ViewModelStore =
     when {
            parameters.from != null -> parameters.from.invoke().viewModelStore
            this is FragmentActivity -> this.viewModelStore
            this is Fragment -> this.viewModelStore
            else -> error("Can't getByClass ViewModel '${parameters.clazz}' on $this - Is not a FragmentActivity nor a Fragment neither a valid ViewModelStoreOwner")
     }

从上面可以看到创建的viewModel会绑定到当前的viewModelStore,这个也是真正做到依赖注入对创建对象的生命周期管理作用

相比dagger框架,koin框架不需要对注入对象手动调用注入,因为它创建的对象不是全局的,而是和当前对象绑定的,也就不需要等待注入参数准备好后再进行构建,特别如果注入对象里面还有注入对象,手动注入就会变得混乱

 

三、Retrofit2

简介:

Retrofit2简单的说就是一个网络请求的适配器,它将一个基本的Java接口通过动态代理的方式翻译成一个HTTP请求,并通过OkHttp去发送请求。此外它还具有强大的可扩展性,支持各种格式转换以及RxJava

使用样例:

1)创建interface 服务接口:

public interface IWeather {
     @GET("/v3/weather/now.JSON")
     Call weather(@Query("key")String key,@Query("location")String location);
     @FORMUrlEncoded
     
     @POST("/article/query/{page}/json")
     WanResponse searchHot(@Path("page") int page, @Field("k") String key)
     @POST("users/new")
     Call createUser(@Body User user);
     //QueryMap可以实现将参数统一放到Map里面,减少参数定义
     @GET("/v3/weather/now.json")
     Call weather(@QueryMap Map key,@QueryMap Map location);
}

Retrofit2要求我们创建如上面所示的interface接口,而创建该接口的目的是,retrofit通过获取接口的@GET注解里面的值,与下面即将讲到的baseUrl拼接成一个请求网址,另外通过调用接口的方法,填充相应参数之类的

2)创建Retrofit:

Retrofit retrofit2 = new Retrofit.Builder()
        .baseUrl("https://api.thinkpage.cn")
        .addConverterFactory(GsonConverterFactory.create())
        .client(new OkHttpClient())
        .build();
IWeather iWeather = retrofit2.create(IWeather.class);

通过Retrofit.Builder()方法来创建一个Retrofit实例,baseUrl()是设置Url,这是必须的,addConverterFactory()该方法是设置解析器,即上面提到的GsonConverterFactory,最后通过build()完成创建

3)创建请求,设置请求参数,执行请求:

Call call = iWeather.weather("rot2enzrehaztkdk","beijing");
call.enqueue(new Callback() {
      @Override
      public void onResponse(Call call, Response response) {
         WeatherBean weatherBean = response.body();
         Log.d("cylog",weatherBean.results.get(0).now.temperature+"");
      }
      @Override
      public void onFailure(Call call, Throwable t) {
        Log.d("cylog", "Error" + t.toString());
      }
 });

通过调用IWeather的weather方法(我们在接口中定义的),把两个关键参数传递了进入,这两个参数均是使用@Query注解标记的,因此构成了url中的请求参数,而返回的call则是我们的请求。最后,调用call.enqueue方法,执行一个异步请求,如果成功了,则回调onResponse方法,否则回调onFailure方法。另外,这里补充一下:call.enqueue是一个异步方法,不在同一线程内,而call.execute是一个同步方法,在同一线程内

4) 上传文件

@Multipart
@PUT("user/photo") 
Call updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);

@Multipart表示能使用多个Part,而@Part注解则是对参数进行标记,RequestBody是一种类型,是okHttp3里面的一个类,既然请求参数是RequestBody类型的,那么我们要把请求体封装到RequestBody里面去,通过RequestBody.creat()方法进行创建,RequestBody创建有两个参数,第一个参数是MediaType,是媒体类型,第二个参数可为String、byte、file等,通过上述方法创建的RequestBody是一个请求体,将与其他的请求体一起发送到服务端,它们的key值是@Part("key")注解的值

Retrofit2的好处就是对各种请求的封装,这样代码写起来就简洁很多,还有一个特性是比较符合HTTP2.0多路复用,多路复用正是同一个域名下的请求可以共用一个连接,这与Retrofit2的定义刚好不谋而合

 

四、WorkManager

简介:

WorkManager 在工作的触发器 满足时, 运行可推迟的后台工作。WorkManager会根据设备API的情况,自动选用JobScheduler, 或是AlarmManager来实现后台任务,WorkManager里面的任务在应用退出之后还可以继续执行,这个技术适用于在应用退出之后任务还需要继续执行的需求,对于在应用退出的之后任务也需要终止的需求,可以选择ThreadPool、AsyncTask

使用样例:

1)使用状态机

val request1 = OneTimeWorkRequestBuilder().build()
val request2 = OneTimeWorkRequestBuilder().build()
val request3 = OneTimeWorkRequestBuilder().build()
WorkManager.getInstance().beginWith(request1)
        .then(request2)
        .then(request3)
        .enqueue()

2)设置约束条件:     

val myConstraints = Constraints.Builder()
        .setRequiresDeviceIdle(true)//指定{@link WorkRequest}运行时设备是否为空闲
        .setRequiresCharging(true)//指定要运行的{@link WorkRequest}是否应该插入设备
        .setRequiredNetworkType(NetworkType.NOT_ROAMING)
        .setRequiresBatteryNotLow(true)//指定设备电池是否不应低于临界阈值
        .setRequiresCharging(true)//网络状态
        .setRequiresDeviceIdle(true)//指定{@link WorkRequest}运行时设备是否为空闲
        .setRequiresStorageNotLow(true)//指定设备可用存储是否不应低于临界阈值
        .addContentUriTrigger(myUri,false)//指定内容{@link android.net.Uri}时是否应该运行{@link WorkRequest}更新
        .build()
val request = PeriodicWorkRequestBuilder(24,TimeUnit.SECONDS)
        .setConstraints(myConstraints)//注意看这里!!!
        .build()

3)加入队列后监听任务状态:  

val liveData: LiveData =WorkManager.getInstance().getStatusById(request.id)
    public final class WorkStatus {   
      private @NonNull UUID mId;  
      private @NonNull State mState;   
      private @NonNull Data mOutputData;   
      private @NonNull Set mTags;   
      public WorkStatus(
            @NonNull UUID id,
            @NonNull State state,
            @NonNull Data outputData,
            @NonNull List tags) {
        mId = id;
        mState = state;
        mOutputData = outputData;
        mTags = new HashSet(tags);
    }
    public enum State {
      ENQUEUED,//已加入队列
      RUNNING,//运行中
      SUCCEEDED,//已成功
      FAILED,//已失败
      BLOCKED,//已刮起
      CANCELLED;//已取消
      public boolean isFinished() {
        return (this == SUCCEEDED || this == FAILED || this == CANCELLED);
      }
   }

4)combine 操作符-组合

现在我们有个复杂的需求:共有A、B、C、D、E这五个任务,要求 AB 串行,CD 串行,但两个串之间要并发,并且最后要把两个串的结果汇总到E,代码如下:  

   val chuan1 = WorkManager.getInstance()
    .beginWith(A)
    .then(B)
   val chuan2 = WorkManager.getInstance()
   .beginWith(C)
   .then(D)
   WorkContinuation
    .combine(chuan1, chuan2)
    .then(E)
    .enqueue()

使用WorkManager的好处就是对android各种API的策略做了适配,特别目前android对后台执行任务的限制越来越厉害,app需要做很多处理来适配各个版本,不仅代码逻辑复杂,效果也不能做到非常好。不过目前WorkManager还处于试验阶段,可以等它稳定后再引入

 

五、kotlin suspendCoroutine

kotlin的一大特色就是协程,其中一个作用就是将异步回调写成同步方式,这里就用到了suspendCoroutine,它可以挂起当前协程而不阻塞线程,这样就能等待异步回调返回前挂起当前协程,比如想获取camera实例,正常是监听camera打开的回调来获取,这样写逻辑就比较复杂,但是用suspend fun可以实现没有线程阻塞的执行暂停(suspend只能在协程里面调用,注册回调后就结束,只是挂起当前协程,不会阻塞线程,影响其他协程运行),直到调用resume方法返回结果,这样就能等待camera实例返回再继续执行,代码如下:   

 private suspend fun openCamera(
            manager: CameraManager,
            cameraId: String,
            handler: Handler? = null
    ): CameraDevice = suspendCancellableCoroutine { cont ->
        manager.openCamera(cameraId, object : CameraDevice.StateCallback() {
            override fun onOpened(device: CameraDevice) = cont.resume(device)
            override fun onDisconnected(device: CameraDevice) {
                Log.w(TAG, "Camera $cameraId has been disconnected")
                requiReactivity().finish()
            }
            override fun onError(device: CameraDevice, error: Int) {
                val msg = when(error) {
                    ERROR_CAMERA_DEVICE -> "Fatal (device)"
                    ERROR_CAMERA_DISABLED -> "Device policy"
                    ERROR_CAMERA_IN_USE -> "Camera in use"
                    ERROR_CAMERA_SERVICE -> "Fatal (service)"
                    ERROR_MAX_CAMERAS_IN_USE -> "Maximum cameras in use"
                    else -> "Unknown"
                }
                val exc = RuntimeException("Camera $cameraId error: ($error) $msg")
                Log.e(TAG, exc.message, exc)
                if (cont.isActive) cont.resumeWithException(exc)
            }
        }, handler)
    }

获取camera实例代码:    

private fun initializeCamera() = lifecycleScope.launch(Dispatchers.Main) {
        // Open the selected camera
        camera = openCamera(cameraManager, args.cameraId, cameraHandler)
        //use camera..
     }

suspend fun可以像上面直接返回结果,也可以使用use{result -> }来返回,前者是遇到异常直接抛出,没有处理就会崩溃,后者是try-catch形式,不会直接崩溃,适用于直接跳过异常情况

 

总结

经过上面对一些主要用到的框架和组件的介绍,我们基本可以了解到它们的主要作用,使用这些组合可以很快的搭建一个app的框架并且可以适配android各种版本的差异,并且后期维护也会更简单高效些



--结束END--

本文标题: Android快速搭建MVVM框架

本文链接: https://www.lsjlt.com/news/29440.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Android快速搭建MVVM框架
    架构上面是从一个开源项目中了解到的框架结构,以最简洁的方式搭建一个app的基础框架。框架的几个特点是:通过Jetpack的Navigation构建单Activity多Fragment结构,我们知道Activity是属于比较重的组件,而Fra...
    99+
    2022-06-06
    mvvm Android
  • android mvvm框架怎么搭建
    要搭建Android MVVM框架,您可以按照以下步骤进行: 创建Android项目:使用Android Studio创建一个新...
    99+
    2023-10-22
    android
  • Android用kotlin搭建MVVM框架(一)
    Android用kotlin搭建MVVM框架(一) 什么是MVVM搭建MVVM框架 什么是MVVM Android的项目框架,大家应该都不陌生吧。而目前的项目框架有MVC,MVP,MVVM...
    99+
    2023-10-11
    android kotlin android studio
  • 从0快速搭建一个实用的MVVM框架(超详细)
    目录前言基于MVVM进行快速开发,上手即用。(重构已完成,正在编写SampleApp)如何集成1.继承BaseApplication2.创建ViewModel扩展函数3.引入一键生成...
    99+
    2022-11-13
  • 快速搭建SSM框架【详细】
    文章目录 一、开发环境准备二、搭建SSM2.1新建Maven项目2.2项目整体结构2.3spring-config.xml配置2.4jdbc.properties配置2.5mybatis-co...
    99+
    2023-10-09
    mybatis java spring
  • 用Django框架快速搭建博客
    阅读文本大概需要 5 分钟。上次 2 篇文章给大家分享了 Django 搭建的基本知识,今天就把 Django 基本知识串起来,搭建一个简单的博客网站。项目环境语言:Python 3.6编辑器:Pycharm主要步骤创建项目创建 APP创建...
    99+
    2023-06-02
  • 怎么快速搭建一个SSM框架
    怎么快速搭建一个SSM框架?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。一、我用的是idea二、首先创建一个maven项目,结构如下:三、开始写配置文件pom文...
    99+
    2023-05-31
    ssm
  • 教你快速搭建一个springMVC框架
    这篇文章将为大家详细讲解有关教你快速搭建一个springMVC框架,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。一、搭建步骤导入jar包、创建项目包结构在web.xml中配置前端控制器编写s...
    99+
    2023-05-31
    springmvc
  • Spring Boot快速搭建Spring框架教程
           Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J...
    99+
    2023-05-31
    spring boot spring框架
  • Android技术框架篇(三):MVVM框架
    目录 一、MVVM架构的基本概念 二、MVVM架构的核心思想 三、MVVM架构的实现方式 四、MVVM架构的优缺点 五、MVVM架构的应用场景 一、MVVM架构的基本概念 以下是MVVM架构的基本概念的简要总结: 概念描述Model数...
    99+
    2023-08-31
    android java
  • 在windows下快速搭建web.py开发框架方法
      用Python进行web开发的话有很多框架供选择,比如最出名的Django,tornado等,除了这些框架之外,有一个轻量级的框架使用起来也是非常方便和顺手,就是web.py。它由一名黑客所创建,但是不...
    99+
    2022-06-04
    框架 快速 方法
  • 一文带你快速搭建框架(最全MyBatis笔记)
      目录 一.概述 1.简介 2.maven构建 二.相关概念 1.Mapper接口 2.ORM思想 三.映射配置文件 1.文件结构 2.映射配置文件标签详解 3.SQL语句中参数的获取 (1)获取方式 (2)参数类型 4.各种SQL操作...
    99+
    2023-09-03
    mybatis java maven
  • 如何在 Windows 系统中快速搭建 Python 框架环境?
    Python 是一种高级编程语言,其简单易学、高效实用、可移植性强等特点,使其成为了众多编程语言中最流行的一种。但是,在 Windows 系统中搭建 Python 框架环境并不是一件容易的事情,这篇文章将会向您展示如何在 Windows 系...
    99+
    2023-07-24
    框架 shell windows
  • Android 架构之数据库框架搭建
    目录1、先创建对应相关操作的注解1.1 bTable 标识表 1.2 DbPrimaryKey 标识主键 1.3 DbFiled 标识成员属性 2、创建对应表操作...
    99+
    2022-11-12
  • golang快速搭建
    随着互联网的不断发展,编程语言的种类也在不断增加与更新。其中golang作为一门新兴的编程语言,因其快速、安全、简单易用等特点,越来越受到开发者的关注。在本文中,我将分享如何快速搭建golang开发环境。第一步:安装golanggolang...
    99+
    2023-05-18
  • 详解Android的MVVM框架 - 数据绑定
    本教程是跟着 Data Binding Guide 学习过程中得出的一些实践经验,同时修改了官方教程的一些错误,每一个知识点都有对应的源码,争取做到实践与理论相结合。Data Binding 解决了 Android UI 编...
    99+
    2023-05-31
    android mvvm 双向绑定
  • Android模块化框架怎么搭建
    搭建Android模块化框架需要以下步骤:1. 设计模块化架构:确定项目的模块划分,每个模块的功能和职责等。2. 创建Android...
    99+
    2023-10-08
    Android
  • Android模块化框架如何搭建
    搭建Android模块化框架可以按照以下步骤进行:1. 创建一个新的Android项目:使用Android Studio创建一个新的...
    99+
    2023-10-11
    Android
  • 详解Android框架MVVM分析以及使用
    Android MVVM 分析以及使用 首先我们需要知道什么是MVVM,他的功能和优点,以及他的缺点。 MVVM是Model-View-ViewModel的简写。它本质上就是MVC ...
    99+
    2022-11-12
  • 从零搭建SpringBoot+MyBatisPlus快速开发脚手架
    目录前言聊聊mall-tiny项目项目简介项目演示技术选型数据库表结构接口文档使用流程升级过程Swagger升级Spring Security升级MyBatis-Plus升级解决循环...
    99+
    2022-11-13
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作