Android Jetpack 应用指南(一) - LiveData

简介:

前言

从事Android开发两年有余了,从15年开始学习Android,到17年开始实际接触企业级Android APP的开发,这一路也从MVC走到了MVP。19年辞职后,休息期间研究了一下最新的Android Jetpack,萌生了一个大胆的想法——计划使用当前各类成熟的框架和技术如组件化、插件化、MVVM等等,结合AAC开发出一个自己之前从未走过的Android开发之路。

本篇文章是LiveData的初探,会用尽可能简洁的方式来了解LiveData,让我们对LiveData有一个初步印象,不会长篇大论或者源码轰炸,导致干货太多引起阅读困难。

目录

  • LiveData生命周期与简介
  • LiveData的使用
  • LiveDataAPI介绍
  • LiveData的扩展
  • LiveData数据转换

正文

LiveData简介

LiveData的官方文档是这样介绍它的,
LiveData是一种具有生命周期感知能力的可观察数据持有类。
从它介绍中我们可以知道,LiveData是一个持有数据的类,同时可以感知Activity或Fragment的生命周期,并且支持观察者模式。

LiveData的使用

根据官方的介绍,可以按照以下的步骤来使用LiveData

1.创建一个LiveData的实例来保存特定类型的数据。 一般会把LiveData的实例定义在ViewModel类中。

    val name: MutableLiveData<String> by lazy {
        MutableLiveData<String>()
    }

MutableLiveData是LiveData的一个子类,LiveData是一个抽象类,实例化LiveData需要使用MutableLiveData。

2.创建一个定义了onChanged()方法的Observer对象,当LiveData对象保存的数据发生变化时,onChanged()方法可以进行相应的处理。

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        //创建viewmodel
        mViewModel = ViewModelProviders.of(this).get(LiveDataViewModel::class.java)

        //声明观察TextView对象,
        mViewModel.name.observe(this, Observer {
            //实现onChanged()方法,这里使用了lambda表达式,省略了onChanaged()
            textview.text = it
        })

    }

通常在UI控制器(如Activity或Fragment)中创建Observer对象。

3.调用LiveData的observe()方法需要传入两个参数,第一个参数LifecycleOwner对象,LifecycleOwner是一个接口,只要UI控制器实现了该接口,可以直接传this,Android中的Fragment和AppCompatActivity的父类都已经实现LifecycleOwner接口。第二个参数是Observer观察者,属于方法回调。

更新LiveData数据

MutableLiveData提供了两个更新数据的方法

  • postValue(value: T)
  • setValue(value: T)

两个方法都可以用来更新LiveData中数据,区别在与postValue可以在子线程中更新LiveData的数据,而setValue只能在UI线程中更新LiveData的数据。

注意: UI控制器(activity和fragment)只应该负责显示数据,不应该保存任何数据,所以不要在UI控制器中创建LiveData的实例。

LiveDataAPI介绍

getValue():T

返回LiveData当前的存储的值

hasActiveObservers():Boolean

如果当前的LiveData存在活跃的Observer对象,则返回true

hasObservers():Boolean

如果当前的LiveData存在Observer对象,则返回true

observe(@NonNull owner: LifecycleOwner, @NonNull observer: Observer)

将给定的观察者添加到给定所有者的生命周期内的观察者列表中。

observeForever(@NonNull observer: Observer)

注册一个没有关联LifecycleOwner对象的Observer。 在这种情况下,Observer被认为始终处于活动状态,因此当有数据变化时总是会被通知。 可以调用removeObserver(Observer)方法移除这些Observer。

removeObserver(@NonNull observer: Observer)

从观察者列表中删除给定的观察者。

removeObservers(@NonNull owner: LifecycleOwner)

删除与给定关联的所有观察者LifecycleOwner。

LiveData的扩展

LiveData的扩展千变万化,这里只介绍LiveData的源码中预留的两个空实现方法的扩展

  • onActive()

当LiveData对象有一个活跃的Observer时,onActive()方法被调用。

  • onInactive()

当LiveData对象没有任何活跃的Observer时,onInactive()方法被调用。

通过onActive和onInactive方法我们可以很轻松的知道当前LiveData对象是否有正在活跃的观察者对象,并根据业务逻辑作出合适的调整。

LiveData对象具有感知生命周期的能力意味着可以在多个Activity,Fragment和service之间共享它们。 为了保持简洁,可以使用单例模式实现LiveData

class ExpandLiveData :LiveData<String>() {


    companion object {
      private lateinit var sInstance: ExpandLiveData

        @MainThread
        fun get(): ExpandLiveData {
            sInstance = if (::sInstance.isInitialized) sInstance else ExpandLiveData()
            return sInstance
        }
    }

    //当活动的观察者数量从0变为1时调用。
    override fun onActive() {
        super.onActive()
    }

    //当活动的观察者数量从1变为0时调用。
    override fun onInactive() {
        super.onInactive()
    }


}

