Android广播机制

news2024/11/23 19:54:44

简介

        某个网络的IP范围是192.168.0.XXX,子网 掩码是255.255.255.0,那么这个网络的广播地址就是192.168.0.255。广播数据包会被发送到同一 网络上的所有端口,这样在该网络中的每台主机都将会收到这条广播。为了便于进行系统级别的消息通知,Android也引入了一套类似的广播消息机制。这是因为Android中的每个应用程序都可以对自己感 兴趣的广播进行注册,这样该程序就只会接收到自己所关心的广播内容,这些广播可能是来自 于系统的,也可能是来自于其他应用程序的。Android提供了一套完整的API,允许应用程序自 由地发送和接收广播。发送广播的方法其实之前稍微提到过,如果你记性好的话可能还会有印 象,就是借助我们第2章学过的Intent。而接收广播的方法则需要引入一个新的概念——广播接 收器(Broadcast Receiver)。广播接收器的具体用法将会在下一节中做介绍,这里我们先来了解一下广播的类型。Android中 的广播主要可以分为两种类型:标准广播有序广播

一、广播的方式

标准广播:

        标准广播 (Normal broadcasts)是一种完全异步执行的广播,在广播发出之后,所有的广播 接收器几乎都会在同一时刻接收到这条广播消息,因此它们之间没有任何先后顺序可言。 这种广播的效率会比较高,但同时也意味着它是无法被截断的。标准广播的工作流程如图所示。

有序广播:

        有序广播 (Ordered broadcasts)则是一种同步执行的广播,在广播发出之后,同一时刻只 会有一个广播接收器能够收到这条广播消息,当这个广播接收器中的逻辑执行完毕后,广 播才会继续传递。所以此时的广播接收器是有先后顺序的,优先级高的广播接收器就可以 先收到广播消息,并且前面的广播接收器还可以截断正在传递的广播,这样后面的广播接 收器就无法收到广播消息了。有序广播的工作流程如图所示。

二、动态注册监听网络变化

        Android内置了很多系统级别的广播,我们可以在应用程序中通过监听这些广播来得到各种系统 的状态信息。比如手机开机完成后会发出一条广播,电池的电量发生变化会发出一条广播,时 间或时区发生改变也会发出一条广播,等等。如果想要接收到这些广播,就需要使用广播接收 器,下面我们就来看一下它的具体用法。广播接收器可以自由地对自己感兴趣的广播进行注册,这样当有相应的广播发出时,广播接收 器就能够收到该广播,并在内部处理相应的逻辑。注册广播的方式一般有两种,在代码中注册(动态注册) 和在AndroidManifest.xml中注册(静态注册)。

三、动态注册

1.定义NetworkChangeReceived监听网络状态变化
第一种代码逻辑:

public class NetworkChangeReceived extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
            boolean isConnected = isNetworkConnected(context);
            String statusMessage = isConnected ? "连接" : "断开";
            String networkType = NetworkType(context);
            Toast.makeText(context, "网络已" + statusMessage + ",类型" + networkType, Toast.LENGTH_SHORT).show();
        }
    }
        private boolean isNetworkConnected(Context context) {
            ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
            return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
        }
        private String NetworkType(Context context) {
            ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
            return activeNetwork != null ? activeNetwork.getTypeName() : "未知";
        }
}


                                        /*代码解释*/


// 定义一个BroadcastReceiver子类,用于监听网络状态变化
public class NetworkChangeReceived extends BroadcastReceiver {
    
