在 Android 开发中使用常见的 Kotlin 模式

Android第一行代码——快速入门 Kotlin 编程( 5.2 Fragment 的使用方式) 说实在的,这个问题并没有看上去那么复杂,它的基本思路非常简单:首先在一个Fragment 中可以得到与它相关联的 Activity ,然后再通过这个 Activity 去获取另外一个 Fragment 的实例, 这样就实现了不同 Fragment 之间的通信功能。在上一节当中,你已经学会了在布局文件中添加 Fragment 的方法,不过 Fragment 真正的强大之处在于,它可以在程序运行时动态地添加到 Activity 当中。介绍了这么多抽象的东西,是时候学习一下 Fragment 的具体用法了。 阅读详情

在 Android 开发中使用常见的 Kotlin 模式

介绍 Kotlin 语言在 Android 开发过程中最有用的一些方面

使用 Fragment
继承

LoginFragment 是 Fragment 的子类,在子类与其父类之间使用 : 运算符指示继承:

class LoginFragment : Fragment()

在 LoginFragment 中,您可以替换许多生命周期回调以响应 Fragment 中的状态变化。如需替换函数,请使用 override 关键字,如以下示例所示:

override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
): View? {
    return inflater.inflate(R.layout.login_fragment, container, false)
}

如需引用父类中的函数,请使用 super 关键字,如以下示例所示:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
}
可为 null 性和初始化

在前面的示例中,被替换的方法中某些参数的类型以问号 ? 为后缀。这表示为这些参数传递的实际参数可以为 null。请务必安全地处理其可为 null 性

在 Kotlin 中,您必须在声明对象时初始化对象的属性。这意味着,当您获取类的实例时,可以立即引用它的任何可访问属性。不过,在调用 Fragment#onCreateView 之前,Fragment 中的 View 对象尚未准备好进行扩充,所以您需要一种方法来推迟 View 的属性初始化

可以使用 lateinit 推迟属性初始化。使用 lateinit 时,您应尽快初始化属性

如何使用 lateinit 在 onViewCreated 中分配 View 对象:

private lateinit var usernameEditText: EditText
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        usernameEditText = view.findViewById(R.id.username_edit_text)       
    }

注意:如果您在初始化属性之前对其进行访问,Kotlin 会抛出 UninitializedPropertyAccessException

SAM转换(Single Abstract Method)

Button 对象包含一个 setOnClickListener() 函数,该函数接受 OnClickListener 的实现

OnClickListener 具有单一抽象方法 onClick(),您必须实现该方法。因为 setOnClickListener() 始终将 OnClickListener 当作参数,又因为 OnClickListener 始终都有相同的单一抽象方法,所以此实现在 Kotlin 中可以使用匿名函数来表示。此过程称为单一抽象方法转换或 SAM 转换,SAM 转换可使代码明显变得更简洁。以下示例展示了如何使用 SAM 转换来为 Button 实现 OnClickListener:

binding.loginButton.setOnClickListener {
    Toast.makeText(activity, "click me", Toast.LENGTH_LONG).show()
}

当用户点击 loginButton 时,系统会执行传递给 setOnClickListener() 的匿名函数中的代码。

伴生对象

伴生对象提供了一种机制,用于定义在概念上与某个类型相关但不与某个特定对象关联的变量或函数。伴生对象类似于对变量和方法使用 Java 的 static 关键字

在以下示例中,TAG 是一个 String 常量。您不需要为每个 LoginFragment 实例定义一个唯一的 String 实例,因此您应在伴生对象中定义它:

class LoginFragment : Fragment() {

    ...

    companion object {
        private const val TAG = "LoginFragment"
    }
}

您可以在文件的顶级定义 TAG,但文件中可能有大量的变量、函数和类也是在顶级定义的。伴生对象有助于连接变量、函数和类定义,而无需引用该类的任何特定实例

每个类仅允许存在一个伴生对象

属性委托

初始化属性时,您可能会重复 Android 的一些比较常见的模式,例如在 Fragment 中访问 ViewModel。为避免过多的重复代码,您可以使用 Kotlin 的属性委托语法。

private val viewModel: LoginViewModel by viewModels()

属性委托提供了一种可在您的整个应用中重复使用的通用实现。Android KTX 为您提供了一些属性委托。例如,viewModels 可检索范围限定为当前 Fragment 的 ViewModel

属性委托使用反射,这样会增加一些性能开销。这种代价换来的是简洁的语法,可让您节省开发时间

可为 null 性

