《第一行代码》第三版笔记五

本文详细介绍了Android应用中的广播系统,包括标准广播与有序广播的区别、动态注册与静态注册的方法,以及如何发送自定义广播。此外,还涵盖了高阶函数、内联函数和noinline/crossinline的关键概念及其应用。
摘要由CSDN通过智能技术生成

目录

第六章

6.1广播

6.2接收系统广播

6.2.1动态注册

6.2.2静态注册 

6.3发送自定义广播

6.3.1发送标准广播

6.3.2发送有序广播 

 6.4高阶函数

6.4.1定义高阶函数

6.4.2内联函数

6.4.3noinline与crossinline


第六章

6.1广播

        广播类型:标准广播和有序广播。

标准广播:无序、无法被截断、效率高;

有序广播:有序、可以被截断(可以设置优先级)

6.2接收系统广播

        注册BroadcastReceiver方式:动态注册(在代码中)、静态注册(在AndroidManifest.xml中)

6.2.1动态注册

        动态广播必须在程序启动之后。

        新建一个类让其继承自BroadcastReceiver,并重写父类的onReceive()方法,在onCreate方法中创建IntentFilter实例,并添加一个为android.intent.action.TIME_TICK的action,接着创建一个TimeChangeReceiver的实例,调用registerReceiver方法将TimeChangeReceiver以及IntentFilter传入,最后在onDestroy方法中调用unregisterReceiver方法取消注册。

        查看完整的系统广播列表可到如下路径查看:

        <Android SDK>/platforms/<任意android api版本>/data/broadcast_actions.txt

class MainActivity : AppCompatActivity() {
     
     lateinit var timeChangeReceiver: TimeChangeReceiver
    
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         setContentView(R.layout.activity_main)

         // 创建IntentFilter实例
         val intentFilter = IntentFilter()

         // 添加一个action
         // android.intent.action.TIME_TICK为系统时间变化时发出的广播
         intentFilter.addAction("android.intent.action.TIME_TICK")

         // 创建一个TimeChangeReceiver实例
         timeChangeReceiver = TimeChangeReceiver()

         // 用registerReceiver方法将TimeChangeReceiver与intentFilter传入
         registerReceiver(timeChangeReceiver, intentFilter)
     }
     //动态注册的广播一定要取消注册!
     override fun onDestroy() {
         super.onDestroy()
         // 在onDestroy中调用unregisterReceiver方法
         unregisterReceiver(timeChangeReceiver)
     }

     // 新建一个类继承自BroadcastReceiver并重写onReceive方法
     inner class TimeChangeReceiver : BroadcastReceiver() {
         override fun onReceive(context: Context, intent: Intent) {
                // 当收到广播时显示toast消息
                Toast.makeText(context, "Time has changed", Toast.LENGTH_SHORT).show()
         }
     }
}
6.2.2静态注册 

        在Android 8.0系统之后,所有隐式广播都不允许使用静态注册的方式来接收。隐式广播指的 是那些没有具体指定发送给哪个应用程序的广播。

        少数特殊的系统广播目前仍然允许使用静态注册的方式来接收。这些特殊的系统广播列表详见 https://developer.android.google.cn/guide/components/broadcast-exceptions.html

       在清单文件中的application 标签下进行注册,并在<uses-permission>标签声明对应的权限。

<receiver
    android:name=".BootCompleteReceiver"
    android:enabled="true"     // 表示是否启用这个BroadcastReceiver
    android:exported="true">  // 表示是否允BroadcastReceiver接收本程序外的广播
    <intent-filter>
          // 添加一个广播
          // android.intent.action.BOOT_COMPLETED为一条开机广播
         <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

         尽量不要在onReceive()方法中添加过多的逻辑或者进行任何的耗时操作,因为BroadcastReceiver是不允许开启线程的。

6.3发送自定义广播

        广播分为标准广播和有序广播

