第一行代码Android个人笔记(四)——广播

tech2022-07-06  247

文章目录

一、注册广播监听1、动态注册2、静态注册 二、发送自定义广播1、发送标准广播2、发送有序广播 三、广播的最佳实践——强制下线功能四、kotlin课堂1、高阶函数

一、注册广播监听

1、动态注册

建立广播的监听类建立过滤器在过滤器中添加监听的动作注册广播取消注册 lateinit var timeChangeReceiver: TimeChangeReceiver override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val intentFilter = IntentFilter()//建立过滤器 intentFilter.addAction("android.intent.action.TIME_TICK")//监听的动作 timeChangeReceiver = TimeChangeReceiver()//接受广播的类 registerReceiver(timeChangeReceiver, intentFilter)//注册广播 } override fun onDestroy() { super.onDestroy() unregisterReceiver(timeChangeReceiver)//一定要取消注册 } //接收广播的类,需要继承BroadcastReceiver inner class TimeChangeReceiver:BroadcastReceiver(){ override fun onReceive(context: Context?, intent: Intent?) { Toast.makeText(context,"Time has changed", Toast.LENGTH_SHORT).show() } }

2、静态注册

建立广播的监听类在Manifest.xml注册广播监听 如果使用如图方式添加广播类,会自动注册在Manifest.xml注册广播动作 <receiver android:name=".BootCompleteReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"/> </intent-filter> </receiver> 某些操作(如监听开机)需要授予权限 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

二、发送自定义广播

1、发送标准广播

val intent = Intent("com.lrgy.broadcasttest.MY_BROADCAST")//构建包含对应广播的Intent对象 intent.setPackage(packageName)//对于静态注册的隐式广播,一定要调用该方法以确定作用的应用程序,使他成为一条显式广播 sendBroadcast(intent)//发送广播

2、发送有序广播

有序和无序的差别其实不大只需要修改以下几点:

发送广播时使用 sendOrderedBroadcast(intent, null)//发送广播 在广播注册时指定优先级,优先级高的先接收到广播 android:priority="200" <receiver android:name=".AnotherBroadcastReceiver" android:enabled="true" android:exported="true"> <intent-filter android:priority="200"> <action android:name="com.lrgy.broadcasttest.MY_BROADCAST"/> </intent-filter> </receiver> 可以在广播中截断广播的传递 abortBroadcast()

三、广播的最佳实践——强制下线功能

分析:强制下线需要在任何一个页面都实现:收到下线命令,即刻下线的功能。因此为每个activity都写这个功能并不合适,所以需要使用广播。

思路:收到下线广播——触发对应receiver——关闭所有activity——启动登录界面activity

建立ActivityCollector方便管理所有的Activity //单例类,伪静态方法 object ActivityCollector { private val activities = ArrayList<Activity>() fun addActivity(activity: Activity){ activities.add(activity) } fun removeActivity(activity: Activity){ activities.remove(activity) } fun finishAll(){ //finish所有activity for (activity in activities){ if (!activity.isFinishing){ activity.finish() } } activities.clear()//将集合中的所有activity元素清空 } } 建立BaseActivity类,使得所有activity都可以被ActivityCollector控制 /*该项目中所有Activity的父类*/ //添加open才可以被继承 open class BaseActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) Log.d("BaseActivity", javaClass.simpleName)//javaClass相当于java中的getClass方法,获取当前类的对象 ActivityCollector.addActivity(this) } override fun onDestroy() { super.onDestroy() ActivityCollector.removeActivity(this) } } 在LoginActivity中添加登录验证 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_login) login.setOnClickListener { val account = accountEdit.text.toString() val password = passwordEdit.text.toString() if (account == "admin" && password == "123"){ val intent = Intent(this, MainActivity::class.java) startActivity(intent) finish() }else{ Toast.makeText(this, "error", Toast.LENGTH_SHORT).show() } } } 在MainActivity中添加触发下线的功能 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) forceOffLine.setOnClickListener { val intent = Intent("com.lrgy.boardcastbestpractice.FORCE_OFFLINE") sendBroadcast(intent) } } 在BaseActivity中可以为每个Activity注册和取消注册广播 特别地,这里使用了内部类进行动态绑定 //自定义广播的对象 lateinit var receiver: ForceOfflineReceiver override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) Log.d("BaseActivity", javaClass.simpleName)//javaClass相当于java中的getClass方法,获取当前类的对象 ActivityCollector.addActivity(this) } override fun onResume() { super.onResume() val intentFilter = IntentFilter()//广播过滤器 intentFilter.addAction("com.lrgy.boardcastbestpractice.FORCE_OFFLINE") receiver = ForceOfflineReceiver() //这里在onResume里注册的原因是:避免非栈顶元素有广播的注册,发生WindowManager$BadTokenException: Unable to add window异常 registerReceiver(receiver,intentFilter)//注册广播绑定 } override fun onPause() { super.onPause() unregisterReceiver(receiver)//!!!!!注意一定要在onPause里取消注册 } override fun onDestroy() { super.onDestroy() ActivityCollector.removeActivity(this) } inner class ForceOfflineReceiver : BroadcastReceiver(){ override fun onReceive(context: Context, intent: Intent) { AlertDialog.Builder(context).apply { setTitle("Warning") setMessage("you will offline") setCancelable(false)//设置为不可取消 setPositiveButton("OK"){ _, _ ->//省略了参数:dialog, which ActivityCollector.finishAll()//销毁所有activity //启动LoginActivity val i = Intent(context, LoginActivity::class.java) context.startActivity(i) } show() } } } 别忘了在Mainifest中修改第一个页面 <activity android:name=".LoginActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <activity android:name=".MainActivity"> </activity>

四、kotlin课堂

1、高阶函数

创建方式 fun num1AndNum2(num1: Int, num2: Int, operation: (Int, Int) -> Int): Int{ val result = operation(num1, num2) return result } 调用方法

可以使用引用函数的方式

//【::函数名】 可以引用函数 val result1 = num1AndNum2(num1, num2, ::plus) fun plus(num1: Int, num2: Int): Int{ return num1 + num2 }

也可以使用lamda表达式

val result2 = num1AndNum2(num1, num2){ n1, n2 -> n1 + n2 } 使用内联函数(inline关键字)可以消除运行时带来的额外开销 inline fun num1AndNum2(num1: Int, num2: Int, operation: (Int, Int) -> Int): Int{ val result = operation(num1, num2) return result }

如果只想将其中一个高阶函数变成内联函数,可以使用noinline关键字

inline fun inlineTest(block1: () -> Unit, noinline block2: () -> Unit){ } 内联函数和非内联函数的区别 除了可以消除运行时带来的额外开销之外,内联函数中是可以使用retrun关键字来返回的,但是非内联函数只能进行局部返回。(return@函数名)
最新回复(0)