    // 当接收到广播时调用此方法
    @Override
    public void onReceive(Context context, Intent intent) {
        // 检查Intent的动作是否为网络连接状态改变
        if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
            
            // 调用私有方法检查网络是否连接
            boolean isConnected = isNetworkConnected(context);
            
            // 根据网络连接状态构建提示消息
            String statusMessage = isConnected ? "连接" : "断开";
            
            // 获取网络类型
            String networkType = NetworkType(context);
            
            // 使用Toast显示网络状态和类型
            Toast.makeText(context, "网络已" + statusMessage + ",类型" + networkType, Toast.LENGTH_SHORT).show();
        }
    }

    // 私有方法,用于检查网络是否处于连接状态
    private boolean isNetworkConnected(Context context) {
        // 获取系统的ConnectivityManager服务
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        
        // 获取当前活动的网络信息
        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
        
        // 判断网络信息是否非空并且网络正在连接或已经连接
        return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
    }

    // 私有方法,用于获取网络类型
    private String NetworkType(Context context) {
        // 获取系统的ConnectivityManager服务
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        
        // 获取当前活动的网络信息
        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
        
        // 如果网络信息非空,返回网络类型名;否则返回"未知"
        return activeNetwork != null ? activeNetwork.getTypeName() : "未知";
    }
}
第二种代码逻辑:

public class NetworkChangeReceived extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
            Toast.makeText(context,checkNetworkConnectionAndGetType(context), Toast.LENGTH_SHORT).show();
        }
    }
    public static String checkNetworkConnectionAndGetType(Context context) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = cm.getActiveNetworkInfo();
        if (info != null && info.isConnectedOrConnecting()) {
            // 网络已连接,返回网络类型名称
            return "连接"+info.getTypeName();
        } else {
            // 未连接网络
            return "断开";
        }
    }
}



                                        /*代码解释*/




/**
 * NetworkChangeReceived 类,继承自 BroadcastReceiver,用于监听和响应网络状态变化的广播事件。
 */
public class NetworkChangeReceived extends BroadcastReceiver {

    /**
     * 当接收到广播时调用此方法。
     * 
     * @param context 上下文,提供了应用程序的环境信息。
     * @param intent Intent 对象,包含了广播的数据和动作。
     */
    @Override
    public void onReceive(Context context, Intent intent) {
        /**
         * 检查 Intent 的动作是否是网络状态改变的广播。
         * 如果是,则获取网络状态和类型的信息,并通过 Toast 显示给用户。
         */
        if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {
            Toast.makeText(context, checkNetworkConnectionAndGetType(context), Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * 检查当前设备的网络连接状态,并返回连接状态和网络类型。
     * 
     * @param context 上下文,提供了应用程序的环境信息。
     * @return 返回一个字符串,描述了当前网络的连接状态和类型。
     */
    public static String checkNetworkConnectionAndGetType(Context context) {
        // 从系统服务中获取 ConnectivityManager 实例,用于管理网络连接。
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        
        // 获取当前活动的网络信息。
        NetworkInfo info = cm.getActiveNetworkInfo();

        if (info != null && info.isConnectedOrConnecting()) {
            // 如果网络已连接,返回网络类型名称,并且前面加上"连接"两个字。
            return "连接" + info.getTypeName();
        } else {
            // 如果网络未连接,返回"断开"。
            return "断开";
        }
    }
}
2.Mainactivity中应用NetworkChangeReceived

public class MainActivity extends AppCompatActivity {
    private NetworkChangeReceived networkChangeReceived;
    private static final int PERMISSION_REQUEST_CODE = 1;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this);
        setContentView(R.layout.activity_main);
        if (ContextCompat.checkSelfPermission(this,
                android.Manifest.permission.ACCESS_NETWORK_STATE)!=PackageManager.PERMISSION_GRANTED){
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.ACCESS_NETWORK_STATE}, PERMISSION_REQUEST_CODE);
        }
        else {
            registerReceiver();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == PERMISSION_REQUEST_CODE){
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            registerReceiver();
            }
            else {
                Toast.makeText(this, "没有网络权限,无法检测网络状态", Toast.LENGTH_SHORT).show();
            }
        }
    }
    private void registerReceiver(){
        networkChangeReceived = new NetworkChangeReceived();
        IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
        registerReceiver(networkChangeReceived,filter);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (networkChangeReceived != null) {
            unregisterReceiver(networkChangeReceived);
        }
    }
}





                                        /*代码解释*/



