我在“Now In Android”中学到的 9 件事

这篇具有很好参考价值的文章主要介绍了我在“Now In Android”中学到的 9 件事。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

我在“Now In Android”中学到的 9 件事

我在“Now In Android”中学到的 9 件事

Now in Android是一款功能齐全的 Android 应用程序,完全使用 Kotlin 和 Jetpack Compose 构建。它遵循 Android 设计和开发最佳实践,旨在为开发人员提供有用的参考。

https://github.com/android/nowinandroid

UI 状态类

sealed interface InterestsUiState {
    object Loading : InterestsUiState

    data class Interests(
        val authors: List<FollowableAuthor>,
        val topics: List<FollowableTopic>
    ) : InterestsUiState

    object Empty : InterestsUiState
}

此类旨在保存屏幕上显示的流数据,这些数据将随时间或事件发生变化,例如:调用 API 显示动作电影的流将需要视图来显示加载屏幕(以防请求花费太长时间)在显示查询结果之前,如果发现异常则显示错误屏幕。

在发现这一点之前,我是这样管理视图模型中屏幕上显示的流数据的:

var authors: LiveData<List<FollowableAuthor>> = MutableLiveData(emptyList())
var topics: LiveData<List<FollowableTopic>> = MutableLiveData(emptyList())

val isLoading = MutableLiveData(true)

val isEmpty: LiveData<Boolean> = authors.switchMap { authors ->
    topics.map { topics ->
        topics.isEmpty() && authors.isEmpty()
    }
}

init {
    viewModelScope.launch {
        authors = authorsRepository.getAuthorsStream()
        topics = topicsRepository.getTopicsStream()
    }.invokeOnCompletion {
        isLoading.value = false
    }
}

现在代码看起来像这样:

val uiState = combine(
    authorsRepository.getAuthorsStream(),
    topicsRepository.getTopicsStream(),
) { availableAuthors, availableTopics ->
    InterestsUiState.Interests(
        authors = availableAuthors,
        topics = availableTopics
    )
}.stateIn(
    scope = viewModelScope,
    started = SharingStarted.WhileSubscribed(5_000),
    initialValue = InterestsUiState.Loading
)

(在这个例子中,我从 LiveData 切换到 StateFlow,但实际上使用“asLiveData()”和“asFlow()”方法仍然很容易互换)
State holder & UI State
https://developer.android.com/topic/architecture/ui-layer/state-production#stream-apis

使用构造函数引用转换流

val myStream = combine(
  followedAuthorIdsStream,
  authorStream,
  ::Pair
)

而不是“手动”映射它…

val myStream = 
combine(
  followedAuthorIdsStream,
  authorStream,
) { followedAuthorIds, author -> 
    Pair(followedAuthorIds, author)
}

“::Class”被称为构造函数引用。构造函数可以像方法和属性一样被引用。您可以在程序需要函数类型对象的任何地方使用它们,该对象采用与构造函数相同的参数并返回适当类型的对象。

轻松将其映射到密封接口结果中

return combine(
  followedAuthorIdsStream,
  authorStream,
  ::Pair
).asResult() // <- The change is here !

因为我们之前将我们的流配对成单个流,所以我们可以将它映射到一个会改变的结果类中,就像UIState类一样,但是以一种更通用的方式,因为 Result.Success将公开一个字段:数据

sealed interface Result<out T> {
    data class Success<T>(val data: T) : Result<T>
    data class Error(val exception: Throwable? = null) : Result<Nothing>
    object Loading : Result<Nothing>
}

Flow上的 Kotlin 扩展可自动映射到Result

fun <T> Flow<T>.asResult(): Flow<Result<T>> {
    return this
        .map<T, Result<T>> {
            Result.Success(it)
        }
        .onStart { emit(Result.Loading) }
        .catch { emit(Result.Error(it)) }
}

将其映射到 UI 状态类中

return combine(
  followedAuthorIdsStream,
  authorStream,
  ::Pair
).asResult()
.map { followedAuthorToAuthorResult ->
    when (followedAuthorToAuthorResult) {
        is Result.Success -> {
            val (followedAuthors, author) = followedAuthorToAuthorResult.data
            AuthorUiState.Success()
        }
        is Result.Loading -> AuthorUiState.Loading
       
        is Result.Error -> AuthorUiState.Error
    }
}

使用生命周期安全方法搜集状态