Kotlin 提供了严格的可为 null 性规则,可在您的整个应用中维护类型安全。在 Kotlin 中,默认情况下,对对象的引用不能包含 null 值。如需为变量赋 null 值,必须通过将 ? 添加到基本类型的末尾以声明可为 null 变量类型

name 的类型为 String,不可为 null:

val name: String = null

如需允许 null 值,必须使用可为 null String 类型 String?,如以下示例所示:

val name: String? = null
互操作性
平台类型

如果您使用 Kotlin 引用在 Java Account 类中定义的不带注解的 name 成员,编译器将不知道 String 映射到 Kotlin 中的 String 还是 String?。这种不明确性通过平台类型 String! 表示。

String! 对 Kotlin 编译器而言没有特殊的含义。String! 可以表示 String 或 String?,编译器可让您赋予任一类型的值。请注意,如果您将类型表示为 String 并赋予 null 值,则系统可能会抛出 NullPointerException。

为了解决此问题,每当您用 Java 编写代码时,都应使用可为 null 性注解。这些注解对 Java 和 Kotlin 开发者都有帮助。

下面是在 Java 中定义的 Account 类:

public class Account implements Parcelable {
    public final String name;
    public final String type;
    private final @Nullable String accessId;

    ...
}

其中一个成员变量 accessId 带有 @Nullable 注解,这表示它可以持有 null 值。于是,Kotlin 会将 accessId 视为 String?。

如需指明变量绝不能为 null,请使用 @NonNull 注解:

public class Account implements Parcelable {  public final @NonNull String name;  ...}

在这种情况下,name 在 Kotlin 中被视为不可为 null String。

可为 null 性注解包含在所有新增的 Android API 以及许多现有的 Android API 中。许多 Java 库已添加可为 null 性注解,以便为 Kotlin 和 Java 开发者提供更好的支持

处理可为 null 性

如果您不确定 Java 类型,则应将其视为可为 null。例如,Account 类的 name 成员不带注解,因此您应假定它是一个可为 null String。

如果 name 以使其值不包含尾随空格,则可以使用 Kotlin 的 trim 函数

如何安全的处理String?

使用非 null 断言运算符 !!
val account = Account("name", "type")
val accountName = account.name!!.trim()

!! 运算符将其左侧的所有内容视为非 null,因此,在本例中,应将 name 视为非 null String。如果它左侧表达式的结果为 null,则您的应用会抛出 NullPointerException。此运算符简单快捷,但应谨慎使用,因为它会将 NullPointerException 的实例重新引入您的代码

有没有更安全的呢?

使用安全调用运算符 ?.
val account = Account("name", "type")
val accountName = account.name?.trim()

使用安全调用运算符时,如果 name 不为 null,则 name?.trim() 的结果是一个不带前导或尾随空格的名称值。如果 name 为 null,则 name?.trim() 的结果为 null。这意味着,在执行此语句时,您的应用永远不会抛出 NullPointerException

虽然安全调用运算符可使您避免潜在的 NullPointerException,但它会将 null 值传递给下一个语句。您可以使用 Elvis 运算符 (?:) 紧接着处理 null 值的情况,如以下示例所示:

val account = Account("name", "type")
val accountName = account.name?.trim() ?: "Default name"

如果 Elvis 运算符左侧表达式的结果为 null,则会将右侧的值赋予 accountName。此方法对于提供本来为 null 的默认值很有用

还可以使用 Elvis 运算符提前从函数返回结果,如以下示例所示:

fun validateAccount(account: Account?) {
    val accountName = account?.name?.trim() ?: "Default name"

    // account cannot be null beyond this point
    account ?: return

    ...
}
Android API 变更

由于从 Fragment#getContext 返回的 Context 可为 null(并且带有 @Nullable 注释),因此您必须在 Kotlin 代码中将其视为 Context?。这意味着,在访问其属性和函数之前,需要应用前面提到的某个运算符来处理可为 null 性问题。对于一些这样的情况,Android 包含可提供这种便利的替代 API。例如,Fragment#requireContext 会返回非 null Context,如果在 Context 将为 null 时调用它,则会抛出 IllegalStateException。这样,您就可以将生成的 Context 视为非 null 值,而无需使用安全调用运算符或其他解决方法

属性初始化

默认情况下,Kotlin 中的属性并未初始化。当初始化属性的封闭类时,必须初始化属性。

如何通过在类声明中为 index 变量赋值初始化该变量:

class LoginFragment : Fragment() {
    val index: Int = 12
}
class LoginFragment : Fragment() {
    val index: Int
    init {
        index = 12
    }
}

