《第一行代码》 第五章:详解广播机制
如果你了解网络通信原理应该会知道,在一个 IP 网络范围中最大的IP 地址是被保留作为广播地址来使用的。比如某个网络的 IP 范围是 192.168.0XXX,子网掩码是255.255.255.0那么这个网络的广播地址就是 192.168.0255广播数据包会被发送到同-网络上的所有端口,这样在该网络中的每台主机都将会收到这条广播。
安卓系统中也有这样的广播机制。
一,广播机制简介
主要氛围标准广播和有序广播两种。
1,标准广播
标准广播是一种完全异步执行的广播,在广播发出之后,所有的广播接收器几乎都会在同一时刻接收到这条广播消息,因此它们之间没有任何先后顺序可言。这种广播的效率会比较高,但同时也意味着它是无法被截断的。
2,有序广播
则是一种同步执行的广播,在广播发出之后,同一时刻只会有一个广播接收器能够收到这条广播消息,当这个广播接收器中的逻辑执行完毕后广播才会继续传递。所以此时的广播接收器是有先后顺序的,优先级高的广播接收器就可以先收到广播消息,并且前面的广播接收器还可以截断正在传递的广播,这样后面的广播接收器就无法收到广播消息了。
二,接收系统广播
1,动态注册监听网络变化
public class MainActivity extends AppCompatActivity {private IntentFilter intentFilter;private NetworkChangeReceiver networkChangeReceiver;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);intentFilter =new IntentFilter();intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");networkChangeReceiver=new NetworkChangeReceiver();registerReceiver(networkChangeReceiver,intentFilter);}class NetworkChangeReceiver extends BroadcastReceiver{@Overridepublic void onReceive(Context context, Intent intent) {Toast.makeText(context, "网络发生了变化", Toast.LENGTH_SHORT).show();}}@Overrideprotected void onDestroy() {super.onDestroy();unregisterReceiver(networkChangeReceiver);}
}
具体的步骤如下:
1,定义内部类NetworkChangeReceiver 继承BroadcastReceiver
2,重写onReceive,当网络发生变化的时候就会执行这里的代码。
3,创建一个intentFilter 实例
4,给这个intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE"),以此来捕获网咯变化时系统发出的对应广播。
5, registerReceiver(networkChangeReceiver,intentFilter);注册这个网络变化的广播捕捉器
6,在活动销毁的时候,要记得清除这个捕捉器unregisterReceiver(networkChangeReceiver);
单单是提示网络变化还不够,实际使用时,我们常常需要判断是否有网络。于是可以修改NetworkChangeReceiver 类中的onReceive方法:
class NetworkChangeReceiver extends BroadcastReceiver{@Overridepublic void onReceive(Context context, Intent intent) {//获取系统服务类,它是专门用来管理网络的ConnectivityManager connectivityManager =(ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);//获取到networkInfo实例NetworkInfo networkInfo=connectivityManager.getActiveNetworkInfo();if(networkInfo!=null&&networkInfo.isAvailable()){Toast.makeText(context, "现在有网络", Toast.LENGTH_SHORT).show();}else{Toast.makeText(context, "现在没有网络", Toast.LENGTH_SHORT).show();}}}
当然获取网络状态常常需要用户授权,这个是在AndroidManifest.xml设置的:
<manifest><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
</manifest>
2,静态注册实现开机启动
动态注册虽然可以自由地控制注册与注销,但是它必须在app启动之后才能执行。
那如果想要app未开启的时候就执行呢?这就需要使用到静态注册。
然后修改其中的代码:
public class BootCompleteReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {// TODO: This method is called when the BroadcastReceiver is receiving// an Intent broadcast.Toast.makeText(context, "静态注册的广播器", Toast.LENGTH_SHORT).show();}
}
另外,静态的广播接收器一定要在AndroidManifest.xml中注册,因为是用AS创建的,它已经帮我们自动注册了:
<receiverandroid:name=".BootCompleteReceiver"android:enabled="true"android:exported="true"></receiver>
但是现在还不够,因为开机自启是需要权限的:
到目前为止,我们在广播接收器的 onReceive()方法中都只是简单地使用 Toast提示了一段文本信息,当你真正在项目中使用到它的时候,就可以在里面编写自己的逻辑。需要注意的是不要在 onReceive()方法中添加过多的逻辑或者进行任何的耗时操作,因为在广播接收器中是不允许开启线程的,当 onReceive()方法运行了较长时间而没有结束时,程序就会报错。因此广播接收器更多的是扮演一种打开程序其他组件的角色,比如创建一条状态栏通知,或者启动一个服务等。
三,发送自定义广播
1,发送标准广播
在发送广播之前,我们需要先定义一个广播接收器来接收这个广播才行,不然发出去也是白发。
第一步:新建MyBroadcastReceiver类
public class MyBroadcastReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {Toast.makeText(context, "广播接收器信息", Toast.LENGTH_SHORT).show();}
}
第二步:在menifest.xml中对广播进行修改
<receiverandroid:name=".MyBroadcastReceiver"android:enabled="true"android:exported="true"><intent-filter><action android:name="com.example.broadcasttest.MY_BROADCAST"/></intent-filter></receiver>
这里也可以注册要接受的广播,通过name指明是MyBroadcastReceiver这个接收器接收,需要接收的广播是com.example.broadcasttest.MY_BROADCAST。
第三步:修改activity_main.xml文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"><Buttonandroid:layout_width="match_parent"android:layout_height="wrap_content"android:text="发送广播按钮"android:id="@+id/button"/></LinearLayout>
第四步:修改MainActivity中的代码
public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button button=(Button) findViewById(R.id.button);button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Intent intent =new Intent("com.example.broadcasttest.MY_BROADCAST");sendBroadcast(intent);}});}
}
利用的就是Intent 来使用sendBroadcast发送广播。
路径是这样的:
1,activity中点击按钮,利用Intent发送广播
2,menifest.xml声明自定义的广播是com.example.broadcasttest.MY_BROADCAST,且对应用MyBroadcastReceiver广播接收器处理
3,MyBroadcastReceiver广播接收器处理接收到的广播。
2,发送标准广播,让另一个程序接收
在1中,我们已经创建了一个标准广播
现在我们要新建一个项目,然后接收该广播。
新建广播接收器:AnotherBroadcastMyReceiver
public class AnotherBroadcastMyReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {Toast.makeText(context,"接收广播1111",Toast.LENGTH_SHORT).show();}
}
然后再在menifext文件中自定义其接收的广播器特征:
<receiverandroid:name=".AnotherBroadcastMyReceiver"android:enabled="true"android:exported="true" ><intent-filter><action android:name="com.example.broadcasttest.MY_BROADCAST"/></intent-filter></receiver>
这样之后,点击上个程序的发送广播,就会发现,这个程序的广播接收器能够接收到该广播。
3,发送有序广播
有序广播上文说过,就是可以被截断,按照顺序发送的广播。
打开1中的项目,修改MainActivity文件:
public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button button=(Button) findViewById(R.id.button);button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Intent intent =new Intent("com.example.broadcasttest.MY_BROADCAST");sendOrderedBroadcast(intent,null);}});}
}
主要就是sendOrderedBroadcast(intent,null);也就是发送广播的方式改成了有序广播。
这时候点击发送按钮,同样时两个程序都能接收到广播。
4,有序广播设置接收顺序
主要就是intent-filter标签中的 android:priority="100"属性,优先级越高的广播接收器越先接收到。
给当前项目的menifest文件设置:
<receiverandroid:name=".MyBroadcastReceiver"android:enabled="true"android:exported="true"><intent-filter android:priority="100"><action android:name="com.example.broadcasttest.MY_BROADCAST"/></intent-filter>
</receiver>
这样一来,该程序的广播接收器就会优先接收到广播了。
5,有序广播的截断
上文已经设置了该程序的广播接收器优先接收到该广播,因为该广播是有序广播,所以接收到之后可以进行截断处理,让后续的广播接收器无法接收。
public class MyBroadcastReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {Toast.makeText(context, "广播接收器信息", Toast.LENGTH_SHORT).show();abortBroadcast();}
}
主要就是使用 abortBroadcast();截断广播的发送。
四,使用本地广播
上文所学的都是全局广播,不仅别的程序能随便给我的程序传,我的程序发送的广播也能被其他程序接收到。为了安全起见,我们希望有只在我们自个儿的程序中发送的广播。这就是本地广播。
本地广播的用法并不复杂,主要就是使用了一个LocalBoradcast,anager来对广播进行管理,并且提供了发送广播和注册广播接收器的方法。
修改MainActivity中的代码:
public class MainActivity extends AppCompatActivity {private IntentFilter intentFilter;private LocalReceiver localReceiver;private LocalBroadcastManager localBroadcastManager;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button button=(Button) findViewById(R.id.button);localBroadcastManager=localBroadcastManager.getInstance(this);button.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {Intent intent =new Intent("com.example.broadcasttest.LOCAL_BROADCAST");localBroadcastManager.sendBroadcast(intent);}});intentFilter=new IntentFilter();intentFilter.addAction("com.example.broadcasttest.LOCAL_BROADCAST");localReceiver=new LocalReceiver();localBroadcastManager.registerReceiver(localReceiver,intentFilter);}class LocalReceiver extends BroadcastReceiver{@Overridepublic void onReceive(Context context, Intent intent) {Toast.makeText(context, "接收到本地广播", Toast.LENGTH_SHORT).show();}}
}
这里可以看到,和之前的动态注册广播器一样的写法。
值得注意的是,本地广播只能动态注册,因为要程序运行后才有广播的容器。
五,广播的最佳实践-实现强制下线功能
比如说QQ 号在别处登录了,就会将你强制挤下线。其实实现强制下线功能的思路也比较简单,只需要在界面上弹出一个对话框,让用户无法进行任何其他操作,必须要点击对话框中的确定按钮,然后回到登录界面即可。可是这样就存在着一个问题,因为当我们被通知需要强制下线时可能正处于任何一个界面,难道需要在每个界面上都编写一个弹出对话框的逻辑?
这里我们可以使用广播的方式实现。
1,创建一个ActivityCollector类用于管理所有活动
public class ActivityCollector {public static List<Activity> activities=new ArrayList<Activity>();public static void addActivity(Activity activity) {activities.add(activity);}public static void removeActivity(Activity activity) {activities.remove(activity);}public static void finishAll(){for (Activity activity:activities){if(!activity.isFinishing()){activity.finish();}}}
}
2,新建BaseActivity类作为搜友活动的父类
public class BaseActivity extends AppCompatActivity {@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);ActivityCollector.addActivity(this);}@Overrideprotected void onDestroy() {super.onDestroy();ActivityCollector.removeActivity(this);}
}
3,新建LoginActivity2文件,生成并书写对应布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"><LinearLayoutandroid:orientation="horizontal"android:layout_width="match_parent"android:layout_height="60dp"><TextViewandroid:layout_width="90dp"android:layout_height="wrap_content"android:layout_gravity="center_vertical"android:textSize="18sp"android:text="账号:"/><EditTextandroid:id="@+id/account"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:layout_gravity="center_vertical"/></LinearLayout><LinearLayoutandroid:orientation="horizontal"android:layout_width="match_parent"android:layout_height="60dp"><TextViewandroid:layout_width="90dp"android:layout_height="wrap_content"android:layout_gravity="center_vertical"android:textSize="18sp"android:text="密码:"/><EditTextandroid:id="@+id/password"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:layout_gravity="center_vertical"android:inputType="textPassword"/></LinearLayout><Buttonandroid:id="@+id/login"android:layout_width="match_parent"android:layout_height="60dp"android:text="登录"/>
</LinearLayout>
4,修改3中创建的LoginActivity2文件
public class LoginActivity2 extends BaseActivity {private EditText accountEdit;private EditText passwordEdit;private Button login;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_login2);accountEdit=(EditText) findViewById(R.id.account);passwordEdit=(EditText) findViewById(R.id.password);login=(Button) findViewById(R.id.login);login.setOnClickListener(new View.OnClickListener(){@Overridepublic void onClick(View view) {String account=accountEdit.getText().toString();String password=passwordEdit.getText().toString();if(account.equals("admin")&& password.equals("123456")){Intent intent =new Intent(LoginActivity2.this,MainActivity.class);startActivity(intent);finish();}else{Toast.makeText(LoginActivity2.this, "账密错误", Toast.LENGTH_SHORT).show();}}});}
}
这样,我们已经写好了登录页面。登录成功后会到MainActivity页面。
5,于是修改MainActivity页面的代码:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"><Buttonandroid:id="@+id/force_office"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="强制下线"/></LinearLayout>
修改对应的活动代码:
public class MainActivity extends BaseActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Button forceOffline=(Button) findViewById(R.id.force_office);forceOffline.setOnClickListener(new View.OnClickListener(){@Overridepublic void onClick(View view) {Intent intent =new Intent("com.example.broadcastbestpractice.FORCE_OFFLINE");sendBroadcast(intent);}});}
}
我们再按钮的点击事件里面发送了一条广播,广播的值为:com.example.broadcastbestpractice.FORCE_OFFLINE,这条广播就是用于通知强制下线的。
那么毫无疑问,我们现在就需要创建一个广播接收器来接收这个广播。由于广播接收器需要弹窗来阻塞用户的所有正常操作。
如果创建的是一个静态注册的广播接收器,是没有办法在 onReceive()方法里弹出对话框这样的UI控件的,而我们显然也不可能在每个活动中都去注册一个动态的广播接收器。
那么到底应该怎么办呢? 答案其实很明显,只需要在 BaseActivity 中动态注册一个广播接收器就可以了,因为所有的活动都是继承自 BaseActivity 的。
6,修改BaseActivity中的代码
public class BaseActivity extends AppCompatActivity {private ForceOfflineReceiver receiver;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);ActivityCollector.addActivity(this);}@Overrideprotected void onDestroy() {super.onDestroy();ActivityCollector.removeActivity(this);}@Overrideprotected void onResume() {super.onResume();IntentFilter intentFilter=new IntentFilter();intentFilter.addAction("com.example.broadcastbestpractice.FORCE_OFFLINE");receiver =new ForceOfflineReceiver();registerReceiver(receiver,intentFilter);}@Overrideprotected void onPause() {super.onPause();if(receiver!=null){unregisterReceiver(receiver);receiver=null;}}class ForceOfflineReceiver extends BroadcastReceiver{@Overridepublic void onReceive(Context context, Intent intent) {AlertDialog.Builder builder =new AlertDialog.Builder(context);builder.setTitle("提示");builder.setMessage("信息提示");builder.setCancelable(false);builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialogInterface, int i) {ActivityCollector.finishAll();Intent intent= new Intent(context,LoginActivity2.class);context.startActivity(intent);}});builder.show();}}
}
先是创建一个广播接收器,接收到广播后,展开弹窗,点击确定后,会关闭所有活动然后打开登录活动页。
7,修改Menifest文件,让登录页成为主活动
<activity android:name=".LoginActivity2"android:exported="true"><intent-filter><action android:name="android.intent.action.MAIN" /><category android:name="android.intent.category.LAUNCHER" /></intent-filter></activity><activityandroid:exported="true"android:name=".MainActivity"></activity>
实现的效果:
相关文章:
《第一行代码》 第五章:详解广播机制
如果你了解网络通信原理应该会知道,在一个 IP 网络范围中最大的IP 地址是被保留作为广播地址来使用的。比如某个网络的 IP 范围是 192.168.0XXX,子网掩码是255.255.255.0那么这个网络的广播地址就是 192.168.0255广播数据包会被发送到同-网络上的所有端口…...
Leetcode(每日一题)——1139. 最大的以 1 为边界的正方形
摘要 1139. 最大的以 1 为边界的正方形 一、以1为边界的最大正方形 1.1 动态规划 第530题需要正方形所有网格中的数字都是1,只要搞懂动态规划的原理,代码就非常简洁。而这题只要正方形4条边的网格都是1即可,中间是什么数字不用管。 这题…...
YOLOv5:GitHub两万八Star项目
来源:投稿 作者:王同学 编辑:学姐 Yolov5详解 官方源码仓库:https://github.com/ultralytics/yolov5 相关论文:未发表(改进点都被你们抢先发了) 0 前言 截止到2022年7月,Yolov5项…...
袋鼠云产品功能更新报告04期丨2023年首次,产品升级“狂飙”
新的一年我们加紧了更新迭代的速度,增加了数据湖平台EasyLake和大数据基础平台EasyMR,超40项功能升级优化。我们将继续保持产品升级节奏,满足不同行业用户的更多需求,为用户带来极致的产品使用体验。 以下为袋鼠云产品功能更新报…...
如何在Power Virtual Agents中使用Power Automate
今天我们来介绍一下如何在Power Virtual Agents中使用PowerAutomate。我们以通过在PVA聊天机器人的对话框中输入“发布通知”后会把预设好的通知信息自动发布到Teams中的某个团队中为例。首先进入PVA聊天机器人编辑界面后选择“主题”-“新建主题”。 在“新建主题”中添加“触…...
BXC6332A第二代智能头盔方案助力电动车市场,为安全保驾护航
随着2020年6月1日起,公安部交管局在全国开展“一盔一带”安全守护行动,摩托车、电动车驾驶人乘车人按照规定正确使用头盔,是保障司乘安全的一道重要屏障,据统计,摩托车、电动自行车驾乘人员死亡事故中约80%为颅脑损伤致…...
浮点数值计算精度丢失问题剖析及解决方法
文章目录1、原因分析2、解决方法2.1、Java中使用 BigDecimal 类2.2、JavaScript 中解决计算精度丢失的问题3、使用建议1、原因分析 首先我们来看个反直觉的浮点数值计算 System.out.println(0.3*3);有的同学可能要问为啥不是0.9? 首先要知道为什么会产生这个问题…...
字符串匹配 - 模式预处理:朴素算法(Naive)(暴力破解)
朴素的字符串匹配算法又称为暴力匹配算法(Brute Force Algorithm),最为简单的字符串匹配算法。算法简介朴素的字符串匹配算法又称为暴力匹配算法(Brute Force Algorithm),它的主要特点是:没有预…...
CVE-2021-42278 CVE-2021-42287域内提权漏洞
漏洞介绍2021 年 11 月 9 日,国外研究员在推特上发布了AD相关的 CVE,CVE-2021-42278 & CVE-2021-42287 ,两个漏洞组合可导致域内普通用户权限提升至域管权限。CVE-2021-42278:是一个安全绕过漏洞,允许通过修改机器…...
关于IcmpSendEcho2的使用和回调问题
由于我的需求是短时间内ping多台机子,所以需要异步执行,微软提供的例子是同步方式的,根据微软官方提供的icmpSendEcho2 函数的信息 ,我需要定义一个空的宏PIO_APC_ROUTINE_DEFINED ,定义完之后,编译又出现…...
XQuery 术语
在 XQuery 中,有七种节点:元素、属性、文本、命名空间、处理指令、注释、以及文档节点(或称为根节点)。 XQuery 术语 节点 在 XQuery 中,有七种节点:元素、属性、文本、命名空间、处理指令、注释、以及文…...
会议论文分享-Security22-状态感知符号执行
Ferry: State-Aware Symbolic Execution for Exploring State-Dependent Program Paths1.引言2.问题陈述与分析2.1.实现状态感知符号执行的挑战2.2.真实程序的特征2.3.Ferry的模型2.3.1.程序状态的定义2.3.2.状态描述变量的特征3.Design3.1.Overview of Ferry3.2.状态描述变量识…...
吴恩达深度学习笔记(八)——卷积神经网络(上)
一、卷积相关 用一个ff的过滤器卷积一个nn的图像,假如padding为p,步幅为s,输出大小则为: [n2p−fs1][n2p−fs1][\frac{n2p-f}{s}1][\frac{n2p-f}{s}1][sn2p−f1][sn2p−f1] []表示向下取整(floor) 大部分深度学习…...
14 基数排序(桶排序)
文章目录1 基数排序基本思想2 基数排序的代码实现2.1 java2.2 scala3 基数排序总结1 基数排序基本思想 1) 基数排序(radix sort)属于“分配式排序”(distribution sort),又称“桶子法”(bucket sort&#…...
汉明距离Java解法
两个整数之间的 汉明距离 指的是这两个数字对应二进制位不同的位置的数目。 给你两个整数 x 和 y,计算并返回它们之间的汉明距离。 例: 输入:x 1, y 4 输出:2 解释: 1 (0 0 0 1) 4 (0 1 0 0) ↑ ↑ 上…...
Netty服务端请求接受过程源码剖析
目标 服务器启动后,客户端进行连接,服务器端此时要接受客户端请求,并且返回给客户端想要的请求,下面我们的目标就是分析Netty 服务器端启动后是怎么接受到客户端请求的。我们的代码依然与上一篇中用同一个demo, 用io.…...
金三银四春招特供|高质量面试攻略
🔰 全文字数 : 1万5千 🕒 阅读时长 : 20min 📋 关键词 : 求职规划、面试准备、面试技巧、谈薪职级 👉 公众号 : 大摩羯先生 本篇来聊聊一个老生常谈的话题————“面试”。利用近三周工作午休时间整理了这篇洋洋洒洒却饱含真诚…...
搭建Hexo博客-第4章-绑定自定义域名
搭建Hexo博客-第4章-绑定自定义域名 搭建Hexo博客-第4章-绑定自定义域名 搭建Hexo博客-第4章-绑定自定义域名 在这一篇文章中,我将会介绍如何给博客绑定你自己的域名。其实绑定域名本应该很简单的,但我当初在这上走了不少弯路,所以我觉得有…...
lightdb-sql拦截
文章目录LightDB - sql 审核拦截一 简介二 参数2.1 lightdb_sql_mode2.2 lt_firewall.lightdb_business_time三 规则介绍及使用3.1 select_without_where3.1.1 案例3.2 update_without_where/delete_without_where3.2.1 案例3.3 high_risk_ddl3.3.1 案例LightDB - sql 审核拦截…...
二进制中1的个数-剑指Offer-java位运算
一、题目描述编写一个函数,输入是一个无符号整数(以二进制串的形式),返回其二进制表达式中数字位数为 1 的个数(也被称为 汉明重量).)。提示:请注意,在某些语言(如 Java&…...
学自动化测试可以用这几个练手项目
练手项目的业务逻辑比较简单,只适合练手,不能代替真实项目。 学习自动化测试最难的是没有合适的项目练习。 测试本身既要讲究科学,又有艺术成分,单单学几个 api 的调用很难应付工作中具体的问题。 你得知道什么场景下需要添加显…...
2023年保健饮品行业分析:市场规模不断攀升,年度销额增长近140%
随着人们健康意识的不断增强,我国保健品市场需求持续增长,同时,保健饮品的市场规模也在不断攀升。 根据鲸参谋电商数据显示,2022年度,京东平台上保健饮品的年度销量超60万件,同比增长了约124%;该…...
2023-02-17 学习记录--TS-邂逅TS(一)
TS-邂逅TS(一) 不积跬步,无以至千里;不积小流,无以成江海。💪🏻 一、TypeScript在线编译器 https://www.typescriptlang.org/play/ 二、类型 1、普通类型 number(数值型ÿ…...
SpringMVC创建异步回调请求的4种方式
首先要明确一点,同步请求和异步请求对于客户端用户来讲是一样的,都是需客户端等待返回结果。不同之处在于请求到达服务器之后的处理方式,下面用两张图解释一下同步请求和异步请求在服务端处理方式的不同:同步请求异步请求两个流程…...
MySQL(二)表的操作
一、创建表 CREATE TABLE table_name ( field1 datatype, field2 datatype, field3 datatype ) character set 字符集 collate 校验规则 engine 存储引擎; 说明: field 表示列名 datatype 表示列的类型 character set 字符集,如…...
SpringCloud - 入门
目录 服务架构演变 单体架构 分布式架构 分布式架构要考虑的问题 微服务 初步认识 案例Demo 服务拆分注意事项 服务拆分示例 服务调用 服务架构演变 单体架构 将业务的所有功能集中在一个项目中开发,打成一个包部署优点: 架构简单部署成本低缺…...
进一步了解C++函数的各种参数以及重载,了解C++部分的内存模型,C++独特的引用方式,巧妙替换指针,初步了解类与对象。满满的知识,希望大家能多多支持
C的编程精华,走过路过千万不要错过啊!废话少说,我们直接进入正题!!!! 函数高级 C的函数提高 函数默认参数 在C中,函数的形参列表中的形参是可以有默认值的。 语法:返…...
Chapter6:机器人SLAM与自主导航
ROS1{\rm ROS1}ROS1的基础及应用,基于古月的课,各位可以去看,基于hawkbot{\rm hawkbot}hawkbot机器人进行实际操作。 ROS{\rm ROS}ROS版本:ROS1{\rm ROS1}ROS1的Melodic{\rm Melodic}Melodic;实际机器人:Ha…...
Sass的使用要点
Sass 是一个 CSS 预处理器,完全兼容所有版本的 CSS。实际上,Sass 并没有真正为 CSS 语言添加任何新功能。只是在许多情况下可以可以帮助我们减少 CSS 重复的代码,节省开发时间。 一、注释 方式一:双斜线 // 方式二:…...
计算机启动过程,从按下电源按钮到登录界面的详细步骤
1、背景 自接触计算机以来,一直困扰着我一个问题。当我们按下电脑的开机键后,具体发生了哪些过程呢?计算机启动的具体步骤是什么? 计算机启动过程通常分为五个步骤:电源自检、BIOS自检、引导设备选择、引导程序加载和…...
wordpress 上传文件大小/怎么做网站推广和宣传
1.Python虚拟环境创建首先我们为什么要创建虚拟环境呢?因为不同的项目所依赖的环境不一样,他们需要不同的第三方库等等。为了避免冲突,所以我们要创建虚拟环境,在次此我用的的Linux ubuntu和pycharm。在虚拟机上创建Python虚拟环境…...
柔造网站定制/代运营公司是怎么运营的
海淀区法院审结一起利用******他人电脑,获取他人隐私数据,借此敲诈勒索的案件,***者李金华来自江西瑞金,最终获刑6年。***者使用******受害者电脑,***者使用***窃取受害人隐私数据,通过邮件/QQ给受害人发消…...
西宁商城网站建设公司/seo推广是什么意思
第三卷 第十二章 年龄和性别预测 为了构建一个能够识别照片中人物年龄和性别的系统,我们将使用 Adience 数据集。我们训练两个模型,一个用于年龄识别,另一个用于性别识别。此外,我们还必须依靠更高级的计算机视觉算法,例如面部标志和面部对齐来帮助我们进行预处理 我们在分…...
沈阳市建设工程安全监督站网站/怎么创建网站赚钱
感兴趣python 字符串函数大全的小伙伴,下面一起跟随编程之家 jb51.cc的小编来看看吧。生成字符串变量strpython String function字符串长度获取:len(str)例:print %s length%d % (str,len(str))连接字符串sStr1 strcatsStr2 appendsStr1 s…...
显示wordpress用户/百度优化服务
shutdown方法:平滑的关闭ExecutorService,当此方法被调用时,ExecutorService停止接收新的任务并且等待已经提交的任务(包含提交正在执行和提交未执行)执行完成。当所有已提交任务执行完毕,线程池即被关闭。…...
网站海外推广谷歌seo方案/百度在线人工客服
1. Struts2(struts-2.2.3.1) 1.1 加入struts2的jar包 解压缩"struts2-blank"空项目,lib下的jar包全部拷贝。 1.2 web.xml加入struts2的过滤器 <filter> <filter-name>struts2</filter-name> <filter-class&…...