val uiState by viewModel.uiState.collectAsStateWithLifecycle()

我正在使用 collectAsState() 并且没有注意到生命周期版本已经结束。

collectAsState()方法的提醒:

@Composable
public fun <T> StateFlow<T>.collectAsState(
 context: CoroutineContext
): State<T>

从此 StateFlow 收集值并通过 State 表示其最新值。StateFlow.value 用作初始值。每次有新值发布到 StateFlow 时,返回的 State 都会更新,从而导致每个 State.value 用法的重组。

Composable 中的方法引用

@Composable
fun MyScreen(viewModel: ForYouViewModel) {

  ForYouScreen(
      onTopicCheckedChanged = viewModel::updateTopicSelection,
      onAuthorCheckedChanged = viewModel::updateAuthorSelection,
      saveFollowedTopics = viewModel::saveFollowedInterests,
      onNewsResourcesCheckedChanged = viewModel::updateNewsResourceSaved,
  )
}

这使代码更具可读性,特别是在这里,您的眼睛需要关注 UI。
调用参考:

@Composable
fun MyScreen(viewModel: ForYouViewModel) {

  ForYouScreen(
      onTopicCheckedChanged = { topicId, isChecked ->
        viewModel.updateTopicSelection(topicId = topicId, isChecked = isChecked)
      },
      onAuthorCheckedChanged = { authorId, isChecked ->
        viewModel.updateAuthorSelection(authorId = authorId, isChecked = isChecked)
      },
      saveFollowedTopics = { viewModel.saveFollowedInterests() },
      onNewsResourcesCheckedChanged = { newsResourceId, isChecked ->
        viewModel.updateNewsResourceSaved(
           newsResourceId = newsResourceId,
           isChecked = isChecked
        )
     },
  )
}

多预览的注解

表示各种设备尺寸的多预览的注解。将此注解添加到Composable以呈现各种设备。

@Preview(name = "phone", device = "spec:shape=Normal,width=360,height=640,unit=dp,dpi=480")
@Preview(name = "landscape", device = "spec:shape=Normal,width=640,height=360,unit=dp,dpi=480")
@Preview(name = "foldable", device = "spec:shape=Normal,width=673,height=841,unit=dp,dpi=480")
@Preview(name = "tablet", device = "spec:shape=Normal,width=1280,height=800,unit=dp,dpi=480")
annotation class DevicePreviews

我在“Now In Android”中学到的 9 件事
Multipreview注解表示不同设备尺寸的多个预览。可以将这个注解添加到Compose中的某个组件上,以在不同设备上渲染多个预览界面。

我在“Now In Android”中学到的 9 件事

Android允许您通过继承IssueRegistry来创建自定义lint规则,示例如下(我不会解释如何做,因为我在我的项目中还没有成功地让它正常工作):

class DesignSystemIssueRegistry : IssueRegistry()

在最新的Android版本中,他们创建了一个类来检查是否使用了他们自定义的组件而不是通用的组件。以下是他们编写的代码片段:

class DesignSystemDetector : Detector(), Detector.UastScanner {

  ...

  val METHOD_NAMES = mapOf(
            "MaterialTheme" to "NiaTheme",
            "Button" to "NiaFilledButton",
            "OutlinedButton" to "NiaOutlinedButton",
            ...
            )
}

我发现这对不知道项目中已经存在特定组件的新开发人员很有用。

Composable 扩展

它只适用于 LazyListScopeColumnScope ……不适用于 @Composable

fun LazyListScope.MyItem() {
  item {
    // Your Composable
  }
}

@Composable
fun MyList() {
  LazyColumn {
    MyItem()
  }
}

我发现这很有用,例如:在多个屏幕上共享可组合的粘性标头。

先前:

@Composable
fun MyStickyHeader() {
  // Composable
}

@Composable
fun MyList() {
  LazyColumn {
    stickyHeader {
      MyStickyHeader()
    }
  }
}

之后:

fun LazyListScope.MyStickyHeader() {
  stickyHeader {
    // Composable
  }
}

@Composable
fun MyList() {
  LazyColumn {
    MyStickyHeader()
  }
}

参考链接

https://medium.com/@romeo.prosecco/top-things-i-learned-on-now-in-android-dba991da1c0文章来源地址https://www.toymoban.com/news/detail-421509.html