上面的示例中,在构建 LoginFragment 时初始化 index

不过,某些属性可能无法在对象构建期间进行初始化。例如,您可能要从 Fragment 中引用 View,这意味着,必须先扩充布局。构建 Fragment 时不会发生扩充,而是在调用 Fragment#onCreateView 时进行扩充。

应对这种情况的一种方法是将视图声明为可为 null 并尽快对其进行初始化,如以下示例所示:

class LoginFragment : Fragment() {
    private var statusTextView: TextView? = null

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            statusTextView = view.findViewById(R.id.status_text_view)
            statusTextView?.setText(R.string.auth_failed)
    }
}

当然可以使用lateinit关键字,可以避免在构建对象时初始化属性。

class LoginFragment : Fragment() {
    private lateinit var statusTextView: TextView
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
            super.onViewCreated(view, savedInstanceState)
            statusTextView = view.findViewById(R.id.status_text_view)
            statusTextView.setText(R.string.auth_failed)
    }
}

如果在属性进行初始化之前对其进行了引用,Kotlin 会抛出 UninitializedPropertyAccessException,因此请务必尽快初始化属性

注意:诸如数据绑定之类的视图绑定解决方案可以消除对 findViewById 的手动调用,这些解决方案有助于减少您需要考虑的 null 安全问题数量

Android第一行代码——快速入门 Kotlin 编程(5.3 Fragment 的生命周期) 其中,Activity 中有的回调方法, Fragment 中基本上也有,不过Fragment 还提供了一些附加的回调方法,下面我们就重点看一 下这几个回调。和 Activity 一样,Fragment 也有自己的生命周期,并且它和 Activity 的生命周期实在是太像 了,我相信你很快就能学会,下面我们马上就来看一下。当一个 Activity 进入停止状态时,与它相关联的 Fragment 就会进入停止状态,或者通过调用FragmentTransaction 的。方法,最终将 Fragment 销毁。 阅读详情

相关推荐

Kotlin空安全解决Android NPE问题

在 Android 开发中,(NPE)一直是最常见的崩溃类型之一。Kotlin 通过创新的空安全机制,在语言层面彻底解决了这一问题。

时小雨的专栏 574

使用Kotlin优雅的添加Fragment

综述 在上面文章聊一聊Kotlin扩展函数run,with,let,also和apply的使用和区别中讲解Kotlin的几个扩展函数的使用和区别。那么在这篇文章中去自己定义一些扩展函数来更加优雅的去将添加Fragment到Activity中。 回顾Fragment使用 在使用Kotlin之前,首先回顾一下在Java中是如何添加一个Fragment到Activity当中的。 Frag...

李江东 1万+

Kotlin基础从入门到进阶系列讲解(基础篇)Fragment的基本使用

Kotlin基础从入门到进阶系列讲解(基础篇)Fragment的基本使用Fragment的基本使用一、什么是Fragment二、Activity+多个Fragment Fragment的基本使用 ->返回总目录<- 一、什么是Fragment Fragment是一种可以嵌入在Activity当中的UI片段,因为它和Activity看起来太像了。Fragment是依赖于Activity的,不能独立存在,一个Activity里可以有多个Fragment 二、Activity+多个Fragment 测

彬sir哥的博客 1349

Kotlin 使用Fragment

原文地址:http://jbblog.top/MyBlog/html/blogpagecontent.html?id=54 用kotlin使用fragment比java方便。 回顾一下再Java中实现fragment的添加http://jbblog.top/blogpagecontent.html?id=3 **第一步:** 这就是FragmentManager的扩展函数,接收一个La...

虚幻的守护者的专栏 5345

全双工AI语音交互:从原理到实践,构建实时对话系统

语音交互技术正从传统的半双工模式向全双工模式演进,以实现更自然、实时的对话体验。全双工交互的核心原理在于模拟人类电话通话,允许双方同时发送和接收音频流,这需要流式语音识别(Streaming ASR)和实时自然语言理解(Real-time NLU)技术的深度整合。其技术价值在于显著降低交互延迟,支持智能打断(Barge-in),从而提升人机对话的流畅度和自然度。在应用场景上,全双工技术是智能助手、实时翻译、车载语音及无障碍交互等领域的关键突破。本文以微软MAI Realtime等模型为例,探讨如何利用开源技

weixin_33693070的博客 404

ML307A模组连接ONENET平台(AT指令步骤教程)

