MVVM框架的初体验

本文介绍了如何使用JetPack的MVVM框架,结合APT注解处理工具和Dagger来实现数据层与ViewModel的解耦。通过简单的注解,实现了网络接口的自动化处理和ViewModelFactory的生成,降低了开发复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第一次写文章~,废话少说。先给大家拜个早年 2020 年新年快乐~

2018 年Google I/O 大会推出了 JetPack 框架。旨在帮助开发者更轻松地开发出色的 Android 应用。

作为一名Android开发还不赶紧尝试一波~

下面摘自Google:

  • Jetpack 是 Android 软件组件的集合,使您可以更轻松地开发出色的 Android 应用。这些组件可帮助您遵循最佳做法、让您摆脱编写样板代码的工作并简化复杂任务,以便您可以专注于您关心的代码。
  • Jetpack 包含与平台 API 解除捆绑的 androidx.* 软件包库。这意味着,它提供向后兼容性并且比 Android 平台更频繁地更新,从而确保您始终可以获取最新且最好的 Jetpack 组件版本。

目前开发中常用的设计模式 无非MVP、MVVM 关于各自的优缺点。相信每个开发都各有各的看法与观点,VM模式在我看来也是MVP的变种,能够更好地去和View解耦,可以极大地给View层减负。

以下摘自百度:

MVVM优点:
	1. 低耦合。视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的"View"上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
	2. 可重用性。你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。
	3. 独立开发。开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计,使用Expression Blend可以很容易设计界面并生成xaml代码。
	4. 可测试。界面素来是比较难于测试的,而现在测试可以针对ViewModel来写    

简介

只使用3个注解也可以轻松完成MVVM框架的搭建,让你的代码也可以看起来很骚~~~
本项目根据Google 新框架JepPack基本模式搭配dagger2 (地址) 完成 ViewModel 与 Respository (数据层) 的解耦。
使用 APT (Annotation Processing Tool) 注解处理工具,配合 Javapoet 构建完成。

项目整体架构参照Google的模式,基本保持一致。

项目地址: MvvmKotlin

? ? ? ? ? ? 喜欢记得 Star~ 点赞 ? ? ? ? ? ?

下面分为几个步骤大致说明一下实现过程~

直接引用原图(数据库部分没做处理 后续再说~~~)

  • 整体框架结构
    Android JectPack

Respository (数据层)

Respository(数据处理层): 是用来处理网络数据、数据库、本地等数据的逻辑。(目前仅实现了网络部分)
数据层,依然是经典的搭配组合:retrofit + rxjava  使用dagger 来提供实例对象。

自定义的Repository只需继承BaseRepository,BaseRepository由APT自动生成,并且提供所有网络(Retrofit)接口实例。在BaseRepository中提供各个接口数据。

  1. 处理retrofit接口。在接口类中添加注解@ApiFactory即可
@ApiFactory
interface DemoService {
    @GET("users/{user}")
    fun getUser(@Path("user") user: String): Flowable<Any>
}
  1. APT会找到注解ApiFactory 并自动生产一些重复的代码,生成的代码会对接口进行简单处理。
    代码注释中包含每个函数来自那个接口的方法,方便快速定位。手动 ?
public class DemoServiceFactory extends BaseHttpFactory<DemoService> {
  @Inject
  public DemoServiceFactory(RetrofitInterface retrofitInterface) {
     super(retrofitInterface);
  }

  /**
   * @apt生产的接口方法 {@link DemoService#getUser} 
   */
  public Flowable<Object> getUser(String user) {
    return mObtainService.getUser(user).compose(RxThread.Companion.applyAsync());
  }
}
  1. APT自动生成BaseRepository,并且通过dagger注入所有接口工厂
    BaseRepository抽象类中拥有所有retrofit接口工厂的实例,方便调用网络接口。
public abstract class BaseRepository implements RepositoryInterface {
  /**
   * @apt生产 注入 @{@link com.m.mvvmkotlin.sample.DemoService} 的网络请求工厂 
   */
  @Inject
  public DemoService2Factory mDemoServiceRepository;

  /**
   * @apt生产 注入 @{@link com.m.mvvmkotlin.smaple2.DemoService2} 的网络请求工厂 
   */
  @Inject
  public DemoService2Factory mDemoService2Repository;

  public CompositeDisposable mSubscription;

  public BaseRepository() {
    this.mSubscription = new CompositeDisposable();
    DaggerBaseRepositoryComponent.builder().build().inject(this);
  }

  @Override
  public void onCleared() {
     mSubscription.clear();
  }
}

至此,网络请求部分已经全部结束了。
可是我们好像还没做什么东西~~~ 还没开始,怎么就结束了~。???
是的。我们要做的仅仅是 在retrofit 接口 添加一个注解,剩下的都有APT帮我们做完了~

