Android Framework AMS(13)广播组件分析-4(LocalBroadcastManager注册/注销/广播发送处理流程解读)
该系列文章总纲链接:专题总纲目录 Android Framework 总纲
本章关键点总结 & 说明:

说明:本章节主要解读广播组件的广播发送过程。关注思维导图中左上侧部分即可。
有了前面普通广播组件 注册/注销程/广播组件的发送广播流程分析的基础,基于此,接下来我们来分析LocalBroadcastManager也就是本地广播组件的 注册/注销程/广播组件的发送广播流程。
我们先对LocalBroadcastManager的引用有一个了解,再详细分析其注册/注销/广播发送关键流程。
1 LocalBroadcastManager应用解读
LocalBroadcastManager是Android框架中一个非常有用的工具类,它允许应用内的各个组件(如Activities、Services、Fragments等)之间通过广播机制进行通信,而无需使用全局的Intent系统。这种通信方式被称为本地广播或应用内广播。它的主要特点和用途解读如下:
- 作用域限制:
LocalBroadcastManager限制了广播的作用域在应用内部,这意味着广播不会被发送到其他应用,增强了数据的安全性。 - 简化通信:它提供了一种简化的通信方式,使得应用内部的组件可以轻松地发送和接收消息,而不需要处理复杂的Intent和Permission。
- 解耦组件:
LocalBroadcastManager帮助解耦应用内的组件,组件之间不需要直接引用或依赖,只需注册感兴趣的广播即可。 - 线程安全:所有与
LocalBroadcastManager交互的操作都是线程安全的,这意味着它可以在任何线程中使用,包括主线程和后台线程。 - 异步和同步发送:应用可以使用
LocalBroadcastManager发送异步广播(使用sendBroadcast)或同步广播(使用sendBroadcastSync)。 - 广播生命周期管理:
LocalBroadcastManager管理广播的生命周期,包括注册接收器、发送广播和注销接收器。 - 性能优化:由于广播仅限于应用内部,
LocalBroadcastManager可以减少系统资源的消耗,提高应用性能。 - 使用场景:适用于需要在应用的不同组件之间传递小量数据的场景,如更新UI、同步数据。
以下是一个使用LocalBroadcastManager发送和接收本地广播的示例,包含发送广播和接收广播两部分。
1.1 发送广播部分
首先,我们需要一个方法来发送本地广播。这通常可以在某个事件发生时触发,比如用户完成了某个操作。SendBroadcastActivity.java内如实现如下:
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import androidx.appcompat.app.AppCompatActivity;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;public class SendBroadcastActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_send_broadcast);}public void sendLocalBroadcast(View view) {Intent intent = new Intent("com.example.myapp.LOCAL_BROADCAST");intent.putExtra("key_message", "Hello, this is a local broadcast!");// 使用LocalBroadcastManager发送本地广播LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this);localBroadcastManager.sendBroadcast(intent);}
}
1.2 接收广播部分
接下来,我们需要一个组件来接收并处理这个本地广播。这里我们使用一个Service作为例子。ReceiveBroadcastService.java内容实现如下:
import android.app.Service;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;public class ReceiveBroadcastService extends Service {@Overridepublic void onCreate() {super.onCreate();// 创建IntentFilter并添加要接收的广播ActionIntentFilter filter = new IntentFilter("com.example.myapp.LOCAL_BROADCAST");// 使用LocalBroadcastManager注册接收器LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this);localBroadcastManager.registerReceiver(broadcastReceiver, filter);}@Overridepublic void onDestroy() {super.onDestroy();// 注销接收器LocalBroadcastManager localBroadcastManager = LocalBroadcastManager.getInstance(this);localBroadcastManager.unregisterReceiver(broadcastReceiver);}@Overridepublic IBinder onBind(Intent intent) {// 不提供绑定服务,返回nullreturn null;}private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {@Overridepublic void onReceive(Context context, Intent intent) {String action = intent.getAction();if ("com.example.myapp.LOCAL_BROADCAST".equals(action)) {String message = intent.getStringExtra("key_message");// 处理接收到的广播,比如显示日志、更新UI等}}};
}
1.3 对应的AndroidManifest.xml配置文件部分
对应的AndroidManifest.xml配置文件参考如下:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="com.example.myapp"><applicationandroid:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:roundIcon="@mipmap/ic_launcher_round"android:supportsRtl="true"android:theme="@style/AppTheme"><!-- 发送广播的Activity --><activity android:name=".SendBroadcastActivity"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><!-- 接收广播的Service --><service android:name=".ReceiveBroadcastService" /></application>
</manifest>
2 LocalBroadcastManager解读
基于上面的案例demo,我们主要分析几个关键代码及对应流程:
- localBroadcastManager = LocalBroadcastManager.getInstance(this); 获取LocalBroadcastManager的单例对象流程
- localBroadcastManager.registerReceiver(broadcastReceiver, filter);注册流程
- localBroadcastManager.unregisterReceiver(broadcastReceiver);注销流程
- localBroadcastManager.sendBroadcast(intent);广播发送流程
2.1 获取LocalBroadcastManager的单例对象流程解读
LocalBroadcastManager的单例模式设计和构造器实现代码如下:
//LocalBroadcastManager// 单例模式public static LocalBroadcastManager getInstance(Context context) {synchronized (mLock) {if (mInstance == null) {mInstance = new LocalBroadcastManager(context.getApplicationContext());}return mInstance;}}// 构造函数private LocalBroadcastManager(Context context) {mAppContext = context;mHandler = new Handler(context.getMainLooper()) {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case MSG_EXEC_PENDING_BROADCASTS:// 调用executePendingBroadcasts方法来执行挂起的广播executePendingBroadcasts(); break;default:super.handleMessage(msg);}}};}
这里在构造期中初始化了一个Handler用于消息处理。
2.2 LocalBroadcastManager注册接收器流程解读
注册receiver流程为registerReceiver方法,代码实现如下:
//LocalBroadcastManagerpublic void registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {synchronized (mReceivers) {// 创建一个新的ReceiverRecord对象,它包含了IntentFilter和BroadcastReceiver的引用ReceiverRecord entry = new ReceiverRecord(filter, receiver);// 获取与该BroadcastReceiver关联的IntentFilter列表ArrayList<IntentFilter> filters = mReceivers.get(receiver);if (filters == null) {// 如果列表不存在,则创建一个新的列表并将其与BroadcastReceiver关联filters = new ArrayList<IntentFilter>(1);mReceivers.put(receiver, filters);}// 将新的IntentFilter添加到列表中filters.add(filter);// 遍历IntentFilter中的所有动作for (int i = 0; i < filter.countActions(); i++) {String action = filter.getAction(i);// 获取与该动作关联的ReceiverRecord列表ArrayList<ReceiverRecord> entries = mActions.get(action);if (entries == null) {// 如果列表不存在,则创建一个新的列表并将其与动作关联entries = new ArrayList<ReceiverRecord>(1);mActions.put(action, entries);}// 将ReceiverRecord添加到与动作关联的列表中entries.add(entry);}}}
registerReceiver方法通过维护两个映射(mReceivers和mActions)来管理BroadcastReceiver的注册信息。这种方法允许LocalBroadcastManager高效地处理本地广播的注册和分发,确保只有匹配特定IntentFilter的广播被发送到对应的BroadcastReceiver。
2.3 LocalBroadcastManager注销接收器流程解读
注销receiver流程为unregisterReceiver方法,代码实现如下:
//LocalBroadcastManagerpublic void unregisterReceiver(BroadcastReceiver receiver) {synchronized (mReceivers) {// 从mReceivers映射中移除与BroadcastReceiver关联的IntentFilter列表ArrayList<IntentFilter> filters = mReceivers.remove(receiver);if (filters == null) {// 如果没有找到对应的IntentFilter列表,直接返回return;}for (int i = 0; i < filters.size(); i++) {// 遍历每个IntentFilterIntentFilter filter = filters.get(i);for (int j = 0; j < filter.countActions(); j++) {// 遍历IntentFilter中的每个动作String action = filter.getAction(j);ArrayList<ReceiverRecord> receivers = mActions.get(action);if (receivers != null) {// 在与动作关联的ReceiverRecord列表中查找对应的BroadcastReceiverfor (int k = 0; k < receivers.size(); k++) {if (receivers.get(k).receiver == receiver) {// 如果找到,从列表中移除对应的ReceiverRecordreceivers.remove(k);k--; // 调整索引,因为列表大小变了}}// 如果某个动作的所有ReceiverRecord都被移除了,那么也移除这个动作if (receivers.size() <= 0) {mActions.remove(action);}}}}}}
unregisterReceiver方法通过遍历mReceivers映射和mActions映射来注销BroadcastReceiver。它确保了所有与BroadcastReceiver关联的IntentFilter和动作都被正确地移除,保持了LocalBroadcastManager内部状态的一致性。这个过程对于维护LocalBroadcastManager的注册表非常重要,确保了广播能够准确地发送给正确的接收器。
2.4 LocalBroadcastManager发送广播流程解读
2.4.1 sendBroadcast方法解读
发送广播流程为sendBroadcast方法,代码实现如下:
//LocalBroadcastManager//关键流程:step1public boolean sendBroadcast(Intent intent) {synchronized (mReceivers) {// 获取Intent中的动作final String action = intent.getAction();// 根据ContentResolver解析Intent的数据类型final String type = intent.resolveTypeIfNeeded(mAppContext.getContentResolver());// 获取Intent中的数据Urifinal Uri data = intent.getData();// 获取Intent中的schemefinal String scheme = intent.getScheme();// 获取Intent中的categoriesfinal Set<String> categories = intent.getCategories();// 根据动作从mActions映射中获取对应的ReceiverRecord列表ArrayList<ReceiverRecord> entries = mActions.get(intent.getAction());if (entries != null) {// 如果有记录,准备发送广播ArrayList<ReceiverRecord> receivers = null;for (int i = 0; i < entries.size(); i++) {ReceiverRecord receiver = entries.get(i);// 如果ReceiverRecord正在广播中,则跳过if (receiver.broadcasting) {continue;}// 匹配IntentFilter和Intentint match = receiver.filter.match(action, type, scheme, data, categories, "LocalBroadcastManager");// 如果匹配成功if (match >= 0) {if (receivers == null) {receivers = new ArrayList<ReceiverRecord>();}receivers.add(receiver);receiver.broadcasting = true; // 标记为正在广播}}// 如果有匹配的接收器if (receivers != null) {for (int i = 0; i < receivers.size(); i++) {receivers.get(i).broadcasting = false; // 重置广播状态}// 将广播记录添加到待处理列表mPendingBroadcasts.add(new BroadcastRecord(intent, receivers));// 如果Handler没有正在处理的消息,则发送一个消息以执行待处理的广播if (!mHandler.hasMessages(MSG_EXEC_PENDING_BROADCASTS)) {mHandler.sendEmptyMessage(MSG_EXEC_PENDING_BROADCASTS);}return true; // 返回true表示广播已发送}}}return false; // 返回false表示没有匹配的接收器}//消息处理流程private LocalBroadcastManager(Context context) {mAppContext = context;mHandler = new Handler(context.getMainLooper()) {@Overridepublic void handleMessage(Message msg) {switch (msg.what) {case MSG_EXEC_PENDING_BROADCASTS:// 调用executePendingBroadcasts方法来执行挂起的广播executePendingBroadcasts(); break;default:super.handleMessage(msg);}}};}//关键流程:step3private void executePendingBroadcasts() {while (true) {BroadcastRecord[] brs = null;synchronized (mReceivers) {// 获取挂起广播的数量final int N = mPendingBroadcasts.size();// 如果没有挂起的广播,退出方法if (N <= 0) {return;}// 创建一个数组来存储挂起的广播记录brs = new BroadcastRecord[N];// 将挂起的广播记录复制到数组中mPendingBroadcasts.toArray(brs);// 清空挂起的广播列表mPendingBroadcasts.clear();}// 遍历所有挂起的广播记录for (int i = 0; i < brs.length; i++) {BroadcastRecord br = brs[i];// 遍历广播记录中的所有接收器for (int j = 0; j < br.receivers.size(); j++) {// 获取ReceiverRecordReceiverRecord receiverRecord = br.receivers.get(j);// 调用BroadcastReceiver的onReceive方法receiverRecord.receiver.onReceive(mAppContext, br.intent);}}}}
sendBroadcast方法通过匹配Intent和IntentFilter来找到所有感兴趣的BroadcastReceiver,并将它们添加到待处理列表中。然后,它使用Handler来异步执行这些广播,确保广播的发送不会阻塞当前线程。这种方法允许LocalBroadcastManager在应用内部高效地分发本地广播。
sendBroadcast最后是通过handler消息机制调用executePendingBroadcasts方法来完成处理的,该方法负责执行所有挂起的本地广播。它通过遍历挂起的广播列表,为每个广播调用相应的BroadcastReceiver的onReceive方法。这个方法确保了所有本地广播都能被正确处理,即使在主线程繁忙时也能异步执行。
2.4.2 sendBroadcastSync方法解读
同步发送广播流程为sendBroadcastSync方法,代码实现如下:
//LocalBroadcastManagerpublic void sendBroadcastSync(Intent intent) {// 首先,尝试异步发送广播if (sendBroadcast(intent)) {// 如果sendBroadcast方法返回true,表示广播已经成功放入待处理队列// 然后,调用executePendingBroadcasts方法来同步执行所有挂起的广播executePendingBroadcasts();}}
sendBroadcastSync方法提供了一个同步发送本地广播的机制。与sendBroadcast方法不同,sendBroadcastSync会立即执行挂起的广播,而不是将它们放入消息队列等待主线程处理。这确保了广播的接收器能够立即接收到广播,这对于需要快速响应的场景非常有用。
这种方法的同步特性意味着它可能会阻塞当前线程,直到所有挂起的广播都被处理完毕。因此,在使用sendBroadcastSync时需要谨慎,以避免在主线程中引起不必要的延迟。通常,sendBroadcastSync用于测试或后台线程中,以确保广播能够立即被处理。
2.4.3 sendBroadcastSync与sendBroadcast的区别
两者的区别主要有以下几点:
- 同步执行:
sendBroadcastSync方法在发送广播后,会立即调用executePendingBroadcasts方法来同步执行所有挂起的广播。这意味着BroadcastReceiver的onReceive方法会在当前方法调用栈中被执行,而不是被放入消息队列等待。sendBroadcast方法则需要消息等待。 - 立即响应:使用
sendBroadcastSync可以确保广播的接收器立即接收到广播,这对于需要快速响应的事件处理非常重要。 - 阻塞性:
sendBroadcastSync可能会导致当前线程阻塞,直到所有挂起的广播都被处理完毕,因为它是同步执行的。而sendBroadcast是异步的。 - 适用场景:
sendBroadcastSync适用于那些需要立即处理广播的场景,而sendBroadcast则适用于那些可以异步处理广播的场景。
总之,sendBroadcastSync方法提供了一种机制,允许应用在发送本地广播后立即同步处理这些广播,而不是等待主线程的消息队列中的其他消息。这与sendBroadcast方法形成对比,后者是异步的,它将广播放入消息队列中,等待主线程在适当的时候处理。选择使用哪种方法取决于应用的具体需求,是否需要立即处理广播或者可以容忍一定的延迟。
相关文章:
Android Framework AMS(13)广播组件分析-4(LocalBroadcastManager注册/注销/广播发送处理流程解读)
该系列文章总纲链接:专题总纲目录 Android Framework 总纲 本章关键点总结 & 说明: 说明:本章节主要解读广播组件的广播发送过程。关注思维导图中左上侧部分即可。 有了前面普通广播组件 注册/注销程/广播组件的发送广播流程分析的基础&…...
模糊理论与模糊集概述
1. 模糊集 1️⃣ μ A : U → [ 0 , 1 ] \mu_A:U\to{[0,1]} μA:U→[0,1],将任意 u ∈ U u\in{}U u∈U映射到 [ 0 , 1 ] [0,1] [0,1]上的某个函数 模糊集: A { μ A ( u ) , u ∈ U } A\{\mu_A(u),u\in{}U\} A{μA(u),u∈U}称为 U U U上的一个模糊集…...
基于STM32的实时时钟(RTC)教学
引言 实时时钟(RTC)是微控制器中的一种重要功能,能够持续跟踪当前时间和日期。在许多应用中,RTC用于记录时间戳、定时操作等。本文将指导您如何使用STM32开发板实现RTC功能,通过示例代码实现当前时间的读取和显示。 环…...
Caffeine Cache解析(三):BoundedBuffer 与 MpscGrowableArrayQueue 源码浅析
接续 Caffeine Cache解析(一):接口设计与TinyLFU 接续 Caffeine Cache解析(二):drainStatus多线程状态流转 BoundedBuffer 与 MpscGrowableArrayQueue multiple-producer / single-consumer 这里multiple和single指的是并发数量 BoundedBuffer: Caf…...
全双工通信协议WebSocket——使用WebSocket实现智能学习助手/聊天室功能
一.什么是WebSocket? WebSocket是基于TCP的一种新的网络协议。它实现了浏览器与服务器的全双工通信——浏览器和服务器只需要完成一次握手,两者之间就可以创建持久性的连接,并进行双向数据传输 HTTP 协议是一种无状态的、无连接的、单向的应用…...
Rust-Trait 特征编程
昨夜江边春水生,艨艟巨舰一毛轻。 向来枉费推移力,此日中流自在行。 ——《活水亭观书有感二首其二》宋朱熹 【哲理】往日舟大水浅,众人使劲推船,也是白费力气,而此时春水猛涨,巨舰却自由自在地飘行在水流中…...
彻底理解哈希表(HashTable)结构
目录 介绍优缺点概念哈希函数快速的计算键类型键转索引霍纳法则 均匀的分布 哈希冲突链地址法开放地址法线性探测二次探测再哈希法 扩容/缩容实现哈希创建哈希表质数判断哈希函数插入&修改获取数据删除数据扩容/缩容函数全部代码 哈希表(Hash Table)…...
微信小程序的汽车维修预约管理系统
文章目录 项目介绍具体实现截图技术介绍mvc设计模式小程序框架以及目录结构介绍错误处理和异常处理java类核心代码部分展示详细视频演示源码获取 项目介绍 系统功能简述 前台用于实现用户在页面上的各种操作,同时在个人中心显示各种操作所产生的记录:后…...
LeetCode:3255. 长度为 K 的子数组的能量值 II(模拟 Java)
目录 3255. 长度为 K 的子数组的能量值 II 题目描述: 实现代码与解析: 模拟 原理思路: 3255. 长度为 K 的子数组的能量值 II 题目描述: 给你一个长度为 n 的整数数组 nums 和一个正整数 k 。 一个数组的 能量值 定义为&am…...
深入了解逻辑回归:机器学习中的经典算法
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...
软件测试基础十三(python 函数)
函数 1. 函数的意义 代码复用 提高效率:Python中的函数允许将一段可重复使用的代码封装起来。例如,在一个数据分析项目中,可能需要多次计算一组数据的平均值。可以将计算平均值的代码定义为一个函数: def calculate_average(nu…...
计算机网络——HTTP篇
基础篇 IOS七层网络模型 TCP/IP四层模型? 应⽤层:位于传输层之上,主要提供两个终端设备上的应⽤程序之间的通信,它定义了信息交换的格式,消息会交给下⼀层传输层来传输。 传输层的主要任务就是负责向两台设备进程之间…...
信息化运维方案,实施方案,开发方案,信息中心安全运维资料(软件资料word)
1 编制目的 2 系统运行维护 2.1 系统运维内容 2.2 日常运行维护方案 2.2.1 日常巡检 2.2.2 状态监控 2.2.3 系统优化 2.2.4 软件系统问题处理及升级 2.2.5 系统数据库管理维护 2.2.6 灾难恢复 2.3 应急运行维护方案 2.3.1 启动应急流程 2.3.2 成立应急小组 2.3.3 应急处理过程 …...
自动化工具 Gulp
自动化工具 gulp 摘要 概念:gulp用于自动化开发流程。 理解:我们只需要编写任务,然后gulp帮我们执行 核心概念: 任务:通过定义不同的任务来组织你的构建流程。 管道:通过管道方式将文件从一个插件传递…...
css实现div被图片撑开
固定好盒子的宽度,高度随传过来的图片大小决定 <div class"tab-con"> <img:src"concertInfo.detail"alt""> </div>.tab-con {margin-bottom: 20px;width: 700px;img {width: 700px;height: auto;object-fit: cont…...
Power Pivot、Power BI 和 SQL Server Analysis Services 的公式语言:DAX(数据分析表达式)
DAX(Data Analysis Expressions)是一种用于 Power Pivot、Power BI 和 SQL Server Analysis Services 的公式语言,旨在帮助用户进行数据建模和复杂计算。DAX 的设计初衷是使数据分析变得简单而高效,特别是在处理数据模型中的表关系…...
大模型应用编排工具Dify二开之工具和模型页面改造
1.前言 简要介绍下 dify: 一款可以对接市面上主流大模型的任务编排工具,可以通过拖拽形式进行编排形成解决某些业务场景的大模型应用。 背景信息: 环境:dify-0.8.3、docker-21 最近笔者在做 dify的私有化部署和二次…...
Pytorch用BERT对CoLA、新闻组文本数据集自然语言处理NLP:主题分类建模微调可视化分析...
原文链接:https://tecdat.cn/?p38181 自然语言处理(NLP)领域在近年来发展迅猛,尤其是预训练模型的出现带来了重大变革。其中,BERT 模型凭借其卓越性能备受瞩目。然而,对于许多研究者而言,如何高…...
LightGBM-GPU不能装在WSL,能装在windows上
这是一篇经验总结文章,注重思路,忽略细节。 1.起因 用多个机器学习方法训练模型,比较性能,发现Light GBM方法获得的性能明显更高,但问题是在CPU上训练的速度特别特别慢,需要用GPU训练。 2.开始装LightGB…...
工业相机常用功能之白平衡及C++代码分享
目录 1、白平衡的概念解析 2、相机白平衡参数及操作 2.1 相机白平衡参数 2.2 自动白平衡操作 2.3 手动白平衡操作流程 3、C++ 代码从XML读取参数及设置相机参数 3.1 读取XML 3.2 C++代码,从XML读取参数 3.3 给相机设置参数 1、白平衡的概念解析 白平衡(White Balance)…...
未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...
XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...
Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...
渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...
1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