ML307A 是一款集成度高、体积小的物联网通信模组,支持多种无线通信协议,如 LoRa、NB-IoT 等。它具有低功耗、远程通信等特点,适用于多种物联网场景。支持 LoRa 和 NB-IoT 等多种无线通信标准。提供丰富的 GPIO 接口。内置多种传感器支持。UART 接口:用于与微控制器或其他设备通信。GPIO 接口:可以连接外部传感器或执行器。电源接口:用于供电。OneNET 是中国移动推出的一款物联网开放平台,它提供了从数据采集、存储到分析的一站式解决方案。

xiewengeng的博客 5482

03)在 Android 开发中使用常见的 Kotlin 模式

在 Android 开发中使用常见的 Kotlin 模式 本主题重点介绍 Kotlin 语言在 Android 开发过程中最有用的一些方面。 使用 Fragment 下面几部分使用 Fragment 示例来突出 Kotlin 的一些最佳功能。 继承 您可以使用 class 关键字在 Kotlin 中声明类。在以下示例中,LoginFragment 是 Fragment 的子类。您可以通过在子类与其...

ZPCrobot的博客 305

CRaxsRat v7.6 安装与使用教程(附工具下载)

摘要:本文介绍远程管理工具CRaxsRat v7.6的合法应用与基本操作,强调仅限授权环境使用。该工具支持多客户端管理、TLS加密及文件/进程控制等功能,适用于内网维护与安全测试。安装需Windows 10/11系统及.NET 4.8,步骤包括解压运行、配置监听端口及生成客户端。文中提醒防火墙设置与杀软误报问题,并重申禁止非法用途,建议在虚拟机或隔离环境学习使用。

lzj781210的博客 3792

【Kotlin安卓开发避坑大全】:90%开发者忽略的内存泄漏隐患及解决方案

解决Kotlin安卓开发常见内存泄漏问题,本文详解Handler、静态引用、回调注册等场景的避坑方案,结合WeakReference与Lifecycle感知组件实现高效内存管理。实用技巧总结,值得收藏

PixelStream的博客 407

Cosmos Transfer2.5多模态AI模型部署与优化实战

多模态AI技术通过融合文本、图像、代码等不同模态数据,实现跨模态理解与生成。其核心原理基于Transformer架构的注意力机制,结合对比学习实现模态对齐。这类技术在智能内容创作、跨模态搜索等领域具有重要价值,尤其适合电商营销图文生成、UI设计转代码等场景。Cosmos Transfer2.5作为先进的多模态模型,支持8192 tokens长文本窗口和混合模态输入,实测推理速度达17.5 samples/s(T4显卡)。部署时需注意FlashAttention优化可提升3倍长文本处理效率,8-bit量化则能

weixin_29038303的博客 281

AT89C52单片机+LCD屏:手把手教你做一个能算小数和负数的计算器(附完整代码)

本文详细介绍了如何使用AT89C52单片机和LCD1602显示屏构建一个支持小数和负数运算的高精度计算器。从硬件选型、系统架构设计到核心算法实现,提供了完整的代码示例和优化技巧,特别适合51单片机初学者和课程设计参考。

weixin_30374009的博客 371

Android开发之Kotlin基础(零散版2)

by lazy要求属性声明为val,即不可变变量,在java中相当于被final修饰,这意味着该变量一旦初始化后就不允许再被修改值了,基本类型是值不能被修改,对象类型是引用不能被修改。可是有的时候,我并不想声明一个类型可空的对象,而且我也没办法在对象一声明的时候就为它初始化,那么这时就需要用到。var 很容易理解,JavaScript 等其他语言也通过该关键字来声明变量,它对应的就是 Java 中的变量。在很多 Kotlin 的学习资料中,都会传递一个原则:优先使用 val 来声明变量。

wj3034547573的博客 423

完美解决LBP2900打印机安装驱动提示无法识别USB及连接错误等问题(附Win11全新安装支持及卸载方案)

LBP2900打印机虽然经典老旧,但在Win11上依然可以完美使用!许多网上教程都无视安装失败后的问题,在此分享一种全新、100%有效的方法来解决驱动连接错误和无法识别USB设备的问题。无论是新安装还是卸载重装,这个方法都适用。本文整合了通用驱动包,支持Win2000到Win11系统,操作简单,轻松摆脱安装困扰,享受无忧打印体验!

心开始の未来~的博客 2万+

uni-app安卓原生插件开发实战指南

原生插件开发是跨平台应用实现高性能本地功能的核心技术,通过Java/Kotlin扩展JavaScript运行环境,开发者可以突破WebView限制直接调用设备硬件API。其技术原理基于模块化架构设计,通过UniModule/UniComponent基类实现原生能力封装,最终以aar形式集成到uni-app工程中。这种方案特别适合需要蓝牙打印、NFC读卡等硬件交互场景,既能保持跨平台开发效率,又能获得接近原生应用的性能表现。在uni-app生态中,合理使用原生插件可显著提升复杂业务场景下的用户体验,特别是在处

