3)View层
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
btnNet?.setOnClickListener {
// View调用Controller
getUserInfo {
tvName?.text = it.name
tvAge?.text = it.age.toString()
tvHeight?.text = it.height.toString()
tvWeight?.text = it.weight.toString()
}
}
}
}
在MVC架构中,Controller实际上就是对Model代码的封装,如果在btnNet的点击回调中调用getUserInfo方法,则是View调用Controller。如果在点击回调中直接调用netModel的getUserInfo方法,那就变成了View调用Model。
=========================================================================
MVP架构是MVC架构的升级版,由Model、View、Presenter三部分组成:
-
Model:负责数据的存储及相关逻辑。
-
View:负责界面展示。
-
Presenter:负责业务逻辑。
MVP架构也将代码逻辑分成了数据逻辑、渲染逻辑、业务逻辑三部分。与MVC架构不同的是,在MVP架构中,负责业务逻辑的Controller层升级为Presenter层。Presenter层不再像Controller层一样耦合在View层中,而是作为独立的类与View层和Model层进行双向的通信,三者调用关系如下图所示:
MVP架构有效的将View层与Model层隔离,同时,由于Presenter层仅持有View层和Model层的接口,因此对于Presenter层逻辑的测试变得更加的方便。而由于所有的逻辑代码都集中到Presenter层中,因此Presenter层变得比原本的Controller层更臃肿。
点击按钮从网络获取用户信息,经过解析后展示到界面上。
1)Model层
data class UserInfo(
var name: String,
var age: Int,
var height: Int,
var weight: Int
)
interface NetResponse<T> {
fun onSuccess(data: T)
fun onError(e: Throwable)
}
class NetModel {
fun getUserInfo(callback: NetResponse<UserInfo>) {
// 模拟网络获取
val dataStr = getStringFromNet()
val info = dataStr.parseJson<UserInfo>()
return callback.onSuccess(info)
}
}
2)Presenter层
class Presenter(private val view: IView) {
private val model = NetModel()
fun getUserInfo() {
model.getUserInfo(object : NetResponse<UserInfo> {
override fun onSuccess(data: UserInfo) {
view.setName(data.name)
view.setAge(data.age)
view.setHeight(data.height)
view.setWeight(data.weight)
}
override fun onError(e: Throwable) {
val data = getNetErrorData()
view.setName(data.name)
view.setAge(data.age)
view.setHeight(data.height)
view.setWeight(data.weight)
}
})
}
private fun getNetErrorData(): UserInfo {
return UserInfo(name = "", age = 0, height = 0, weight = 0)
}
}
3)View层
interface IView {
fun setName(name: String)
fun setAge(age: Int)
fun setHeight(height: Int)
fun setWeight(weight: Int)
}
class MainActivity : AppCompatActivity(), IView {
private val presenter = Presenter(this)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
btnNet?.setOnClickListener {
presenter.getUserInfo()
}
}
override fun setName(name: String) {
tvName?.text = name
}
override fun setAge(age: Int) {
tvAge?.text = age.toString()
}
override fun setHeight(height: Int) {
tvHeight?.text = height.toString()
}
override fun setWeight(weight: Int) {
tvWeight?.text = weight.toString()
}
}
==========================================================================
MVVM架构最早由微软提出,并在微软的桌面客户端UI框架WPF中实现,由Model、View、ViewModel三部分组成:
-
Model:负责数据的存储及相关逻辑。
-
View:负责界面展示。
-
ViewModel:负责业务逻辑。
MVVM架构是MVP架构的简化版,它同样的解决了View层与Model层的隔离问题。不同于MVP架构中的View层与Presenter层之间的双向通信,MVVM架构采用了一种View层与ViewModel层绑定的方式,当ViewModel层中的UI数据或属性发生变化时,View层的UI会跟随一起变化,这样原本Presenter层中操作View层接口的逻辑通过绑定的方式被简化,层级变得更加轻量,简化后的Presenter层与View层之间只存在数据驱动的关系,Presenter层被简化成了ViewModel层。三个层级的调用关系如下图所示:
在MVVM架构的早期发展中, 开发者们使用谷歌官方的DataBinding框架实现数据与视图的绑定,但DataBinding框架使用复杂,且每当有一处代码需要修改,就会联动修改多处代码。后来,谷歌官方推荐使用Jetpack组件集中的LiveData+ViewModel。通过使用LiveData+ViewModel,大大减少了在使用MVVM架构中模版代码的编写。再后来,为了更好的在协程中使用MVVM架构,以及更方便的编写流式代码,谷歌官方推荐使用StateFlow。
MVVM架构既做到了View层与Model层的隔离,又保证了ViewModel层的简洁不臃肿。View层与ViewModel层的交互完全依赖数据驱动,方便层级的逻辑复用与测试以及多人的协作开发。但同时,由于MVVM架构比MVC架构和MVP架构更抽象,因此在使用时需要编写更多的模版代码。当UI界面复杂时,由于每个UI需要有不同的数据,因此会造成数据过于分散不易维护。
点击按钮从网络获取用户信息,经过解析后展示到界面上。
1)Model层
data class UserInfo(
var name: String,
var age: Int,
var height: Int,
var weight: Int
)
interface NetResponse<T> {
fun onSuccess(data: T)
fun onError(e: Throwable)
}
class NetModel {
fun getUserInfo(callback: NetResponse<UserInfo>) {
// 模拟网络获取
val dataStr = getStringFromNet()
val info = dataStr.parseJson<UserInfo>()
return callback.onSuccess(info)
}
}
2)ViewModel层
class NetViewModel : ViewModel() {
private val model = NetModel()
private val name = MutableLiveData<String>("")
private val age = MutableLiveData<Int>(0)
private val height = MutableLiveData<Int>(0)
private val weight = MutableLiveData<Int>(0)
fun getUserInfo() {
model.getUserInfo(object : NetResponse<UserInfo> {
override fun onSuccess(data: UserInfo) {
name.postValue(data.name)
age.postValue(data.age)
height.postValue(data.height)
weight.postValue(data.weight)
}
override fun onError(e: Throwable) {
val data = getNetErrorData()
name.postValue(data.name)
age.postValue(data.age)
height.postValue(data.height)
weight.postValue(data.weight)
}
})
}
private fun getNetErrorData(): UserInfo {
return UserInfo(name = "", age = 0, height = 0, weight = 0)
}
fun name(): LiveData<String> = name
fun age(): LiveData<Int> = age
fun height(): LiveData<Int> = height
fun weight(): LiveData<Int> = weight
}
3)View层
class MainActivity : AppCompatActivity() {
private lateinit var viewModel: NetViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewModel = ViewModelProvider(this).get(NetViewModel::class.java)
viewModel.name().observe(this, Observer<String> {
tvName?.text = it
})
viewModel.age().observe(this, Observer<Int> {
tvAge?.text = it.toString()
})
viewModel.height().observe(this, Observer<Int> {
tvHeight?.text = it.toString()
})
viewModel.weight().observe(this, Observer<Int> {
tvWeight?.text = it.toString()
})
btnNet?.setOnClickListener {
viewModel.getUserInfo()
}
}
}
===========================================================================
Clean架构由Robert.C.Martin(Bob大叔)提出,最基础的Clean架构由Entities(实体层)、Use Cases(用例层)、Interface Adapters(接口适配层)、Frameworks & Drivers(框架驱动层)四部分组成:
-
Entities:用于封装企业业务规则,指业务的核心数据模型和接口,一般情况下不会发生变化,只有当业务规则改变才会改变实体层。
-
Use Cases:用于封装软件应用的业务规则,包含实现整个应用所需全部功能的用例,通过调用各种实体的规则实现用例的功能。用例层的改变不会影响实体层,同时外部UI与数据库的改变也不会影响到用例层。
-
Interface Adapters:用于将外部数据转换为实体层与用例层需要的数据结构或将实体层与用例层返回的数据转换为外部需要的数据结构。Clean-MVP中Presenter就是在这一层。
-
Frameworks & Drivers:由一些框架与工具组成,如数据库、UI框架等。这层更多的是用于编写技术细节,而不需要考虑业务逻辑。
Clean架构通过规范层级间的单向依赖关系,从而形成一层包裹一层的层级结构。如下图所示:
Clean架构的层级并不是固定的。根据不同的业务特点,Clean架构也可有更多的层级(最少四层)。由此可见,Clean架构并非传统意义上的架构,它更像是一种理念。Clean架构可以与MVC架构、MVP架构、MVVM架构结合形成Clean-MVC架构、Clean-MVP架构、Clean-MVVM架构。谷歌官方借鉴Clean的理念推出Clean-MVVM架构。
Clean架构具有单向依赖、层级分明、数据驱动的优点。因此在Clean架构中,各个层级的代码逻辑更容易被测试,缺陷与问题更容易被定位,代码的可读性得到显著提升。Clean架构的结构十分复杂。它被称为洋葱架构,不仅是因为它层层包裹的结构,也是因为当你意识到需要写多层模版代码时,Clean架构会让你哭泣。同时,Clean架构还存在用例层代码复用率低、急剧增加的用例导致类膨胀的问题。
点击按钮从网络获取用户信息,经过解析后展示到界面上。
1)Entities层
data class UserInfo(
var name: String,
var age: Int,
var height: Int,
var weight: Int
)
2)Use Cases层
interface UseCase<T, R> {
fun execute(param: T, callback: R)
}
interface UseCaseCallback<T> {
fun success(data: T)
fun fail(e: Throwable)
}
class GetUserInfoUseCase : UseCase<Unit, UseCaseCallback<UserInfo>> {
private val repository = NetRepository()
override fun execute(param: Unit, callback: UseCaseCallback<UserInfo>) {
repository.getUserInfo(object : NetResponse<UserInfo> {
override fun onSuccess(data: UserInfo) {
callback.success(data)
}
override fun onError(e: Throwable) {
callback.fail(e)
}
})
}
}
3)Interface Adapters层
interface NetResponse<T> {
fun onSuccess(data: T)
fun onError(e: Throwable)
}
class NetRepository {
fun getUserInfo(callback: NetResponse<UserInfo>) {
// 模拟网络获取
val dataStr = getStringFromNet()
val info = dataStr.parseJson<UserInfo>()
return callback.onSuccess(info)
}
}
interface IView {
fun setName(name: String)
fun setAge(age: String)
fun setHeight(height: String)
fun setWeight(weight: String)
}
class Presenter(private val view: IView) : UseCaseCallback<UserInfo> {
private val getUserInfoUseCase = GetUserInfoUseCase()
fun getUserInfo() =
getUserInfoUseCase.execute(Unit, this)
override fun success(data: UserInfo) {
view.setName(data.name)
view.setAge(data.age.toString())
view.setHeight(data.height.toString())
view.setWeight(data.weight.toString())
}
override fun fail(e: Throwable) {
val data = getNetErrorData()
view.setName(data.name)
view.setAge(data.age.toString())
view.setHeight(data.height.toString())
view.setWeight(data.weight.toString())
}
private fun getNetErrorData(): UserInfo {
return UserInfo(name = "", age = 0, height = 0, weight = 0)
}
}
4)Frameworks & Drivers层
class MainActivity : AppCompatActivity(), IView {
private val presenter = Presenter(this)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
btnNet?.setOnClickListener {
presenter.getUserInfo()
}
}
override fun setName(name: String) {
tvName?.text = name
}
override fun setAge(age: String) {
tvAge?.text = age
**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**
**深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**
**因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**
![img](https://img-blog.csdnimg.cn/img_convert/9db48217cf8180dbe20569287b1c0207.png)
![img](https://img-blog.csdnimg.cn/img_convert/9a5dc775dd8b7f80b1de3fa5fba09389.png)
![img](https://img-blog.csdnimg.cn/img_convert/00de664a186716c3a8dc72c00cbdbb17.png)
![img](https://img-blog.csdnimg.cn/img_convert/9eb7c3d283db09924ac18d769857b7e4.png)
![img](https://img-blog.csdnimg.cn/img_convert/91522c2f320bdf379481f51c3e5d3c96.png)
![img](https://img-blog.csdnimg.cn/img_convert/38d60ebad0bb39c2376f0feb7d0f9ef9.png)
![img](https://img-blog.csdnimg.cn/13f2cb2e05a14868a3f0fd6ac81d625c.png)
**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!**
**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**
**如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)**
![img](https://img-blog.csdnimg.cn/img_convert/3a32b104fd40584f188700200dfafc3e.png)
## 最后
最后这里放上我这段时间复习的资料,这个资料也是偶然一位朋友分享给我的,里面包含了腾讯、字节跳动、阿里、百度2020-2021面试真题解析,并且把每个技术点整理成了视频和PDF(知识脉络 + 诸多细节)。
还有 **高级架构技术进阶脑图、高级进阶架构资料** 帮助大家学习提升进阶,这里我也免费分享给大家也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
![](https://img-blog.csdnimg.cn/img_convert/f425e3f6a0710db3499a087f730313c7.webp?x-oss-process=image/format,png)
![](https://img-blog.csdnimg.cn/img_convert/8966a2261f41a3d82110fea6260b0dff.webp?x-oss-process=image/format,png)
**一起互勉~**
> **本文已被[CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》]( )收录**
[**一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!**](https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0)
**AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算**
录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**
**如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)**
[外链图片转存中...(img-f8bPsPYj-1712158913614)]
## 最后
最后这里放上我这段时间复习的资料,这个资料也是偶然一位朋友分享给我的,里面包含了腾讯、字节跳动、阿里、百度2020-2021面试真题解析,并且把每个技术点整理成了视频和PDF(知识脉络 + 诸多细节)。
还有 **高级架构技术进阶脑图、高级进阶架构资料** 帮助大家学习提升进阶,这里我也免费分享给大家也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
[外链图片转存中...(img-uhjJSjpB-1712158913615)]
[外链图片转存中...(img-YsYr3jHL-1712158913615)]
**一起互勉~**
> **本文已被[CODING开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》]( )收录**
[**一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!**](https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0)
**AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算**