一种清晰, 便于扩展android项目架构方案,androidstudio基础教程
作者:互联网
采用以上架构,我们在开发一个功能时,可以很清晰的去组织代码。但这种方式,只能保证某个业务维度,某个功能点相关的代码是清晰的,好维护的。对于整个项目而言,我们该如何架构整个项目呢?
项目层面
对于一个小型的项目,由于代码量少,业务通常不复杂,没有过多的考虑整体代码的组织,结构的管理也不会给后期的维护带来很大的负担,毕竟代码量少,后期维护的成本相对较低,但对于一个中大型项目,代码组织混乱,对后期的维护人员来讲就是灾难。此处引入的方案是参看这篇文章,我把做了一些改动,引入到公司里某一款app开发上,大家反馈都很不错,开发体验大大提升。
我们先来看一下这篇文章提到的方案,作者有把示例代码上传到github上,其地址在这里。 其目录结构如下:
作者将功能与项目的基础架构的代码分离开。整个工程分为core
和features
两个包,core
下面放的是整个工程的基础代码。将业务进行分类组织在features
目录下,这样便将代码按照功能模块的维度组织起来。某个功能(如login)相关的代码都会在features.login
下面。其好处:
- 代码的结构更加清晰,后面维护方便
- 后期如果业务起来了,想要做组件化,因为代码都在同一个目录下面,抽取出去也更加方便。
细化
再回到Google推荐的架构图,我们再将Google推荐的这个架构整合进项目中,于是,项目的结构便如下所示:
com.xxxx.app
core
整个app内所有模块共享,或公共的配置data
全局的数据访问,如用户信息,app配置等model
AppConfigInfo
UserInfo
datasource
impl
AppConfigRemoteDataSource
AppConfigLocalDataSource
UserRemoteDataSource
UserLocalDataSource
IUserRemoteDataSource
IUserLocalDataSource
IAppConfigRemoteDataSource
IAppConfigLocalDataSource
AppConfigRepository
UserRepository
util
view
base
BaseActivity
BaseFragment
BaseViewModel
hybrid
features
下面是按业务来分组login
ui
xxxActivity
xxxViewModelFactory
xxxViewModel
可直接调用core/data
里的UserRepository
product
data
考虑到同一个模块中的数据层面可以共用,故放在外层model
ProductListInfo
ProductDetailInfo
datasource
IProductLocalDataSource
IProductRemoteDataSource
impl
ProductLocalDataSourceImpl
ProductRemoteDataSourceImpl
ProductRepository
ui
detail
view
放置自定义ViewProductLabelView
ProductDetailActivity
ProductDetailViewModel
list
rendermodel
view
放置自定义View- …
ProductListViewModel
(和ProductDetailViewModel
都调用ProductRepository
来获取数据)- …
xxxViewModelFactory
如果业务简单,ViewModelFactory
可以写在这里, detail模块和list可以共用personal
data
ui
xxxViewModelFactory
xxxViewModel
此处可能需要获取用户信息,则直接调用core/data
里的UserRepository
以下对上面的结构进行说明
core 目录
服务于整个工程,一些基础代码。关于系统配置,用户信息等数据的操作全部放在这个里面。
data
目录:DAO相关的操作,model
包下面的是pojo, 数据的获取或持久化全部由xxxRepository
去调用datasource
包下面的数据源去实现util
目录:放置一些公共的工具类view
目录: 放置公共的自定义view,这些自定义view脱离具体的业务联系,能够在各业务模块使用base
目录:用来放置一些基础的组件,如BaseActivity
,BaseFragment
,BaseViewModel
features目录
按业务模块来划分不同的包,组织在该目录下。以下对代码的组织做一些说明
login模块
在上面的目录中,由于涉及到用户登录相关的DAO操作都已经放到core
目录下了, 假设可以满足要求,那么login
模块下只有UI相关文件和ViewModel
,xxxViewModelFactory
product模块
这个模块是用来模拟某个模块下多个页面的场景。以商品列表页和详情页为例。由于DAO的操作可能
《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享
会有重叠的场景,这里将它们的数据操作写在一起。UI层面按功能再分为list
, detail
两个包。list
, detail
两个页面的ViewModel可以采用同一个ViewModelFactory来创建。
rendermodel
包:这个目录下有一个需要单独说明一下,当我们从服务器拿到数据了如ProductInfo
之后,将数据显示在页面上,我们显示在页面上的一些信息很有可能是需要根据ProductInfo
的数据进行加工的。为此,我们定义一个ProductInfoRenderModel.java
用来承载只需要显示在页面上的数据。ProductInfoRenderModel.java
则放在rendermodel
包下面。
personal模块
personal
模块中也会涉及到用户相关的信息,这也就是为什么一开始设计把用户相关信息的dao操作放到core
目录下。personal
模块下的xxViewModel
如果要查用户相关的信息,可以直接调用core
下面的UserRepository
至此,整个项目的大体架构便梳理完成了。采用这种方案将代码以功能模块进行划分,方便后期的维护。既使后续某个模块中进行了技术方案的改革,也能保证其影响的粒度最小。当然这里面主要是为了说明项目的主要结构,在实际项目中,除了这些,我们还会有adapter
, 自己写的各种工具等等,这个就根据实际情况再自己分包了。接下来我们看一下涉及到的相关技术栈
技术栈
在这种项目架构中我们主要用到的技术栈有Jetpack
中的ViewModel
, ViewModelFactory
, LiveData
, ROOM
,下面简单介绍一下这几种技术以及它们之间的整合。当然用于网络请求相关的我们可以用Okhttp
, retrofit
,此处就不介绍。
ViewModel
Jetpack
组件中提供了ViewModel
可以方便的将数据,对象与组件的生命周期绑定起来,方便进行组件间的数据共享,如一个activity
中多fragment
的情况。同时它可以有效的从架构层面上进行解藕,和mvp架构模式相比,可以大大减少接口/方法的个数。以登录为例,用户调用登录接口时需要调用presenter.login方法,login成功后调用 view.loginSuccess
方法。而采用ViewMode
后,用户在登录时调用viewModel.login
方法,登录成功后,更新ViewModel
中的LiveData
,然后在调用处观察LiveData
做相应的行为就可以。
ViewModelProvider.Factory
用来创建ViewModel
,ViewModel
不可以自己创建,必须要借助ViewModelProvider.Factory
来创建。在创建时通常为ViewModel指定数据仓库,如下:
public class LoginViewModelFactory implements ViewModelProvider.Factory {
@NonNull
@Override
public T create(@NonNull Class modelClass) {
if (modelClass.isAssignableFrom(LoginViewModel.class)) {
return (T) new LoginViewModel(LoginRepository.getInstance(new LoginDataSource()));
} else {
throw new IllegalArgumentException(“Unknown ViewModel class”);
}
}
}
LiveData
在数据发生变化时,需要通知给页面。通常可以采用接口的方工去做,但如果要观察的数据很多,就需要定义大量的接口,代码会十分冗余。为此, Google提供了LiveData
组件,它是一个可被观察的数据容器类,将数据包装起来,使数据成为被观察者,当该数据发生变化时,观察者能获得通知。
ViewModel
是用来存储数据,LiveData
的作用是在ViewModel
发生变化时通知页面。因此, LiveData
通常放在ViewModel
中使用,用于包装ViewModel
中那些需要被外界观察的数据。
我们来结合具体的例子(登录)看这三者的配合使用
示例
UI层面(LoginActivity)
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityLoginBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
…
viewModel = new ViewModelProvider(this, new LoginViewModelFactory()).get(LoginViewModel.class);
registerObserver();
bindClickEvent();
}
private void registerObserver() {
viewModel.getLoginResult().observe(this, new Observer() {
@Override
public void onChanged(LoginResult loginResult) {
if (loginResult.success) {
//登录成功
}
}
});
//出现异常
viewModel.exceptionLiveData.observe(this, new Observer() {
@Override
public void onChanged(AppException e) {
Toast.makeText(LoginActivity.this, e.getBizMsg(), Toast.LENGTH_SHORT).show();
}
});
Data.observe(this, new Observer() {
@Override
public void onChanged(AppException e) {
Toast.makeText(LoginActivity.this, e.getBizMsg(), Toast.LENGTH_SHORT).show();
}
});
标签:core,基础教程,代码,ViewModel,androidstudio,模块,new,android,目录 来源: https://blog.csdn.net/m0_65638168/article/details/122197674