在activity中就可以用如下的方式调用

    ExpandLiveData.get().observe(this, Observer {
        //doSomething
    })

LiveData的数据转换

通过上述的介绍,我们对LiveData有了一个初步的印象,LiveData是一个可以感知生命周期的的数据持有类,同时支持观察者模式。说到观察者模式,我们一定会联想到Rxjava,Rxjava中提供了多种多样的操作符,极大的便利了Android开发。LiveData的开发者们同样也给LiveData带来了与Rxjava类似的多种操作符。
与Rxjava不同的是,在LiveData中需要借助Transformations类来完成LiveData的数据转换

  • map(liveData,function)

map操作符,与rxjava的map操作符语义非常相似,可修改LiveData的输出值。map方法有两个参数,第一个参数是需要转换的LiveData源,第二个参数是自定义的转换方法。示例如下:

    val newLiveData = Transformations.map(ExpandLiveData.get()) { string ->
        //把转换前的livedata的value加了一个new
        "new$string"
    }

    newLiveData.observe(this, Observer { string ->
        Log.e("newLiveData", string)
    })

    ExpandLiveData.get().observe(this, Observer { string ->
        Log.e("ExpandLiveData", string);
    })

输出结果:

E/newLiveData: newExpand
E/ExpandLiveData: Expand
  • switchMap

switchMap与map相似,区别在于:map给出的是具体的值,而switchMap给出的是具体的LiveData。

举个例子:有这样一个方法getUser(Id),通过传入用户的Id,来查找用户的具体信息,并返回一个LiveData<User>对象。当界面传入的用户Id发生变化时,需要根据Id重新查找用户的LiveData,这时就需要解除上一个LiveData关联界面UI信息,绑定新的UI消息。如果我们使用switchMap,就可以避免重复的解绑和绑定操作。示例如下:

    //模拟查找用户的操作,这里重新生成了一个UserLiveData
    fun getUser(id: String): MutableLiveData<String> {
        //返回查到的UserLiveData,value是固定link加上用户的Id,例如:userId=1000,返回值就是link-1000
        val userLiveData=MutableLiveData<String>()
        userLiveData.value="link-${id}"
        return userLiveData
    }

    //用一个按钮来模拟修改UserId
    button.setOnClickListener {
        //通过随机数动态修改userId
        userIdLiveData.value = Random.nextInt(0, 10000).toString()
    }

    //通过switchMap动态返回不同Id的UserLiveData
    val userIdLiveData = MutableLiveData<String>()
    Transformations.switchMap(userIdLiveData) { userId ->
        Log.e("switchMap", userId)
        getUser(userId)
    }.observe(this, Observer {
        //输出当前getUser()中返回的UserLiveData的值
         Log.e("userLiveData", it)
    })

输出结果:

E/switchMap: 9320
E/userLiveData: link-9320
E/switchMap: 7116
E/userLiveData: link-7116

通过上面例子我们可以看到,不管需要查找多少个用户的LiveData,界面都只需要观察生成的LiveData一次即可。

  • MediatorLiveData

如果map和switchMap都不能满足你对数据格式转换的需求,那么还可以使用MediatorLiveData进行自定义的数据转换。

MediatorLiveData是LiveData的一个子类,它可以添加或者移除多个源LiveData对象,将多个源LiveData对象组合一个单一的LiveData对象。任何LiveData源对象发生改变后,MediatorLiveData的Observer都会被触发。

上面的map和switchMap的底层实现实际上也是使用了MediatorLiveData,我们可以简单看一下map的源码,来对MediatorLiveData的使用又一个大致的了解。

    @MainThread
    public static <X, Y> LiveData<Y> map(
            @NonNull LiveData<X> source,
            @NonNull final Function<X, Y> mapFunction) {
        final MediatorLiveData<Y> result = new MediatorLiveData<>();
        result.addSource(source, new Observer<X>() {
            @Override
            public void onChanged(@Nullable X x) {
                result.setValue(mapFunction.apply(x));
            }
        });
        return result;
    }

MediatorLiveData的使用暂时先不介绍,我们只需要对它有个大致的了解,具体的细节,会在后续的文章中介绍。

总结

本篇文章的简要介绍了LiveData是什么,以及如何使用LiveData。其实只要记住LiveData本质上就是一个可以感知生命周期的数据持有类,支持观察者模式,就可以了,其他的细节几乎都是对其特性的扩展。当我们记牢LiveData的特性后,或许就不会在开发中产生“我为毛要使用LiveData”的疑问了。

在AAC架构中LiveData和ViewModel占据了很重要的位置,下一篇我们再来介绍ViewModel。

