先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
如果你需要这些资料,可以添加V获取:vip204888 (备注Android)
正文
- activity 中观察数据更新 ui 代码
val countDownModel: CountDownModel by viewModels {
ViewModelProvider.NewInstanceFactory()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_count_down)
countDownModel.countDownLivedata.observe(this, object : Observer {
override fun onChanged(value: String?) {
value?.let {
tv_countdown_remainsecond.text = it
}
}
})
}
复制代码
- 效果图
使用全局 Livedata 在多个视图监听状态
本例实现的 demo 效果是,创建一个全局的倒计时,然后在 Activity 中添加两个按钮,点击后可以切换 FragmentA 和 FragmentB。然后我们通过全局的自定义 LiveData 单例实现数据监听,切换 Fragment 后 Fragment 页面上会展示倒计时的剩余秒数
代码:
- 全局自定义 Livedata 代码
class GlobalLivedata : LiveData() {
val coundManager = CountDownManager()
val listener = object : OnDataChangeListener {
override fun change(data: String) {
postValue(data)
}
}
override fun onActive() {
super.onActive()
coundManager.setListener(listener)
}
override fun onInactive() {
super.onInactive()
coundManager.removeListener(listener)
}
companion object {
private lateinit var globalData: GlobalLivedata
fun getInstance(): GlobalLivedata {
globalData = if (::globalData.isInitialized) globalData else GlobalLivedata()
return globalData
}
}
}
复制代码
- 倒计时器代码较长只粘贴一部分,有兴趣可以到 github 去查看完整代码
private val listeners = mutableListOf()
init {
val countDown = object : CountDownTimer(2000 * 1000, 1000) {
override fun onTick(millisUntilFinished: Long) {
remainSecond–
callback(“剩余:${remainSecond} 秒”)
}
override fun onFinish() {
callback(“倒计时结束”)
}
}
countDown.start()
}
/**
- 循环遍历回调消息
*/
private fun callback(msg:String) {
for (listener in listeners){
listener.change(msg)
}
}
复制代码
- FragmentA、FragmentB 中监听倒计时状态
GlobalLivedata.getInstance().observe(viewLifecycleOwner,
{ t ->
inflate.findViewById(R.id.tv_fragmentA).text = “fragmenta:${t}”
})
复制代码
GlobalLivedata.getInstance().observe(viewLifecycleOwner,
{ t ->
inflate.findViewById(R.id.tv_fragmentB).text = “fragmentb:${t}”
})
复制代码
- 最终效果
最终效果,当我们切换 Fragment 的时候两个 Fragment 显示的秒数是一致的,其实即使我们马上启动一个新 activity 去查看剩余秒数也是一样的,有兴趣的朋友可以下载 git 代码自己尝试
对 Livedata 进行转换
map 和 switchMap 两个方法可以对已有的 Livedata 进行转换得到新的 Livedata
Transformation.map
在 activity 中观察 viewmodel 中的数据更新,当点击 activity 中按钮的时候会调用 viewmodel.sendData 方法发送数据,然后发送的数据会做一定的转换给 activity,然后 activity 打印日志展示
直接看代码吧:
- 创建 viewmodel,model 中创建 Livedata
class TransMapViewModel: ViewModel() {
fun sendData() {
userLivedata.value=User(“李白”,1200)//对userLivedata进行复制
}
val userLivedata =MutableLiveData()
val mapLiveData = Transformations.map(userLivedata){
“${it.name} : ${it.age}”//这里可以返回任意类型的数据
}
}
data class User(var name:String,var age:Int)
复制代码
代码中 mapLiveData 是对 userLivedata 进行转换得到的,所以当我们调用 sendData 方法更新 userLivedata 中的方法时,mapLiveData 的回调也会触发
- 在 activity 中观察 mapLiveData 并点击按钮发送小数据
mapViewModel.mapLiveData.observe(this,{
logEE(it)
tv_map.text=it
})
btn_map.setOnClickListener {
mapViewModel.sendData()
}
复制代码
Transformation.switchMap
本例中我们实现如下逻辑:
在 activity 中观察 viewmodel 中的数据更新,当点击 activity 中按钮的时候会调用 viewmodel.sendData 方法发送数据,然后发送的数据会做一定的转换给 activity,然后 activity 打印日志展示
- viewmodel 中代码
class SwitchMapViewModel : ViewModel() {
fun sendData() {
userLivedata.value = SwitchUser(“李白”, 1200)
}
private val userLivedata = MutableLiveData()
val mapLiveData = Transformations.switchMap(userLivedata) {
changeUser(it!!)
}
private fun changeUser(it: SwitchUser): LiveData {
return MutableLiveData(“${it.name} 的名字杜甫知道”)
}
}
data class SwitchUser(var name: String, var age: Int)
复制代码
- 调用部分代码
model.mapLiveData.observe(this, {
logEE(it)
})
btn_switchmap.setOnClickListener {
model.sendData()
}
复制代码
合并两个 Livedata(MediatorLiveData)
想象这样一个场景,您的 app 里面有一个评论列表的功能,可以对列表内容进行点赞。每一个点赞都是一个异步任误,你的产品需求并不想让用户点太多赞,比如一分钟点赞数量不能超过 10 次,这种场景就很适合用 Livedata 的合并功能
我们就不模拟这么复杂的场景了,我们的例子做这样一个事情:
界面上有两个按钮,点一次相当于点赞一次,我们点击十次按钮就在界面上展示文字提示用户已经点击了十次数据。
代码展示:
1.model 代码
class MeditorLiveViewModel : ViewModel() {
var count =0//计数字段
fun setData1(name: String) {
liveData1.value = name
}
fun setData2(age: Int) {
liveData2.value = age
}
private val liveData1 = MutableLiveData()
private val liveData2 = MutableLiveData()
val liveCombind = MediatorLiveData()
init {
liveCombind.addSource(liveData1) {
increase()
}
liveCombind.addSource(liveData2) {
increase()
}
}
private fun increase() {
count++
if(count==10){
liveCombind.value=“安安安安卓同学,您已经点击 ${count}次,再点我也不跟你玩了,收手吧。。。”
}
}
}
复制代码
model 中创建了三个 Livedata,其中两个分别是 livedata1 和 livedata2,分别对应其中两个按钮。
还有一个 liveCombind 用来回调超过十次调用的场景
init 方法中 liveCombind.addSource 调用就是表示用来中间拦截 livedata1 和 livedata2 的数据更新,处理 count 累加和是否回调 liveCombind 的功能
总结
最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的Android开发中高级必知必会核心笔记,共计2968页PDF、58w字,囊括Android开发648个知识点,我把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
2021年虽然路途坎坷,都在说Android要没落,但是,不要慌,做自己的计划,学自己的习,竞争无处不在,每个行业都是如此。相信自己,没有做不到的,只有想不到的。
虽然面试失败了,但我也不会放弃入职字节跳动的决心的!建议大家面试之前都要有充分的准备,顺顺利利的拿到自己心仪的offer。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注Android)
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-w3LK2Q9z-1713650340566)]
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
2021年虽然路途坎坷,都在说Android要没落,但是,不要慌,做自己的计划,学自己的习,竞争无处不在,每个行业都是如此。相信自己,没有做不到的,只有想不到的。
虽然面试失败了,但我也不会放弃入职字节跳动的决心的!建议大家面试之前都要有充分的准备,顺顺利利的拿到自己心仪的offer。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注Android)
[外链图片转存中…(img-47NhHRgi-1713650340567)]
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!