/**
 * MainActivity 类,继承自 AppCompatActivity,是应用的主要活动入口点。
 */
public class MainActivity extends AppCompatActivity {

    // 声明一个 NetworkChangeReceived 对象,用于接收网络状态变化的广播。
    private NetworkChangeReceived networkChangeReceived;

    // 定义一个常量,用于请求权限时的请求码。
    private static final int PERMISSION_REQUEST_CODE = 1;

    /**
     * 在 Activity 创建时调用。
     * 
     * @param savedInstanceState 可能包含先前实例状态的 Bundle 对象。
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        EdgeToEdge.enable(this); // 这里假设 EdgeToEdge 是一个库的方法,用于设置全屏边缘到边缘的界面。
        
        setContentView(R.layout.activity_main); // 设置 Activity 的布局资源。

        // 检查是否已有访问网络状态的权限。
        if (ContextCompat.checkSelfPermission(this,
                android.Manifest.permission.ACCESS_NETWORK_STATE) != PackageManager.PERMISSION_GRANTED) {
            // 请求访问网络状态的权限。
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.ACCESS_NETWORK_STATE}, PERMISSION_REQUEST_CODE);
        } else {
            // 如果已经有权限,则注册网络状态变化的广播接收器。
            registerReceiver();
        }
    }

    /**
     * 当权限请求的结果返回时调用。
     * 
     * @param requestCode 请求码,用于识别哪个权限请求的回调。
     * @param permissions 请求的权限数组。
     * @param grantResults 权限请求的结果数组。
     */
    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == PERMISSION_REQUEST_CODE) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // 如果权限被授予,注册网络状态变化的广播接收器。
                registerReceiver();
            } else {
                // 如果权限被拒绝,显示一个 Toast 提示用户。
                Toast.makeText(this, "没有网络权限,无法检测网络状态", Toast.LENGTH_SHORT).show();
            }
        }
    }

    /**
     * 注册网络状态变化的广播接收器。
     */
    private void registerReceiver() {
        networkChangeReceived = new NetworkChangeReceived();
        IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
        registerReceiver(networkChangeReceived, filter);
    }

    /**
     * 在 Activity 销毁时调用。
     */
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (networkChangeReceived != null) {
            // 在 Activity 销毁前,取消注册网络状态变化的广播接收器。
            unregisterReceiver(networkChangeReceived);
        }
    }
}


四、静态注册实现开机启动

        动态注册的广播接收器可以自由地控制注册与注销,在灵活性方面有很大的优势,但是它也存 在着一个缺点,即必须要在程序启动之后才能接收到广播,因为注册的逻辑是写 在onCreate() 方法中的。这里我们准备让程序接收一条开机广播,当收到这条广播时就可以在onReceive() 方法里执 行相应的逻辑,从而实现开机启动的功能。可以使用Android Studio提供的快捷方式来创建一个 广播接收器,右击com.example.broadcasttest包→New→Other→Broadcast Receiver。

创建广播接收器的窗口

Exported 属性表示是否允许 这个广播接收器接收本程序以外的广播,Enabled 属性表示是否启用这个广播接收器。勾选这 两个属性,点击Finish完成创建。

自动新建一个类,并继承BroadcastReceiver

public class MyReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "My Receiver", Toast.LENGTH_LONG).show();
    }
}

五、AndroidManifest.xml文件中注册

        静态的广播接收器一定要在AndroidManifest.xml文件中注册才可以使用,不过由于我们是 使用Android Studio的快捷方式创建的广播接收器,因此注册这一步已经被自动完成了。打开 AndroidManifest.xml文件瞧一瞧,代码如下所示:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.MyApplication"
        tools:targetApi="31">
        <receiver
            android:name=".MyReceiver"
            android:enabled="true"
            android:exported="true">
          <intent-filter>
              <action android:name="android.intent.action.BOOT_COMPLETED"/>
          </intent-filter>
        </receiver>

        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>



                                <!-- 代码解释 -->