weixin_33674976的博客 417

什么是论文的创新点?公式化描述算是创新点吗?

写科研论文时,挑战之一就是如何让你的工作“脱颖而出”,也就是要有创新性。不管实验多么精确、推导多么复杂,若没有真正的创新,论文很可能会被拒。关于如何创新问题上,我最近在看刘雪峰老师的《科技论文写作指南》,看到了很多关于写作的新论述,在这里和大家进行分享。

加百力 的技术博客 1926

J204B接口数据链路的建立

介绍J204B数据链路层的建立方式

QUACK_G的博客 6550

在Android开发中采用Kotlin

在 2019 年 Google I/O 大会上,谷歌宣布今后将越来越优先采用 Kotlin 进行 Android 开发。Kotlin 是一种富有表现力且简洁的编程语言,不仅可以减少常见代码错误,还可以轻松集成到现有应用中。如果您想构建 Android 应用,建议您从 Kotlin 开始着手,充分利用一流的 Kotlin 功能。 为什么要优先使用 Kotlin 进行 Android 开发? 下面介绍了开发者喜欢用 Kotlin 编写代码的原因: 富有表现力且简洁:您可以使用更少的代码实现更多的功能。

宝爷的专栏 1065

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

kotlin中匿名内部类的写法

用kotlin写,也变得五花八门了。原本java开发安卓常用的。

知道这个有什么用? 569

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

平平无奇Android快速转战Kotlin教程,手把手教学,学不会算我输

这个上面已经说过,我们创建工程的时候如果选中Include kotlin support怎会自动在gradle中生成。

2301_76327109的博客 1095

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Android中常见的设计模式,2022Android开发社招面试总结

static class Builder { public Builder() { } public void setTitle(String msg){ } public void setContent(String msg){ } } } var builder =TestBuider.Builder() builder.setContent(“”) TestBuider.Builder builder1 = new TestBuider.Builder(); builder1.setContent(“

m0_54851114的博客 280

浅谈Kotlin解析之设计模式

设计模式是我们Android成长之路必备的一项技能,相信很多同学都已经Get了,现在让我们来看看在Kotlin中设计模式是如何表达的呢。###二、单例模式单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例。使用场景: 确保某个类有且只有一个对象的场景,避免产生多个对象消耗过多的资源kotlin写法是不是简单直接越看越喜欢,一句话就概括了。来看一下官方的说明。

2301_79655511的博客 1172

Android Kotlin MVP 清洁架构项目常见问题解决方案

Android Kotlin MVP 清洁架构项目常见问题解决方案 1. 项目基础介绍及主要编程语言 本项目是一个使用 Kotlin 语言编写的 Android 应用程序框架,它实现了清洁架构(Clean Architecture)的设计模式,并结合了 MVP(Model-View-Presenter)模式。项目包含三个主要模块:数据(Data)、领域(Domain)和表示(Presentatio...

gitblog_00725的博客 780

Kotlin语言的移动应用开发

Kotlin是一种现代的编程语言,由JetBrains于2011年推出,并于2017年被谷歌正式作为安卓开发的官方语言。Kotlin的语法简洁,能够有效减少样板代码,同时支持面向对象编程及函数式编程,极大地提高了开发效率。Kotlin以其简洁、安全、高效的特性,逐渐成为移动应用开发的主流语言。它在提高开发效率、加强代码可读性、获得活跃社区支持等方面的优势,使得Kotlin的使用越来越广泛。随着技术的不断发展和Kotlin的不断演进,我们有理由相信,在不久的将来,它将会在移动应用开发领域扮演更加重要的角色。

2501_90425976的博客 376

Kotlin MVVM Hilt Flow App 常见问题解决方案

Kotlin MVVM Hilt Flow App 常见问题解决方案 项目基础介绍和主要编程语言 Kotlin MVVM Hilt Flow App 是一个基于 Kotlin 语言开发的 Android 应用程序,采用了 Clean Architecture 和 MVVM(Model-View-ViewModel)设计模式。该项目结合了 Android Jetpack 组件,如 LiveData、...

gitblog_00094的博客 811
上一篇: Android 获取ICCID,IMEI
下一篇: Java 如何改为Kotlin(一)
K_Hello
博客等级 码龄12年 33粉丝 115原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值