目录
相关文章
|
1月前
|
开发框架 前端开发 Android开发
Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势
本文深入探讨了 Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势。这对于实现高效的跨平台移动应用开发具有重要指导意义。
166 4
|
22天前
|
JSON Java API
探索安卓开发:打造你的首个天气应用
在这篇技术指南中,我们将一起潜入安卓开发的海洋,学习如何从零开始构建一个简单的天气应用。通过这个实践项目,你将掌握安卓开发的核心概念、界面设计、网络编程以及数据解析等技能。无论你是初学者还是有一定基础的开发者,这篇文章都将为你提供一个清晰的路线图和实用的代码示例,帮助你在安卓开发的道路上迈出坚实的一步。让我们一起开始这段旅程,打造属于你自己的第一个安卓应用吧!
49 14
|
25天前
|
Java Linux 数据库
探索安卓开发:打造你的第一款应用
在数字时代的浪潮中,每个人都有机会成为创意的实现者。本文将带你走进安卓开发的奇妙世界,通过浅显易懂的语言和实际代码示例,引导你从零开始构建自己的第一款安卓应用。无论你是编程新手还是希望拓展技术的开发者,这篇文章都将为你打开一扇门,让你的创意和技术一起飞扬。
|
23天前
|
搜索推荐 前端开发 测试技术
打造个性化安卓应用:从设计到开发的全面指南
在这个数字时代,拥有一个定制的移动应用不仅是一种趋势,更是个人或企业品牌的重要延伸。本文将引导你通过一系列简单易懂的步骤,从构思你的应用理念开始,直至实现一个功能齐全的安卓应用。无论你是编程新手还是希望拓展技能的开发者,这篇文章都将为你提供必要的工具和知识,帮助你将创意转化为现实。
|
23天前
|
Java Android开发 开发者
探索安卓开发:构建你的第一个“Hello World”应用
在安卓开发的浩瀚海洋中,每个新手都渴望扬帆起航。本文将作为你的指南针,引领你通过创建一个简单的“Hello World”应用,迈出安卓开发的第一步。我们将一起搭建开发环境、了解基本概念,并编写第一行代码。就像印度圣雄甘地所说:“你必须成为你希望在世界上看到的改变。”让我们一起开始这段旅程,成为我们想要见到的开发者吧!
31 0
|
1月前
|
JSON Java Android开发
探索安卓开发之旅:打造你的第一个天气应用
【10月更文挑战第30天】在这个数字时代,掌握移动应用开发技能无疑是进入IT行业的敲门砖。本文将引导你开启安卓开发的奇妙之旅,通过构建一个简易的天气应用来实践你的编程技能。无论你是初学者还是有一定经验的开发者,这篇文章都将成为你宝贵的学习资源。我们将一步步地深入到安卓开发的世界中,从搭建开发环境到实现核心功能,每个环节都充满了发现和创造的乐趣。让我们开始吧,一起在代码的海洋中航行!
|
1月前
|
存储 搜索推荐 Java
打造个性化安卓应用:从设计到实现
【10月更文挑战第30天】在数字化时代,拥有一个个性化的安卓应用不仅能够提升用户体验,还能加强品牌识别度。本文将引导您了解如何从零开始设计和实现一个安卓应用,涵盖用户界面设计、功能开发和性能优化等关键环节。我们将以一个简单的记事本应用为例,展示如何通过Android Studio工具和Java语言实现基本功能,同时确保应用流畅运行。无论您是初学者还是希望提升现有技能的开发者,这篇文章都将为您提供宝贵的见解和实用的技巧。
|
7月前
|
移动开发 安全 Android开发
构建高效Android应用:Kotlin协程的实践与优化策略
【5月更文挑战第30天】 在移动开发领域,性能优化始终是关键议题之一。特别是对于Android开发者来说,如何在保证应用流畅性的同时,提升代码的执行效率,已成为不断探索的主题。近年来,Kotlin语言凭借其简洁、安全和实用的特性,在Android开发中得到了广泛的应用。其中,Kotlin协程作为一种新的并发处理机制,为编写异步、非阻塞性的代码提供了强大工具。本文将深入探讨Kotlin协程在Android开发中的应用实践,以及如何通过协程优化应用性能,帮助开发者构建更高效的Android应用。
|
7月前
|
API 调度 Android开发
打造高效Android应用:探究Kotlin协程的优势与实践
【5月更文挑战第27天】在移动开发领域,性能优化和响应速度是衡量应用质量的关键因素。随着Kotlin语言的普及,协程作为其核心特性之一,为Android开发者提供了一种全新的并发处理方式。本文深入探讨了Kotlin协程在Android应用开发中的优势,并通过实例演示如何在实际项目中有效利用协程提升应用性能和用户体验。
|
7月前
|
移动开发 Android开发 开发者
构建高效Android应用:探究Kotlin协程的优势与实践
【5月更文挑战第21天】在移动开发领域,性能优化和流畅的用户体验是至关重要的。随着Kotlin语言在Android平台的广泛采纳,其并发处理的强大工具—协程(Coroutines),已成为提升应用响应性和效率的关键因素。本文将深入分析Kotlin协程的核心原理,探讨其在Android开发中的优势,并通过实例演示如何有效利用协程来优化应用性能,打造更加流畅的用户体验。
74 4