到了这里,关于我在“Now In Android”中学到的 9 件事的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 我在使用arduino编译时报错:exec: “cmd“: executable file not found in %PATH%

    真是气死我了,第一次因为一个错误搞半天,所以在这里把答案告诉大家,省的和我一样烦躁 我遇到了exec: “cmd”: executable file not found in %PATH%这个报错,然后使用的的板子是esp32,之前8266没有遇到这样的错误,找了好多答案都是说在环境变量path里加入“C:WindowsSystem32cmd.

    2024年02月14日
    浏览(21)
  • 如何让电脑永不息屏?Python:这事我熟,只需5行代码...

    最近新来的小老弟问我,按照公司规定,电脑只有十分钟就锁屏,但是他不想让电脑在空闲十分钟后锁屏。 于是我问他,是不是想挑战一下公司信息安全? 不过小老弟很机智,来了句公司信息安全大于天,他就是想让自己多学点知识 ~ 既然他都这么说了,我就勉为其难的教

    2024年02月09日
    浏览(30)
  • 查询练习:YEAR 与 NOW 函数

    查询  student  表中每个学生的姓名和年龄。

    2023年04月22日
    浏览(25)
  • 可以让ChatGPT干的100件事举例

    还不知道让ChatGPT干点什么来搞钱?以下给出100个例子: 回答数学问题 编辑和校对文本 教授新技能和知识 协助组织和规划行程 制作和编辑视频 管理社交媒体账户 收集数据和分析数据 为您做市场调研 设计和制作海报和宣传资料 为您做市场营销和品牌推广 为您编写商业计划

    2023年04月20日
    浏览(30)
  • 为了开放互联,明道云做了十件事

    本文来自明道云资深研发经理孙伟,在明道云2022年秋季伙伴大会活动演讲,经校对编辑后整理为演讲精华。 很多客户选择我们的一个重要原因,是明道云所能提供的产品开放能力。开放其实是没有选择的,坦白来讲,我也不希望开放,我希望客户所有的业务系统都用明道云

    2024年02月03日
    浏览(20)
  • 大语言模型学到什么

    这篇文章是对《LANGUAGE MODELS REPRESENT SPACE AND TIME》论文的翻译加解读。之所以选这篇文章是因为最近在研究大模型的可解释性,以及基于可解释性对大模型的下游任务适配做训练级别可控性增强研究。其实总结成两句话就是: 1.大模型到底学到什么了 2.是否能够在训练时候通过

    2024年02月07日
    浏览(72)
  • CentOS7重启指令(重启命令)reboot、shutdown -r now(立即重启服务器)、shutdown -h now(立即关机、关闭服务器)

    参考文章:CentOS 几种重启方式的区别 立即关机: 20230816 CentOS是一个基于Red Hat Enterprise Linux (RHEL)的免费开源操作系统。本文将深入介绍如何使用不同的命令在CentOS 7上进行系统重启和关机。 1.1 reboot 命令 在CentOS 7中,最直接也最常用的重启命令就是 reboot 。 这个命令会立即重

    2024年02月11日
    浏览(46)
  • 第一件事 什么是 Java 虚拟机 (JVM)

    1、什么是虚拟机? - 这个其实是一个挺逗的事情,说白了,就是基于某个硬件架构,在这个硬件部署了一个操作系统,再构架一层虚拟的操作系统,这个新构架的操作系统就是虚拟机。 不知道的兄弟姐妹们,可以去看看 VMWARE 这个软件,它可以在很多常用操作系统上面构建很

    2024年02月21日
    浏览(36)
  • 软件测试风险管理需要做的3件事

    众所周知,软件测试作为软件研发中不可或缺的一部分。但是,软件测试不仅仅是查找和修复错误,它还涉及风险的识别和应对。 当领导问你,这个需求能否按时交付?这个版本能否准时发版?是否有延期风险?你又该如何回答呢。 因此,风险管理(Risk Management)也是软件

    2024年02月01日
    浏览(47)
  • 第二件事 在Java 虚拟机 (JVM)跑一个程序

    上篇文章写了 在 WINDOWS上 创建了一个 JVM, 好! 现在在这个 Java 虚拟计算机系统上跑一个Java语言编写的小程序; 题目: 用Java语言 编写一个小程序 在Console界面 打印 整数 1-10 (回头了一下源程序,靠,应该打印的是 10-19 :)) 1、定义文件名 Test.java  这个文件中用Java语言编

    2024年02月20日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包