<?xml version="1.0" encoding="utf-8"?>
<!-- 指定文档的版本和编码方式 -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <!-- 声明命名空间,定义了 Android 和工具属性的前缀 -->

    <!-- 声明应用需要的权限 -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <!-- 允许应用访问网络状态 -->
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
    <!-- 允许应用接收设备启动完成的广播 -->

    <application
        android:allowBackup="true"
        <!-- 应用的数据是否允许被备份 -->
        android:dataExtractionRules="@xml/data_extraction_rules"
        <!-- 数据提取规则,定义哪些数据可以被提取 -->
        android:fullBackupContent="@xml/backup_rules"
        <!-- 完整备份内容规则,定义哪些数据应该包含在完整备份中 -->
        android:icon="@mipmap/ic_launcher"
        <!-- 应用图标资源的引用 -->
        android:label="@string/app_name"
        <!-- 应用的显示名称 -->
        android:roundIcon="@mipmap/ic_launcher_round"
        <!-- 圆形应用图标资源的引用,适用于圆形图标显示的场景 -->
        android:supportsRtl="true"
        <!-- 是否支持从右到左的语言布局方向 -->
        android:theme="@style/Theme.MyApplication"
        <!-- 应用主题的样式引用 -->
        tools:targetApi="31">
        <!-- 工具属性,指定应用的目标 API 级别 -->

        <!-- 定义一个广播接收器 -->
        <receiver
            android:name=".MyReceiver"
            android:enabled="true"
            <!-- 是否启用该接收器 -->
            android:exported="true">
            <!-- 是否允许其他应用发送广播到该接收器 -->
            <intent-filter>
                <!-- 定义接收器能够接收的广播类型 -->
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
                <!-- 接收设备启动完成的广播 -->
            </intent-filter>
        </receiver>

        <!-- 定义一个活动 -->
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <!-- 活动的类名和是否允许外部应用启动 -->
            <intent-filter>
                <!-- 定义活动能够响应的意图类型 -->
                <action android:name="android.intent.action.MAIN" />
                <!-- 活动是应用的入口点 -->
                <category android:name="android.intent.category.LAUNCHER" />
                <!-- 活动属于 Launcher 类别,意味着它会出现在应用启动器中 -->
            </intent-filter>
        </activity>
    </application>
</manifest>

        由于Android系统启动完成后会发出一条值为android.intent.action.BOOT_COMPLETED 的广播,因此我们在 标签里添加了相应的action。另外,监听系统开机广播 也是需要声明权限的,可以看到,我们使用 标签又加入了一 条android.permission.RECEIVE_BOOT_COMPLETED 权限。目前为止,我们在广播接收器的onReceive() 方法中都只是简单地使用Toast提示了一段文 本信息,当你真正在项目中使用到它的时候,就可以在里面编写自己的逻辑。需要注意的是, 不要在onReceive() 方法中添加过多的逻辑或者进行任何的耗时操作,因为在广播接收器中 是不允许开启线程的,当onReceive() 方法运行了较长时间而没有结束时,程序就会报错。 因此广播接收器更多的是扮演一种打开程序其他组件的角色,比如创建一条状态栏通知,或者 启动一个服务等,

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1894077.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android使用http加载自建服务器静态网页

最终效果如下图&#xff0c;成功加载了电脑端的静态网页内容&#xff0c;这是一个xml文件。 电脑端搭建http服务器 使用“Apache Http Server”&#xff0c;下载地址是&#xff1a;https://httpd.apache.org/download.cgi。具体操作步骤&#xff0c;参考&#xff1a;Apache …

使用 urllib OpenSSL 时遇到的问题及解决

