brick框架,助力于快速、简单的搭建MVVM架构。

1,860 阅读2分钟

brick是什么

  • Brick是我去年公开、维护的若干个java、android库;其中最核心的brick框架的主要功能是帮助用户创建ViewModel和Repository,辅助用户快速搭建View-ViewModel-Repository层架构的库。

brick的问题

  • 初期的brick框架是通过反射实现的,虽然brick框架的反射使用并不频繁,吃不了多少性能,但是还是有很多人不喜欢反射;因此,我决心使用APT(注解处理器)重构brick。

进度怎么样了

  • 目前已完成通过@Provide注解为ViewModel生成get方法和lazy方法。
  • 生成Repository层的方法还在探索中,欢迎提出建议和方法。

@Provide注解的使用方法

  • 在你的项目的根目录下的build.gradle文件中添加以下代码,如果已存在则忽略
allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}
  • 在你的子模块的build.gradle文件中添加以下代码以启用kapt:
...
apply plugin: 'kotlin-kapt'
  • 在你的子模块的build.gradle文件中添加以下代码以使用brick:
dependencies {
	...
	kapt 'com.gitee.numeron.brick:compiler:0.1.0'
	implementation 'com.gitee.numeron.brick:annotation:0.1.0'
}
  • 在你的ViewModel类上使用@Provide注解,如:
@Provide
class WeChatAuthorViewModel(val userId: Long, authorIdProvider: () -> String) : ViewModel()
  • 展开AndroidStudio右侧边栏中的Gradle,依次进入:
[ProjectName] -> [ModuleName] -> Tasks -> other -> kaptDebugKotlin(双击执行脚本)

嫌麻烦直接Ctrl + F9编译也可以,等脚本运行完成或编译完成后,会在模块的build文件夹中生成对应的类,类名为ViewModel的名字后面多一个s:

  • 在你的View层(Activity或Fragment)中,直接调用生成的类中的方法即可:
private val weChatAuthorViewModel by lazyWeChatAuthorViewModel(0, ::authoerId)

生成的类如下:

package com.numeron.brick.contract

import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelStoreOwner
import java.lang.Class
import kotlin.Boolean
import kotlin.Function0
import kotlin.Lazy
import kotlin.Long
import kotlin.String
import kotlin.Suppress

fun ViewModelStoreOwner.lazyWeChatAuthorViewModel(userId: Long, authorIdProvider: Function0<String>): 
	Lazy<WeChatAuthorViewModel> = LazyWeChatAuthorViewModel(this, userId, authorIdProvider)

fun get(owner: ViewModelStoreOwner, userId: Long, authorIdProvider: Function0<String>): WeChatAuthorViewModel {
  val factory = WeChatAuthorViewModelFactory(userId, authorIdProvider)
  return ViewModelProvider(owner, factory).get(WeChatAuthorViewModel::class.java)
}

private class WeChatAuthorViewModelFactory(
	private val userId: Long, 
    private val authorIdProvider: Function0<String>
) : ViewModelProvider.Factory {

  @Suppress("UNCHECKED_CAST")
  override fun <VM : ViewModel> create(clazz: Class<VM>): VM = WeChatAuthorViewModel(userId, authorIdProvider) as VM
  
}

private class LazyWeChatAuthorViewModel(
  private val owner: ViewModelStoreOwner,
  private val userId: Long,
  private val authorIdProvider: Function0<String>
) : Lazy<WeChatAuthorViewModel> {

  private var _value: WeChatAuthorViewModel? = null

  override val value: WeChatAuthorViewModel
    get() {
      if(_value == null) {
        _value = get(owner, userId, authorIdProvider)
      }
      return _value!!
    }

  override fun isInitialized(): Boolean = _value != null
}

  • 生成的类中包含两个方法和两个私有类,get方法包装了ViewModelProvider的使用,lazyXXXViewModel则是一个kotlin扩展方法,返回Lazy<XXXViewModel>类型,可以直接通过by关键字代理给val属性。
  • 生成的两个私有类包含一个名为XXXViewModelFactory的类,一般会使用NewInstanceFactory通过反射直接创建无参的ViewModel,但是对于构造方法中有参数的ViewModel,我们一般需要继承自ViewModelProvider.Factory新建一个类来创建ViewModel。这里,我们可以直接生成与构造器中匹配的参数,不再需要手写。
  • 并且生成的XXXViewModelFactory中也没有调用反射,而是直接通过构造方法创建了一个对象,因为这个版本的brick诞生的的目的就是不使用反射嘛。