6.3.1发送标准广播

        在清单文件中进行注册要接收的广播,然后构建一个intent对象,传入要发送的广播的值。由于在Android8.0之后,静态注册的BroadcastReceiver是无法接收隐式广播,因此这里一定要调用setPackage()方法,指定这条广播是发送给哪个应用程序的,从而让它变为一条显式广播。

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

         // 构建一个Intent对象,将要发送广播的值传入
         val intent = Intent("com.example.broadcasttest.MY_BROADCAST")
         intent.setPackage(packageName)
         // 调用sendBroadcast将广播发送出去
         sendBroadcast(intent)
     }
}
6.3.2发送有序广播 

        发送有序广播只需将sendBroadcast()方法改成sendOrderedBroadcast(),sendOrderedBroadcast()接收两个参数,第一个参数为Intent,第二个参数是一个与权限相关的字符串。

 override fun onCreate(savedInstanceState: Bundle?) {
     super.onCreate(savedInstanceState)
     setContentView(R.layout.activity_main)
     button.setOnClickListener {
         val intent = Intent("com.example.broadcasttest.MY_BROADCAST")
         intent.setPackage(packageName)
         sendOrderedBroadcast(intent, null)
     }
 }

         通过android:priority属性给BroadcastReceiver设置优先级,优先级越高可以先接收到广播。

 <receiver
     android:name=".MyBroadcastReceiver"
     android:enabled="true"
     android:exported="true">
     <intent-filter android:priority="100">
         <action android:name="com.example.broadcasttest.MY_BROADCAST"/>
     </intent-filter>
 </receiver>

        调用abortBroadcast()方法,表示将这条广播截断。

class MyBroadcastReceiver : BroadcastReceiver() {
     override fun onReceive(context: Context, intent: Intent) {
         Toast.makeText(context, "received in MyBroadcastReceiver",
         Toast.LENGTH_SHORT).show()
         // 表示将广播截断
         abortBroadcast()
     }
}
 6.4高阶函数
6.4.1定义高阶函数

        高阶函数定义:如果一个函数接收另一个函数作为参数,或者返回值类型是另一个函数那么该函数就称为高阶函数。

        基本规则如下:

(String, Int) -> Unit

        ->左边的部分是用来声明该函数接收什么参数,多个参数之间用逗号隔开,如果不接收任何参数,写一对空括号即可。而->右边的部分用于声明该函数的返回值是什么类型,如果没有返回值就用Unit,大致相当于Java中的void。

        将上述函数类型添加到某个函数声明或者返回值声明上,那么该函数就是一个高阶函数。

        如下的example函数即为一个高阶函数:

fun example(func: (String, Int) -> Unit) {
    func("hello", 123)
}

 调用示例:

1、传递一个具名函数作为参数

fun myFunction(str: String, num: Int) {
    println("String: $str, Number: $num")  
}

example(::myFunction) //输出结果为:String: hello, Number: 123

2、使用Lambda表达式作为参数

example { str, num ->
    println("Received parameters: $str, $num")
}

3、使用匿名函数作为参数

example(fun(str: String, num: Int) {
    println("Received parameters: $str, $num")
})
6.4.2内联函数

        内联函数是一种在编译期将函数调用替换为函数体的特殊函数,使用内联可以避免函数调用的开销,提高代码执行效率。在定义的高阶函数加上inline关键字。

6.4.3noinline与crossinline

        一个高阶函数如果接收两个或者更多函数类型的参数,这时kotlin编译器会自动将所有引用的Lambda表达式全部进行内联,如果只想内联其中一个Lambda表达式就可以使用noinline关键字。

inline fun inlineTest(block1: () -> Unit, noinline block2: () -> Unit) {
}

       在默认情况下,Lambda表达式内部的语句会直接从包含它的函数中返回,但有时我们可能需要在Lambda表达式中使用return语句,而不会影响到包含它的函数的返回。这时就可以使用crossinline关键字来修饰Lambda参数。这告诉编译器,即使Lambda表达式中使用了return语句,也不能让函数提前返回,从而可以确保函数的执行顺序和预期一致。

        例如使用如下写法会报错:

inline fun runRunnable(block: () -> Unit) {
     val runnable = Runnable {
         block()
     }
     runnable.run()
}

        改为使用crossinline即可:

inline fun runRunnable(crossinline block: () -> Unit) {
     val runnable = Runnable {
         block()
     }
     runnable.run()
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值