ViewModel (Model层)

ViewModel模块无须关心自身Factory的生产过程。只需在构造函数中传入自身所需要的Respository(数据层)使用即可,
在ViewModle的构造中可同时传入多个数据源,Factory将自动获取数据实例传入ViewModel中。

~~~~废话少说, 直接上代码~
  1. ViewModel构造中传入需要的数据源获取数据
    ViewModel的基本使用方式、在构造函数中,我们传入自己所需要的Repository(数据层) ,此处可以是多个或者不传。
    有些使用过Jetpack框架的小伙伴可能会说了。ViewModel是需要相对应的ViewModelFactory的,以便对Model和View进行绑定。 带着问题我们往下看step2~~~
class DemoViewModel(private var demoRepository: DemoRepository) : ViewModel(), 
DemoTaskInterface.RespositoryTask {

    val data = ObservableField<String>()
    override fun result(result: String) { data.set(result) }
    
    fun get(user: String) { demoRepository.getUser(user, this) }

    override fun onCleared() {
        super.onCleared()
        demoRepository.onCleared()
    }
}
  1. APT将自动生成ViewModel对应的ViewModelFactory
    终于ViewModelFactory来了,是不是很亲切~~~
    Factory 会将Model需要的参数在 create 过程中将Model需要的数据源传入
    ViewModelFactory 的生产过程是利用了 @InjectViewModel @BindViewModel 这两个注解(至此三个注解都已出现)
    新出现的两个注解的使用 我们去看View层。我们的ViewModel最终都是要在View层出现的。
/**
 * @ViewModelFactory工厂 此类由apt自动生成 {@link DemoViewModel} 的工厂类 
 */
public class DemoViewModelFactory extends ViewModelProvider.NewInstanceFactory {
  private DemoRepository demoRepository;
  
  @Inject
  public DemoViewModelFactory(DemoRepository demoRepository) {
     this.demoRepository = demoRepository;
  }
  
  /**
   * @ {@link ViewModelProvider.NewInstanceFactory} 中的方法 
   */
  @Override
  public <T extends ViewModel> T create(Class<T> modelClass) {
    return (T) new DemoViewModel(demoRepository);
  }
}

Activity/Fragment (View层)

利用注解 @InjectViewModel @BindViewModel 配合APT自动完成ViewModel 与Respository 的注入过程,
利用控制反转轻松实现Activity/Fragment与ViewModel的关联,类似ButterKnife。
同时View可支持多个ViewModel的注入
  1. APT自动生成ViewModelFactoryTools类
    由于这个类较长 仅截取部分展示。查看完整过程。clone 项目 然后 build 即可
    代码中可以看到,我们将View(Activity/Fragment) 通过bind方法传入。然后将ViewModelFactory 与View进行绑定,并且为ViewModel进行了赋值。我们可以在一个View中使用多个ViewModel。
public class ViewModelFactoryTools {
  private static ViewModelFactoryTools mViewModelTools;

  /**
   * @ 注入 {@link DemoViewModel} 对应的: {@link DemoViewModelFactory } 
   */
  @Inject
  DemoViewModelFactory mDemoViewModelFactory;
....
....
....
 public void bind(AppCompatActivity baseActivity) {
    if(baseActivity instanceof MainActivity) {
      MainActivity mMainActivity = (MainActivity)baseActivity;
      mMainActivity.demoViewModel = ViewModelProviders.of(mMainActivity, mDemoViewModelFactory).get(DemoViewModel.class);
    }
    if(baseActivity instanceof MainActivity) {
      MainActivity mMainActivity = (MainActivity)baseActivity;
      mMainActivity.demoViewModel2 = ViewModelProviders.of(mMainActivity, mDemoViewModel2Factory).get(DemoViewModel2.class);
    }
  }
  1. View基类中获取ViewModelFactoryTools的实例
    在我们的基类中获取ViewModelFactoryTools的实例,通过bind方法实现View与ViewModel绑定,并且给View中带有 @BindViewModel注解的 ViewModel赋值。
    ViewModelFactoryTools.getInstance().bind(this)

  2. View中使用注解 @InjectViewModel @BindViewModel

@InjectViewModel
class MainActivity : BaseActivity(), View.OnClickListener {

    @BindViewModel
    lateinit var demoViewModel: DemoViewModel

    //绑定多个model
    @BindViewModel
    lateinit var demoViewModel2: DemoViewModel2
	
	...
	...
	... 省略
    }

至此。整体大致讲完了。好像也没说什么~~~ (第一次写~~~难免紧张 ☺️ ☺️ ☺️ ☺️)

关于 APT 的生产部分。项目 MvvmKotlin 中有源码 ,可以自行查看。 喜欢记得 star ~~ ? 。

后续 ~~

Gif

gif

Thanks

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值