Android 12系统源码_SystemUI(六)显示和隐藏最近任务
前言
Android12对最近任务做了调整,将原本处于SystemUI模块的最近任务转移到了Launcher3QuickStep应用中。
本篇文章我们会结合源码一起来梳理一下最近任务的显示流程。
一、SystemUI模块显示最近任务的相关代码
1、在SystemUI模块调用CommandQueue的showRecentApps方法可以实现最近任务的显示。
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
public class CommandQueue extends IStatusBar.Stub implementsCallbackController<Callbacks>,DisplayManager.DisplayListener {private Handler mHandler = new H(Looper.getMainLooper());public void showRecentApps(boolean triggeredFromAltTab) {synchronized (mLock) {mHandler.removeMessages(MSG_SHOW_RECENT_APPS);mHandler.obtainMessage(MSG_SHOW_RECENT_APPS, triggeredFromAltTab ? 1 : 0, 0,null).sendToTarget();}}}
showRecentApps方法会调用Handler发送类型为MSG_SHOW_RECENT_APPS的消息。
2、Handler对象在接收到MSG_SHOW_RECENT_APPS消息之后,会调用所有回调对象的showRecentApps方法。
public class CommandQueue extends IStatusBar.Stub implementsCallbackController<Callbacks>,DisplayManager.DisplayListener {private static final int MSG_SHOW_RECENT_APPS = 13 << MSG_SHIFT;//显示最近任务private ArrayList<Callbacks> mCallbacks = new ArrayList<>();//回调对象集合private final class H extends Handler {private H(Looper l) {super(l);}public void handleMessage(Message msg) {final int what = msg.what & MSG_MASK;switch (what) {case MSG_SHOW_RECENT_APPS:for (int i = 0; i < mCallbacks.size(); i++) {//调用左右回调对象的showRecentApps方法mCallbacks.get(i).showRecentApps(msg.arg1 != 0);}break;}}}public interface Callbacks {default void showRecentApps(boolean triggeredFromAltTab) {}}}
3、类型为Recents的SystemUI组件实现了CommandQueue.Callbacks接口,并将自身添加到了CommandQueue的监听回调对象集合中,
这样CommandQueue的showRecentApps方法会触发Recents组件的showRecentApps方法。
frameworks/base/packages/SystemUI/src/com/android/systemui/recents/Recents.java
public class Recents extends SystemUI implements CommandQueue.Callbacks {private final RecentsImplementation mImpl;private final CommandQueue mCommandQueue;public Recents(Context context, RecentsImplementation impl, CommandQueue commandQueue) {super(context);mImpl = impl;mCommandQueue = commandQueue;}@Overridepublic void start() {mCommandQueue.addCallback(this);mImpl.onStart(mContext);}//显示最近任务@Overridepublic void showRecentApps(boolean triggeredFromAltTab) {// Ensure the device has been provisioned before allowing the user to interact with// recentsif (!isUserSetup()) {return;}android.util.Log.d("SystemUI.Recents", "showRecentApps: triggeredFromAltTab = " + triggeredFromAltTab);mImpl.showRecentApps(triggeredFromAltTab);}}
Recents的showRecentApps方法会进一步调用RecentsImplementation的showRecentApps方法。
4、RecentsImplementation是一个接口。
frameworks/base/packages/SystemUI/src/com/android/systemui/recents/RecentsImplementation.java
public interface RecentsImplementation {default void onStart(Context context) {}default void onBootCompleted() {}default void onAppTransitionFinished() {}default void onConfigurationChanged(Configuration newConfig) {}default void preloadRecentApps() {}default void cancelPreloadRecentApps() {}default void showRecentApps(boolean triggeredFromAltTab) {}default void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {}default void toggleRecentApps() {}default void dump(PrintWriter pw) {}
}
5、在SystemUI模块的具体实现类是OverviewProxyRecentsImpl。
frameworks/base/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyRecentsImpl.java
public class OverviewProxyRecentsImpl implements RecentsImplementation {private final static String TAG = "OverviewProxyRecentsImpl";@Nullableprivate final Lazy<Optional<StatusBar>> mStatusBarOptionalLazy;private Context mContext;private Handler mHandler;private TrustManager mTrustManager;private OverviewProxyService mOverviewProxyService;@SuppressWarnings("OptionalUsedAsFieldOrParameterType")@Injectpublic OverviewProxyRecentsImpl(Lazy<Optional<StatusBar>> statusBarOptionalLazy) {mStatusBarOptionalLazy = statusBarOptionalLazy;}@Overridepublic void onStart(Context context) {mContext = context;mHandler = new Handler();mTrustManager = (TrustManager) context.getSystemService(Context.TRUST_SERVICE);//为OverviewProxyService赋值mOverviewProxyService = Dependency.get(OverviewProxyService.class);}@Overridepublic void showRecentApps(boolean triggeredFromAltTab) {android.util.Log.d("SystemUI.OverviewProxyRecentsImpl", "showRecentApps: triggeredFromAltTab = " + triggeredFromAltTab);//IOverviewProxy是一个aidl,最初是调用OverviewProxyService的getProxy方法进行赋值的IOverviewProxy overviewProxy = mOverviewProxyService.getProxy();if (overviewProxy != null) {try {//继续调用onOverviewShown方法overviewProxy.onOverviewShown(triggeredFromAltTab);return;} catch (RemoteException e) {Log.e(TAG, "Failed to send overview show event to launcher.", e);}} else {// Do nothing}}}
OverviewProxyRecentsImpl的showRecentApps方法会进一步调用代理者IOverviewProxy的onOverviewShown方法,IOverviewProxy是一个aidl。这里调用OverviewProxyService的getProxy方法为overviewProxy赋值。mOverviewProxyService最初是通过Dependency进行赋值的。
6、OverviewProxyService类和getProxy方法相关代码如下所示。
public class OverviewProxyService extends CurrentUserTracker implementsCallbackController<OverviewProxyListener>, NavigationModeController.ModeChangedListener,Dumpable {//唤起Launcher3模块TouchInteractionService的Actionprivate static final String ACTION_QUICKSTEP = "android.intent.action.QUICKSTEP_SERVICE";//唤起Launcher3模块TouchInteractionService的Intentprivate final Intent mQuickStepIntent;//远程IPC通信是实现类private IOverviewProxy mOverviewProxy;private boolean mBound;public OverviewProxyService(Context context, CommandQueue commandQueue,Lazy<NavigationBarController> navBarControllerLazy,Lazy<Optional<StatusBar>> statusBarOptionalLazy,NavigationModeController navModeController,NotificationShadeWindowController statusBarWinController, SysUiState sysUiState,Optional<Pip> pipOptional,Optional<LegacySplitScreen> legacySplitScreenOptional,Optional<SplitScreen> splitScreenOptional,Optional<OneHanded> oneHandedOptional,Optional<RecentTasks> recentTasks,Optional<StartingSurface> startingSurface,BroadcastDispatcher broadcastDispatcher,ShellTransitions shellTransitions,ScreenLifecycle screenLifecycle,SmartspaceTransitionController smartspaceTransitionController,UiEventLogger uiEventLogger,DumpManager dumpManager) {super(broadcastDispatcher);...代码省略...//获取最近任务组件名称mRecentsComponentName = ComponentName.unflattenFromString(context.getString(com.android.internal.R.string.config_recentsComponentName));//创建最近任务Activity的意图对象mQuickStepIntent = new Intent(ACTION_QUICKSTEP).setPackage(mRecentsComponentName.getPackageName());...代码省略...startConnectionToCurrentUser();...代码省略...}//成功绑定服务所返回的ServiceConnection对象private final ServiceConnection mOverviewServiceConnection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {...代码省略...//拿到IOverviewProxy对象,为后续跨进程通信做准备mOverviewProxy = IOverviewProxy.Stub.asInterface(service);...代码省略...}};private void internalConnectToCurrentUser() {...代码省略... Intent launcherServiceIntent = new Intent(ACTION_QUICKSTEP).setPackage(mRecentsComponentName.getPackageName());try {//绑定服务mBound = mContext.bindServiceAsUser(launcherServiceIntent,mOverviewServiceConnection,Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,UserHandle.of(getCurrentUserId()));} catch (SecurityException e) {Log.e(TAG_OPS, "Unable to bind because of security error", e);}...代码省略...}public IOverviewProxy getProxy() {return mOverviewProxy;} }
对以上代码做个简单总结:
1)为最近任务组件名称mRecentsComponentName赋值。
frameworks/base/core/res/res/values/config.xml
<string name="config_recentsComponentName" translatable="false">com.android.launcher3/com.android.quickstep.RecentsActivity</string>
2)创建最近任务Activity的意图对象mQuickStepIntent
3)创建最近任务服务的意图对象launcherServiceIntent,并进行服务绑定,触发mOverviewServiceConnection的回调方法onServiceConnected,
为类型为远程IPC通信的实现类mOverviewProxy对象赋值。
4)调用的getProxy获得远程通信的实现类
二、Launcher3模块显示最近任务的相关代码
梳理完了SystemUI模块和最近任务相关的代码,我们再来看下Launcher3模块相关的代码。
1、通过上面我们可以知道SystemUI模块启动的时候会启动Launcher3模块的最近任务服务,另外还有提到了最近任务Activity组件, 二者的声明如下所示。
packages/apps/Launcher3/quickstep/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"package="com.android.launcher3"><application android:backupAgent="com.android.launcher3.LauncherBackupAgent"><service android:name="com.android.quickstep.TouchInteractionService"android:permission="android.permission.STATUS_BAR_SERVICE"android:directBootAware="true"android:exported="true"><intent-filter><action android:name="android.intent.action.QUICKSTEP_SERVICE"/></intent-filter></service><activity android:name="com.android.quickstep.RecentsActivity"android:excludeFromRecents="true"android:launchMode="singleTask"android:clearTaskOnLaunch="true"android:stateNotNeeded="true"android:theme="@style/LauncherTheme"android:screenOrientation="unspecified"android:configChanges="keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenSize|screenLayout|smallestScreenSize"android:resizeableActivity="true"android:resumeWhilePausing="true"android:taskAffinity=""/></application></manifest>
2、第一节我们讲过要想显示最近任务,需要调用CommandQueue的showRecentApps方法,而该方法最终调用的其实是IOverviewProxy的onOverviewShown。
这里我们具体看一下这个aidl的具体内容。
frameworks/base/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
oneway interface IOverviewProxy {void onActiveNavBarRegionChanges(in Region activeRegion) = 11;void onInitialize(in Bundle params) = 12;/*** Sent when overview button is pressed to toggle show/hide of overview.*/void onOverviewToggle() = 6;/*** 显示最近任务*/void onOverviewShown(boolean triggeredFromAltTab) = 7;/*** Sent when overview is to be hidden.*/void onOverviewHidden(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) = 8;/*** Sent when there was an action on one of the onboarding tips view.* TODO: Move this implementation to SystemUI completely*/void onTip(int actionType, int viewType) = 10;/*** Sent when device assistant changes its default assistant whether it is available or not.*/void onAssistantAvailable(boolean available) = 13;/*** Sent when the assistant changes how visible it is to the user.*/void onAssistantVisibilityChanged(float visibility) = 14;/*** Sent when back is triggered.* TODO: Move this implementation to SystemUI completely*/void onBackAction(boolean completed, int downX, int downY, boolean isButton,boolean gestureSwipeLeft) = 15;/*** Sent when some system ui state changes.*/void onSystemUiStateChanged(int stateFlags) = 16;/*** Sent when the split screen is resized*/void onSplitScreenSecondaryBoundsChanged(in Rect bounds, in Rect insets) = 17;/*** Sent when suggested rotation button could be shown*/void onRotationProposal(int rotation, boolean isValid) = 18;/*** Sent when disable flags change*/void disable(int displayId, int state1, int state2, boolean animate) = 19;/*** Sent when behavior changes. See WindowInsetsController#@Behavior*/void onSystemBarAttributesChanged(int displayId, int behavior) = 20;/*** Sent when screen turned on and ready to use (blocker scrim is hidden)*/void onScreenTurnedOn() = 21;/*** Sent when the desired dark intensity of the nav buttons has changed*/void onNavButtonsDarkIntensityChanged(float darkIntensity) = 22;
}
3、Launcher3模块的最近任务服务TouchInteractionService和onOverviewShown方法相关的代码如下所示。
packages/apps/Launcher3/quickstep/src/com/android/quickstep/TouchInteractionService.java
public class TouchInteractionService extends Serviceimplements ProtoTraceable<LauncherTraceProto.Builder> {private OverviewCommandHelper mOverviewCommandHelper;private final TISBinder mTISBinder = new TISBinder();/*** Local IOverviewProxy implementation with some methods for local components*/public class TISBinder extends IOverviewProxy.Stub {@BinderThread@Overridepublic void onOverviewShown(boolean triggeredFromAltTab) {android.util.Log.d("Launcher3.TouchInteractionService", "onOverviewShown: triggeredFromAltTab = " + triggeredFromAltTab);if (triggeredFromAltTab) {TaskUtils.closeSystemWindowsAsync(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);mOverviewCommandHelper.addCommand(OverviewCommandHelper.TYPE_SHOW_NEXT_FOCUS);} else {mOverviewCommandHelper.addCommand(OverviewCommandHelper.TYPE_SHOW);}}}@Overridepublic IBinder onBind(Intent intent) {Log.d(TAG, "Touch service connected: user=" + getUserId());return mTISBinder;}
}
TISBinder对象的onOverviewShown方法被SystemUI所触发的时候,会进一步调用OverviewCommandHelper对象的addCommand方法,传入TYPE_SHOW。
4、OverviewCommandHelper和显示最近任务相关的代码如下所示。
public class OverviewCommandHelper {public static final int TYPE_SHOW = 1;//显示public static final int TYPE_SHOW_NEXT_FOCUS = 2;public static final int TYPE_HIDE = 3;//隐藏public static final int TYPE_TOGGLE = 4;//切换public static final int TYPE_HOME = 5;//首页public void addCommand(int type) {CommandInfo cmd = new CommandInfo(type);MAIN_EXECUTOR.execute(() -> addCommand(cmd));}private void addCommand(CommandInfo cmd) {boolean wasEmpty = mPendingCommands.isEmpty();mPendingCommands.add(cmd);if (wasEmpty) {executeNext();}}private void executeNext() {if (mPendingCommands.isEmpty()) {return;}CommandInfo cmd = mPendingCommands.get(0);//层层调用,最终触发executeCommand方法。if (executeCommand(cmd)) {scheduleNextTask(cmd);}}private <T extends StatefulActivity<?>> boolean executeCommand(CommandInfo cmd) {BaseActivityInterface<?, T> activityInterface =mOverviewComponentObserver.getActivityInterface();RecentsView recents = activityInterface.getVisibleRecentsView();if (recents == null) {//如果视图为空,说明最近任务视图不可见if (cmd.type == TYPE_HIDE) {// already hiddenreturn true;}if (cmd.type == TYPE_HOME) {android.util.Log.d("Launcher3.OverviewCommandHelper", "executeCommand cmd.type == TYPE_HOME");mService.startActivity(mOverviewComponentObserver.getHomeIntent());LauncherSplitScreenListener.INSTANCE.getNoCreate().notifySwipingToHome();return true;}} else {//如果视图不为空,说明最近任务视图可见switch (cmd.type) {case TYPE_SHOW:// already visiblereturn true;case TYPE_HIDE: {int currentPage = recents.getNextPage();TaskView tv = (currentPage >= 0 && currentPage < recents.getTaskViewCount())? (TaskView) recents.getPageAt(currentPage): null;return launchTask(recents, tv, cmd);}case TYPE_TOGGLE:return launchTask(recents, getNextTask(recents), cmd);case TYPE_HOME:android.util.Log.d("Launcher3.OverviewCommandHelper", "executeCommand TYPE_HOME");recents.startHome();LauncherSplitScreenListener.INSTANCE.getNoCreate().notifySwipingToHome();return true;}}...代码省略...return false;}}
相关文章:
Android 12系统源码_SystemUI(六)显示和隐藏最近任务
前言 Android12对最近任务做了调整,将原本处于SystemUI模块的最近任务转移到了Launcher3QuickStep应用中。 本篇文章我们会结合源码一起来梳理一下最近任务的显示流程。 一、SystemUI模块显示最近任务的相关代码 1、在SystemUI模块调用CommandQueue的showRecentA…...
Docekr三剑客之 Docekr compose
写在前面 Docker三剑客Docker Compose、Docker Machine、Docker Swarm分别是Docker官方开源的三个项目。有着不同的功能: Docker Compose负责实现对 Docker 容器集群的快速编排Docker Machine负责在多种平台上快速安装 Docker 环境Docker Swarm提供 Docker 容器集…...
企业是否具备等保测评资质在哪里查?怎么查?
为了规范等保相关业务办理流程,确保等保业务顺利办理,保障企业合法权益,政策规定,只有取得等保测评资质机构方可办理等保测评业务。因此很多人在问,企业是否具备等保测评资质在哪里查?怎么查? …...
Spacedesk软件推荐,让你的平板也变成电脑的副屏
我的设备: 电脑:戴尔G15 5511、i7-11800H、Windows 11、RTX3060 平板:荣耀V6、麒麟985、安卓10、分辨率2000*1200(手机也行,我用的平板) 实际使用: 先给放一张实际使用的照片 可以让平板变成电脑的副屏…...
Vue 3.0 组合式API 介绍 【Vue3 从零开始】
提示 在阅读文档之前,你应该已经熟悉了这两个 Vue 基础和创建组件。 在 Vue Mastery 上观看关于组合式 API 的免费视频。 通过创建 Vue 组件,我们可以将接口的可重复部分及其功能提取到可重用的代码段中。仅此一项就可以使我们的应用程序在可维护性和…...
【算法数据结构体系篇class13、14】:贪心算法思想
一、贪心算法概念贪心算法概念:1)最自然智慧的算法2)用一种局部最功利的标准,总是做出在当前看来是最好的选择3)难点在于证明局部最功利的标准可以得到全局最优解4)对于贪心算法的学习主要以增加阅历和经验…...
C++知识点,关键字inline ,String,强制类型转化
🐶博主主页:ᰔᩚ. 一怀明月ꦿ ❤️🔥专栏系列:线性代数,C初学者入门训练 🔥座右铭:“不要等到什么都没有了,才下定决心去做” 🚀🚀🚀大家觉不错…...
MyBatis源码分析(六)MetaObject工具类的使用与源码分析
文章目录一、MetaObject基本使用二、关键类源码分析1、MetaObject的构造方法2、PropertyTokenizer分词器3、BeanWrapper4、MetaClass5、DefaultReflectorFactory6、Reflector7、总结三、MetaObject的getValue源码分析写在后面一、MetaObject基本使用 public class User {priva…...
文献资源最多的文献下载神器,99.99%的文献都可下载
用对工具事半功倍,查找下载文献用对工具能节约大量的时间和精力去做更多的事情。 文献党下载器(wxdown.org),几乎整合了所有文献数据库资源,涵盖各种文献类型,包含全部学科。文献党下载器整合的资源如&…...
工控机ARM工业边缘计算机搭建Node-Red环境
搭建Node-Red环境Node-RED是一个基于Node.js的开源可视化流程编程环境,可以轻松构建自定义应用程序,通过连接简单的节点来完成复杂的任务。Node-RED提供了一种简单的方法,可以快速连接到外部服务,从而实现物联网应用的开发。Node-…...
位图/布隆过滤器/海量数据处理方式
位图 位图的概念 所谓位图,就是用每一位来存放某种状态,适用于海量数据,数据无重复的场景。通常是用来判断某个数据存不存在的。 直接来看问题: 给40亿个不重复的无符号整数,没排过序。给一个无符号整数࿰…...
Tomcat 配置文件数据库密码加密
几年前研究过Tomcat context.xml 中数据库密码改为密文的内容,因为当时在客户云桌面代码没有留备份也没有文章记录,最近项目又提出了这个需求就又重新拾起来学习一下。在网上找了一些资料,自己也大概试了一下,目前功能是实现了。参…...
k8s-Kubernetes集群部署
文章目录前言一、Kubernetes简介与架构1.Kubernetes简介2.kubernetes设计架构二、Kubernetes集群部署1.集群环境初始化2.所有节点安装kubeadm3.拉取集群所需镜像3.集群初始化4.安装flannel网络插件5.扩容节点6.设置kubectl命令补齐前言 一、Kubernetes简介与架构 1.Kubernetes…...
Python数据分析案例19——上市银行财务指标对比
我代码栏目都是针对基础的python数据分析人群,比如想写个本科毕业论文,课程论文,做个简单的案例分析等。过去写的案例可能使用了过多的机器学习和深度学习方法,文科的同学看不懂,可能他们仅仅只想用python做个回归或者…...
Python 中错误 ConnectionError: Max retries exceeded with url
出现错误“ConnectionError: Max retries exceeded with url”有多种原因: 向 request.get() 方法传递了不正确或不完整的 URL。我们正受到 API 的速率限制。requests 无法验证您向其发出请求的网站的 SSL 证书。 确保我们指定了正确且完整的 URL 和路径。 # ⛔️…...
SpringBoot下的Spring框架学习(Tedu)——DAY02
SpringBoot下的Spring框架学习(Tedu)——DAY02 目录SpringBoot下的Spring框架学习(Tedu)——DAY02Spring框架学习1.1 Spring介绍1.2 知识铺垫1.2.1 编辑Dog类1.2.2 编辑Cat类1.2.3 编辑测试类User.java1.2.4 上述代码的总结1.3 面…...
容易混淆的点:C语言中char* a[] 与 char a[] 的区别以及各自的用法
char* a[] 和 char a[] 的区别 char* a[] 和 char a[] 是 C 语言中数组的不同声明方式,二者具有以下区别: char a[] 声明的是一个字符数组,其中存储的是一串字符。此时,a 可以被视为一个指向字符的指针。 char* a[]则声明了一个…...
认识Spring(下)
作者:~小明学编程 文章专栏:Spring框架 格言:热爱编程的,终将被编程所厚爱。 目录 Spring更加高效的读取和存储对象 存储bean对象 五大注解 关于五大类注解 对象的注入 属性注入 构造方法注入 Setter注入 三种注入方式的…...
Educational Codeforces Round 144 (Rated for Div. 2) C - Maximum Set
传送门 题意: 对于一个集合,如果它的任意两个元素都能 有 其中一个能整除另一个,那么它是好的。问在区间[L,R] 中由这个区间某些数内构成的好的集合的最长长度是多少,以及且满足这个长度的好集合有多少个。(懒得想就借…...
学python的第四天---基础(2)
一、三角形类型读入数组并排序的方法nlist(map(float,input().split())) c,b,asorted(n)list_1 list(map(float, input().split())) list_1.sort() list_1.reverse()lengthssorted(map(float,input().split(" ")),reverseTrue)二、动物写法一:d{" &…...
装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...
如何在Windows本机安装Python并确保与Python.NET兼容
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...