题意&#xff1a; ImportError: urllib3 v2.0 only supports OpenSSL 1.1.1, currently the ssl module is compiled with LibreSSL 2.8.3 当前使用的 urllib3 版本&#xff08;v2.0&#xff09;仅支持 OpenSSL 1.1.1 或更高版本&#xff0c;但你的 Python 环境中的 ssl 模块…

Windows 11 安装 Python 3.11 完整教程

Windows 11 安装 Python 3.11 完整教程 一、安装包安装 1. 下载 Python 3.11 安装包 打开浏览器,访问 Python 官方下载页面。点击“Download Python 3.11”,下载适用于 Windows 的安装包(Windows installer)。 2. 安装 Python 3.11 运行下载的安装包 python-3.11.x-amd6…

django @login_required 为什么会自动重定向到/accounts/login/?next=/myblog/post/new/

在Django中&#xff0c;login_required 装饰器用于确保用户在访问某个视图时已经登录。如果用户未登录&#xff0c;那么Django会自动重定向用户到登录页面。默认情况下&#xff0c;Django使用/accounts/login/作为登录URL。如果用户试图访问一个需要登录的视图&#xff0c;比如…

eNSP-VLAN虚拟局域网

一、出现Vlan的原因 同一个局域网&#xff0c;使用交换机连接&#xff0c;虽然比集线器相连&#xff0c;降低了广播风暴&#xff0c;但是局域网主机数量够多的时候&#xff0c;正常的广播数据(arp、dhcp)也很影响网络性能&#xff0c;所以还需要进一步降低广播风暴——VLAN (图…

Altium Designer专业PCB设计软件下载安装 Altium Designer安装包下载获取

在电子设计的广袤领域中&#xff0c;PCB设计无疑占据着重要的地位。而Altium Designer作为一款业界领先的电子设计自动化软件&#xff0c;其提供的先进布局工具&#xff0c;无疑为设计师们打开了一扇通往高效、精确设计的大门。 在PCB设计的核心环节——布局中&#xff0c;Alti…

xinput1_4.dll丢失怎么办?如何来解决xinput1_4.dll丢失问题

在电脑启动游戏时候经常会出现一些问题导致游戏无法打开运行&#xff0c;其中找不到xinput1_4.dll文件丢失就是常见问题之一&#xff0c;那么当遇到xinput1_4.dll丢失怎么办呢&#xff1f;今天就教大家如何来解决xinput1_4.dll丢失问题。 一、xinput1_4.dll文件详解 XINPUT1_4…

一款优秀、亮眼的开源堡垒机

介绍 在运维的日常工作中&#xff0c;登陆服务器操作不可避免&#xff0c;为了更安全的管控服务器&#xff0c;但凡有点规模的公司都会上线堡垒机系统&#xff0c;堡垒机能够做到事前授权、事中监控、事后审计&#xff0c;同时也可以满足等保合规要求。 提到堡垒机&#xff0…

小白 | 华为云docker设置镜像加速器

一、操作场景 通过docker pull命令下载镜像中心的公有镜像时&#xff0c;往往会因为网络原因而需要很长时间&#xff0c;甚至可能因超时而下载失败。为此&#xff0c;容器镜像服务提供了镜像下载加速功能&#xff0c;帮助您获得更快的下载体验。 二、约束与限制 构建镜像的客…

LVS+Nginx高可用集群--基础篇

1.集群概述 单体部署&#xff1a; 可以将上面内容分别部署在不同的服务器上。 单体架构的优点&#xff1a; 小团队成型就可完成开发&#xff0c;测试&#xff0c;上线 迭代周期短&#xff0c;速度快 打包方便&#xff0c;运维简单 单体架构的挑战&#xff1a;单节点宕机造成…

SecureCRT--使用sftp上传和下载文件

原文网址&#xff1a;SecureCRT--使用sftp上传和下载文件_IT利刃出鞘的博客-CSDN博客 简介 本文介绍SecureCRT如何在软件内直接上传和下载文件。 SecureCRT可以用如下两种方法上传和下载文件&#xff1a; 自带的sftp插件服务器安装rz/sz命令 本文介绍第一种方法&#xff0…

12个视觉艺术分类

视觉设计可以按照多种方式进行分类&#xff0c;这些分类通常基于设计的目的、风格或应用场景。本文为大家介绍12种视觉设计&#xff0c;分别是平面设计、标志设计、包装设计、用户界面设计 (UI Design)、用户体验设计 (UX Design)、插图设计、网页设计、动画设计、展览设计、环…

Jenkins 下使用 Node 和 Npm(借助 nvm-wrapper 插件)构建前端程序

一、前言 搭建完Jenkins后&#xff0c;如何使用node进行构建前端呢&#xff0c;多个项目会使用的node的多个版本。如何动态指定node的版本进行构建呢。 方案一&#xff1a; 安装多个node版本&#xff0c;然后进行指定。这样比较麻烦。 方案二&#xff1a; 使用Jenkins的nv…

C++时区转换

#include <iostream> #include "cctz/civil_time.h" #include "cctz/time_zone.h"// 时区转换库 // https://github.com/google/cctzint test() {for (cctz::civil_day d(2016, 2, 1); d < cctz::civil_month(2016, 3); d) {std::cout << &…

必备的 Adobe XD 辅助工具

想要高效便捷的使用 Adobe XD&#xff0c; Adobe XD 插件是必不可少的&#xff0c; Adobe XD 的插件非常多&#xff0c;但 90%都是英文&#xff0c;并且良莠不齐。在这儿挑选 9 个好用的 Adobe XD 插件给大家&#xff0c;这里是我整理的一些实用 Adobe XD 插件&#xff0c;让你…

Python基础小知识问答系列-列表元素次数统计

1. 问题&#xff1a; 怎样统计列表中元素出现次数&#xff1f; 怎样获得列表中元素出现次数排在前n的元素&#xff1f; 怎样汇总两个列表中元素出现次数的信息&#xff1f; 2. 解决方法&#xff1a; 使用collections模块中的Counter函数。 示例&#xff1a; i…

[Mysql] 的基础知识和sql 语句.教你速成(下)——数据库的约束篇

目录 前言 约束 一.我们为什么需要约束 二.常见的约束类型 NOT NULL 约束 UNIQUE 约束 DEFAULT 约束 PRIMARY KEY FOREIGN KEY CHECK约束 原因&#xff1a; 结尾 前言 距离上篇的更新已经快两周了,这个时候大伙都已经考完了吧!现在更新多少有点马后炮,但是没办法呀…

Qt:5.QWidget属性介绍(Enabled属性-控件可用性设置、geometry属性-控件位置/大小设置)

目录 一、 QWidget属性的介绍&#xff1a; 二、Enabled属性-控件可用性设置&#xff1a; 2.1Enabled属性的介绍&#xff1a; 2.2获取控件当前可用状态的api——isEnabled()&#xff1a; 2.3设置控件当前的可用状态的api—— setEnabled() &#xff1a; 2.4 实例&#xff…

ARM架构 AArch64 基础知识介绍

介绍 aarch64是 ARM 架构的 64 位版本&#xff0c;它是 ARMv8 架构的一部分&#xff0c;被设计用来提供更高的性能和更大的地址空间&#xff0c;同时保持与 32 位 ARM 架构的兼容性。AArch64 是 ARMv8 的 64 位指令集架构&#xff08;ISA&#xff09;&#xff0c;它提供了丰富的…

【高级篇】第10章 Elasticsearch 集群管理与扩展

在本章中,我们将深入探讨Elasticsearch集群的管理与扩展策略,旨在帮助读者构建一个既能应对大规模数据处理需求,又能保持高可用性和弹性的系统架构。我们将从集群架构设计入手,解析不同节点的角色与配置,然后转向节点发现与配置同步机制,最后讨论水平扩展与容错策略,确保…