理解Android中不同的Context

作者:两日的blog

Context是什么,有什么用

在Android开发中,Context是一个抽象类,它是Android应用程序环境的一部分。它提供了访问应用程序资源和执行各种操作的接口。可以说,Context是Android应用程序与系统环境进行交互的桥梁

Context的作用包括:

  1. 访问应用程序资源:通过Context,可以获取应用程序的资源,如字符串、布局文件、图像等。这些资源可以在应用程序的各个组件中使用,例如ActivityServiceBroadcastReceiver等。
  2. 启动组件:通过Context,可以启动其他组件,如启动Activity、启动Service、发送广播等。它提供了访问系统服务的能力,如启动其他应用程序、发送系统广播等。
  3. 获取应用程序的上下文:通过Context,可以获取应用程序的上下文,如获取ApplicationContext,用于在整个应用程序中共享数据或执行全局操作。
  4. 访问系统服务:通过Context,可以访问各种系统服务,如获取系统级的服务(如传感器服务、位置服务)、访问设备功能(如摄像头、存储器)、执行网络操作等。
  5. 访问应用程序的文件:通过Context对象,可以获取应用程序的文件目录,创建、读取、写入和删除文件等操作。
  6. 处理资源生命周期:通过Context,可以管理应用程序资源的生命周期,如创建、销毁对象、注册和注销监听器等。它提供了一种机制,确保资源的正确使用和释放,避免内存泄漏等问题。
public abstract AssetManager getAssets();/*** Returns a Resources instance for the application's package.* <p>* <strong>Note:</strong> Implementations of this method should return* a Resources instance that is consistent with the AssetManager instance* returned by {@link #getAssets()}. For example, they should share the* same {@link Configuration} object.** @return a Resources instance for the application's package* @see #getAssets()*/
public abstract Resources getResources();/** Return PackageManager instance to find global package information. */
public abstract PackageManager getPackageManager();/** Return a ContentResolver instance for your application's package. */
public abstract ContentResolver getContentResolver();/*** Return the Looper for the main thread of the current process.  This is* the thread used to dispatch calls to application components (activities,* services, etc).* <p>* By definition, this method returns the same result as would be obtained* by calling {@link Looper#getMainLooper() Looper.getMainLooper()}.* </p>** @return The main looper.*/
public abstract Looper getMainLooper();/*** Return an {@link Executor} that will run enqueued tasks on the main* thread associated with this context. This is the thread used to dispatch* calls to application components (activities, services, etc).*/
public Executor getMainExecutor() {// This is pretty inefficient, which is why ContextImpl overrides itreturn new HandlerExecutor(new Handler(getMainLooper()));
}public abstract Context getApplicationContext();public final CharSequence getText(@StringRes int resId) {return getResources().getText(resId);
}/*** Returns a localized string from the application's package's* default string table.** @param resId Resource id for the string* @return The string data associated with the resource, stripped of styled*         text information.*/
@NonNull
public final String getString(@StringRes int resId) {return getResources().getString(resId);
}/*** Returns a localized formatted string from the application's package's* default string table, substituting the format arguments as defined in* {@link java.util.Formatter} and {@link java.lang.String#format}.** @param resId Resource id for the format string* @param formatArgs The format arguments that will be used for*                   substitution.* @return The string data associated with the resource, formatted and*         stripped of styled text information.*/
@NonNull
public final String getString(@StringRes int resId, Object... formatArgs) {return getResources().getString(resId, formatArgs);
}/*** Returns a color associated with a particular resource ID and styled for* the current theme.** @param id The desired resource identifier, as generated by the aapt*           tool. This integer encodes the package, type, and resource*           entry. The value 0 is an invalid identifier.* @return A single color value in the form 0xAARRGGBB.* @throws android.content.res.Resources.NotFoundException if the given ID*         does not exist.*/
@ColorInt
public final int getColor(@ColorRes int id) {return getResources().getColor(id, getTheme());
}/*** Returns a drawable object associated with a particular resource ID and* styled for the current theme.** @param id The desired resource identifier, as generated by the aapt*           tool. This integer encodes the package, type, and resource*           entry. The value 0 is an invalid identifier.* @return An object that can be used to draw this resource.* @throws android.content.res.Resources.NotFoundException if the given ID*         does not exist.*/
@Nullable
public final Drawable getDrawable(@DrawableRes int id) {return getResources().getDrawable(id, getTheme());
}/*** Returns a color state list associated with a particular resource ID and* styled for the current theme.** @param id The desired resource identifier, as generated by the aapt*           tool. This integer encodes the package, type, and resource*           entry. The value 0 is an invalid identifier.* @return A color state list.* @throws android.content.res.Resources.NotFoundException if the given ID*         does not exist.*/
@NonNull
public final ColorStateList getColorStateList(@ColorRes int id) {return getResources().getColorStateList(id, getTheme());
}/*** Set the base theme for this context.  Note that this should be called* before any views are instantiated in the Context (for example before* calling {@link android.app.Activity#setContentView} or* {@link android.view.LayoutInflater#inflate}).** @param resid The style resource describing the theme.*/
public abstract void setTheme(@StyleRes int resid);/** @hide Needed for some internal implementation...  not public because* you can't assume this actually means anything. */
@UnsupportedAppUsage
public int getThemeResId() {return 0;
}/*** Return the Theme object associated with this Context.*/
@ViewDebug.ExportedProperty(deepExport = true)
public abstract Resources.Theme getTheme();/*** Retrieve styled attribute information in this Context's theme.  See* {@link android.content.res.Resources.Theme#obtainStyledAttributes(int[])}* for more information.** @see android.content.res.Resources.Theme#obtainStyledAttributes(int[])*/
@NonNull
public final TypedArray obtainStyledAttributes(@NonNull @StyleableRes int[] attrs) {return getTheme().obtainStyledAttributes(attrs);
}/*** Retrieve styled attribute information in this Context's theme.  See* {@link android.content.res.Resources.Theme#obtainStyledAttributes(int, int[])}* for more information.** @see android.content.res.Resources.Theme#obtainStyledAttributes(int, int[])*/
@NonNull
public final TypedArray obtainStyledAttributes(@StyleRes int resid,@NonNull @StyleableRes int[] attrs) throws Resources.NotFoundException {return getTheme().obtainStyledAttributes(resid, attrs);
}/*** Retrieve styled attribute information in this Context's theme.  See* {@link android.content.res.Resources.Theme#obtainStyledAttributes(AttributeSet, int[], int, int)}* for more information.** @see android.content.res.Resources.Theme#obtainStyledAttributes(AttributeSet, int[], int, int)*/
@NonNull
public final TypedArray obtainStyledAttributes(@Nullable AttributeSet set, @NonNull @StyleableRes int[] attrs) {return getTheme().obtainStyledAttributes(set, attrs, 0, 0);
}/*** Retrieve styled attribute information in this Context's theme.  See* {@link android.content.res.Resources.Theme#obtainStyledAttributes(AttributeSet, int[], int, int)}* for more information.** @see android.content.res.Resources.Theme#obtainStyledAttributes(AttributeSet, int[], int, int)*/
@NonNull
public final TypedArray obtainStyledAttributes(@Nullable AttributeSet set,@NonNull @StyleableRes int[] attrs, @AttrRes int defStyleAttr,@StyleRes int defStyleRes) {return getTheme().obtainStyledAttributes(set, attrs, defStyleAttr, defStyleRes);
}

总之,Context在Android开发中具有重要的作用,它提供了访问应用程序资源、启动组件、访问系统服务以及处理资源生命周期的能力。开发者可以使用Context来实现各种应用程序功能和与系统环境的交互。

Context有哪些

Context 本身是一个抽象类,主要实现类为 ContextImpl,另外有子类 ContextWrapperContextThemeWrapper,另外还有其他由上述三个类引申出来的Context类,Application/Service/Activity,他们的继承关系如下:

ContextImpl/ContextWrapper/ContextThemeWrapper的区别

ContextImplContextWrapperContextThemeWrapper
ContextImplContext的主要实现类,它提供了大部分Context的基本功能和行为。它是Android框架中真正的上下文实现类,用于处理应用程序的资源访问、组件启动、文件操作和系统服务等操作。ContextWrapper是一个包装类,用于对现有的Context对象进行包装或修改其功能。它是Context的一个间接子类,可以通过继承ContextWrapper类来扩展Context的功能,例如添加自定义的行为或修改Context的行为。ContextThemeWrapperContextThemeWrapperContext的另一个包装类,它继承自ContextWrapper类。与ContextWrapper类似,ContextThemeWrapper也是用于包装现有的Context对象,但它还提供了自己的主题资源。通过ContextThemeWrapper,可以为特定的上下文设置不同的主题,以实现界面的样式和外观的变化。

ContextImpl

上文说到,Context本身是一个抽象类,主要的实现类就是ContextImpl,即Context的那些功能都是在ContexImpl中实现的,即ContextImpl实际承担着提供应用程序资源访问、组件启动和系统服务等功能的责任。

public class ContextImpl extends Context {private Resources mResources;private Theme mTheme;void setResources(Resources r) {if (r instanceof CompatResources) {((CompatResources) r).setContext(this);}mResources = r;}@Overridepublic Resources getResources() {return mResources;}@Overridepublic void setTheme(int resId) {synchronized (mSync) {if (mThemeResource != resId) {mThemeResource = resId;initializeTheme();}}}public Resources.Theme getTheme() {synchronized (mSync) {if (mTheme != null) {return mTheme;}mThemeResource = Resources.selectDefaultTheme(mThemeResource,getOuterContext().getApplicationInfo().targetSdkVersion);initializeTheme();return mTheme;}}private void initializeTheme() {if (mTheme == null) {mTheme = mResources.newTheme();}mTheme.applyStyle(mThemeResource, true);}// 其他方法的实现省略...
}

ContextImpl,我们重点关注一下ResourceTheme的相关实现,ContextImpl中提供了getResources/setResources方法,用于获取Resources以及设置Resources,以提供资源的访问。

getTheme/setTheme用于获取Theme以及设置Theme,以提供对主题的访问.

重点看一下getTheme()方法,该方法,会首先获取mThemeResource,这里直接选择的系统默认主题,系统会根据不同的sdk版本选择不同的默认主题。

@UnsupportedAppUsage
public static int selectDefaultTheme(int curTheme, int targetSdkVersion) {return selectSystemTheme(curTheme, targetSdkVersion,com.android.internal.R.style.Theme,com.android.internal.R.style.Theme_Holo,com.android.internal.R.style.Theme_DeviceDefault,com.android.internal.R.style.Theme_DeviceDefault_Light_DarkActionBar);
}/** @hide */
public static int selectSystemTheme(int curTheme, int targetSdkVersion, int orig, int holo,int dark, int deviceDefault) {if (curTheme != ID_NULL) {return curTheme;}if (targetSdkVersion < Build.VERSION_CODES.HONEYCOMB) {return orig;}if (targetSdkVersion < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {return holo;}if (targetSdkVersion < Build.VERSION_CODES.N) {return dark;}return deviceDefault;
}

通过ContextImpl的实例,应用程序可以获取到Resources对象和Theme对象,从而实现对资源和主题的访问和处理。需要注意的是,这是一个简化的,实际的ContextImpl源码非常复杂,还涉及到处理上下文的生命周期、系统服务的获取等方面的逻辑。

ContextWrapper

ContextWrapper是一个包装类,内部包含一个mBase成员变量,所有的实现都是调用mBase的方法。

public class ContextWrapper extends Context {@UnsupportedAppUsageContext mBase;public ContextWrapper(Context base) {mBase = base;}@Overridepublic void setTheme(int resid) {mBase.setTheme(resid);}/** @hide */@Override@UnsupportedAppUsagepublic int getThemeResId() {return mBase.getThemeResId();}@Overridepublic Resources.Theme getTheme() {return mBase.getTheme();}@Overridepublic ClassLoader getClassLoader() {return mBase.getClassLoader();}@Overridepublic String getPackageName() {return mBase.getPackageName();}}

ContextThemeWrapper

ContextThemeWrapper继承自ContextWrapper,从名字中可以看出,该类主要是跟主题相关的包装类:

public class ContextThemeWrapper extends ContextWrapper {...@Overridepublic Resources getResources() {return getResourcesInternal();}private Resources getResourcesInternal() {if (mResources == null) {if (mOverrideConfiguration == null) {mResources = super.getResources();} else {final Context resContext = createConfigurationContext(mOverrideConfiguration);mResources = resContext.getResources();}}return mResources;}@Overridepublic void setTheme(int resid) {if (mThemeResource != resid) {mThemeResource = resid;initializeTheme();}}@Overridepublic Resources.Theme getTheme() {if (mTheme != null) {return mTheme;}mThemeResource = Resources.selectDefaultTheme(mThemeResource,getApplicationInfo().targetSdkVersion);initializeTheme();return mTheme;}@UnsupportedAppUsageprivate void initializeTheme() {final boolean first = mTheme == null;if (first) {mTheme = getResources().newTheme();final Resources.Theme theme = getBaseContext().getTheme();if (theme != null) {mTheme.setTo(theme);}}onApplyThemeResource(mTheme, mThemeResource, first);}...}

ContextImpl相比较,ContextThemeWrapper中获取资源以及主题的代码有所不同,多了一个Configuration,其他行为大致一致。

另外在AppCompat中,默认的主题为Theme_AppCompat_Light

package androidx.appcompat.view;public class ContextThemeWrapper extends ContextWrapper {... @Overridepublic Resources.Theme getTheme() {if (mTheme != null) {return mTheme;}if (mThemeResource == 0) {mThemeResource = R.style.Theme_AppCompat_Light;}initializeTheme();return mTheme;}
}

App中不同Context对象的Theme

我们在开发中,经常会用到各种Context,常用的有activity/application/applicationContext/baseContext,为了测试不同Context中Theme对象,我们编写如下代码:

class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)printLog("baseContext is ${baseContext.themeResId} baseContext is $baseContext")printLog("application is ${application.themeResId} application is $application")printLog("applicationContext is ${applicationContext.themeResId} applicationContext is $applicationContext")printLog("activity is ${this.themeResId}")}private fun printLog(msg: String) {println("MainActivity themeResId in $msg")}
}

我们分别获取每个Context对应的themeResId,即每个ContextTheme对应的resId

对代码运行结果我们有如下结论:

  1. getApplicationgetApplicationContext得到的是同一个Application实例对象;
  2. Application对象中的themeResId 为0 ,Application其实也有主题的应用,毕竟主题样式都是针对UI元素的;
  3. **Activity中的主题和getBaseContext**中的主题是不一样的,具体对应什么主题下文将进行探究
  4. getBaseContext中得到的是ContextThemeWrapper,这点让我有点意外,之前的理解都是Activity启动时,会新建一个ContextImpl对象,在attachBaseContext中赋予Activity中的mBase,于是仔细研究一下发现,其实是AppCompatActivity做了替换:
//androidx.appcompat.app.AppCompatActivity
// AppCompatActivity重写了Activity中的attachBaseContext方法
@Override
protected void attachBaseContext(Context newBase) {super.attachBaseContext(getDelegate().attachBaseContext2(newBase));
}

我们看一下代理类AppCompatDelegateImplattachBaseContext2的实现:

//androidx.appcompat.app.AppCompatDelegateImpl@NonNull
@Override
@CallSuper
public Context attachBaseContext2(@NonNull final Context baseContext) {mBaseContextAttached = true;final int modeToApply = mapNightMode(baseContext, calculateNightMode());// If the base context is a ContextThemeWrapper (thus not an Application context)// and nobody's touched its Resources yet, we can shortcut and directly apply our// override configuration.if (sCanApplyOverrideConfiguration&& baseContext instanceof android.view.ContextThemeWrapper) {final Configuration config = createOverrideConfigurationForDayNight(baseContext, modeToApply, null);ContextThemeWrapperCompatApi17Impl.applyOverrideConfiguration((android.view.ContextThemeWrapper) baseContext, config);return baseContext;}// Again, but using the AppCompat version of ContextThemeWrapper.if (baseContext instanceof ContextThemeWrapper) {final Configuration config = createOverrideConfigurationForDayNight(baseContext, modeToApply, null);((ContextThemeWrapper) baseContext).applyOverrideConfiguration(config);return baseContext;}// We can't apply the configuration directly to the existing base context, so we need to// wrap it. We can't create a new configuration context since the app may rely on method// overrides or a specific theme -- neither of which are preserved when creating a// configuration context. Instead, we'll make a best-effort at wrapping the context and// rebasing the original theme.if (!sCanReturnDifferentContext) {return super.attachBaseContext2(baseContext);}Configuration configOverlay = null;final Configuration config = createOverrideConfigurationForDayNight(baseContext, modeToApply, configOverlay);//重点1:新建ContextThemeWrapper对象将传入的baseContext赋值给ContextWrapper中的mBase,// 并且ContextThemeWrapper中的主题为Theme_AppCompat_Empty// Next, we'll wrap the base context to ensure any method overrides or themes are left// intact. Since ThemeOverlay.AppCompat theme is empty, we'll get the base context's theme.final ContextThemeWrapper wrappedContext = new ContextThemeWrapper(baseContext,R.style.Theme_AppCompat_Empty);wrappedContext.applyOverrideConfiguration(config);// Check whether the base context has an explicit theme or is able to obtain one// from its outer context. If it throws an NPE because we're at an invalid point in app// initialization, we don't need to worry about rebasing under the new configuration.boolean needsThemeRebase;try {needsThemeRebase = baseContext.getTheme() != null;} catch (NullPointerException e) {needsThemeRebase = false;}if (needsThemeRebase) {// Attempt to rebase the old theme within the new configuration. This will only// work on SDK 23 and up, but it's unlikely that we're keeping the base theme// anyway so maybe nobody will notice. Note that calling getTheme() will clone// the base context's theme into the wrapped context's theme.ResourcesCompat.ThemeCompat.rebase(wrappedContext.getTheme());}return super.attachBaseContext2(wrappedContext);
}//androidx.appcompat.app.AppCompatDelegate
@NonNull
@CallSuper
public Context attachBaseContext2(@NonNull Context context) {
// 重点2,将上一步包装了baseContext的ContextThemeWrapper对象进一步赋值给Activity的mBaseattachBaseContext(context);return context;
}

最终AppCompatActivity中的mBase是包装了ContextImplContextThemeWrapper对象,并且其主题为Theme_AppCompat_Empty

关于第三点,getBaseActivityActivity中的主题到底是哪一个,我们可以根据resId和resources索引表resource.arsc(直接将apk文件拖到AndroidStudio中就可以看到该文件)找到:

21317554102131755474对应16进制为0x7f1001920x7f1001d2

可以看到,getBaseActivityActivity中的主题分别对应Theme_AppCompat_Empty 与我们在AndroidManifest.xml中设置的应用主题Theme.ThemeTest

总结

Context是Android应用程序与系统环境进行交互的桥梁,主要实现类是ContextImpl, 可以访问应用程序资源/启动组件/访问系统服务/访问应用程序的文件等,而Context可以分为三种:ContextImpl/ContextWrapper/ContextThemeWrapper,不同ContextImpl 是Context的主要实现类,ContextWrapper是简单的包装类,所有的实现都由其内部的mBase成员完成,ContextThemeWrapper继承自ContextWrapper ,它的主要继承者是Activity,和其他两个Context不同的是,他内部对应用资源和主题有不同的行为,在应用中使用跟主题相关的Context时,最好使用activity,而不要使用getBaseContext或者applictaion.

Android 学习笔录

Android 性能优化篇:https://qr18.cn/FVlo89
Android 车载篇:https://qr18.cn/F05ZCM
Android 逆向安全学习笔记:https://qr18.cn/CQ5TcL
Android Framework底层原理篇:https://qr18.cn/AQpN4J
Android 音视频篇:https://qr18.cn/Ei3VPD
Jetpack全家桶篇(内含Compose):https://qr18.cn/A0gajp
Kotlin 篇:https://qr18.cn/CdjtAF
Gradle 篇:https://qr18.cn/DzrmMB
OkHttp 源码解析笔记:https://qr18.cn/Cw0pBD
Flutter 篇:https://qr18.cn/DIvKma
Android 八大知识体:https://qr18.cn/CyxarU
Android 核心笔记:https://qr21.cn/CaZQLo
Android 往年面试题锦:https://qr18.cn/CKV8OZ
2023年最新Android 面试题集:https://qr18.cn/CgxrRy
Android 车载开发岗位面试习题:https://qr18.cn/FTlyCJ
音视频面试题锦:https://qr18.cn/AcV6Ap

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

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

相关文章

面向对象——步入JavaScript高级阶段的敲门砖

目录 前言一、认识对象1.什么是对象2.对象的方法3.对象的遍历4.对象的深浅克隆 二、认识函数上下文1.函数的上下文规则 ★2.call和apply ★ 三、构造函数1.用new操作符调用函数2.类与实例3.构造函数和类" 四、原型和原型链1.prototype和原型链查找 ★2.在prototype上添加方…

Windows下安装Hadoop(手把手包成功安装)

Windows下安装Hadoop&#xff08;手把手包成功安装&#xff09; Windows下安装Hadoop&#xff08;手把手包成功安装&#xff09;一、环境准备1.1、查看是否安装了java环境 二、下载Hadoop的相关文件三、解压Hadoop安装包四、替换bin文件夹五、配置Hadoop环境变量六、检查环境变…

【数学建模】时间序列分析

文章目录 1. 条件2. 模型分类3. SPSS处理时间序列 1. 条件 1.使用于具有时间、数值两种要素 2.数据具有周期性可以使用时间序列分解 2. 模型分类 叠加模型【YTSCI】 序列的季节波动变化越来越大&#xff0c;反映变动之间的关系发生变化乘积序列【YTSC*I】 时间序列波动保持恒…

【多模态】16、DetCLIP | 构建超大词汇字典来进行开放世界目标检测

论文&#xff1a;DetCLIP: Dictionary-Enriched Visual-Concept Paralleled Pre-training for Open-world Detection 代码&#xff1a;无。。。 出处&#xff1a;NIPS2022 | 华为诺亚方舟 | 中山大学 | 香港科技大学 效果&#xff1a; 在 LVIS 的 1203 个类别上超越了 GLIP…

【树上乘法原理】ICPC Shanghai 2021 G, Edge Groups

http://oj.daimayuan.top/course/8/problem/400 题意&#xff1a; 思路&#xff1a; 求方案数&#xff0c;考虑组合数学 手摸一下样例发现&#xff0c;对于一棵子树&#xff0c;若边数为偶数&#xff0c;那么可以内部匹配&#xff0c;但是如果边数为奇数&#xff0c;那么就一…

嵌入式:QT Day2

一、继续完善登录框&#xff0c;当登陆成功时&#xff0c;关闭登陆页面&#xff0c;跳转到新的界面中 源码&#xff1a; widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QDebug> //用于打印输出 #include <QIcon> …

无涯教程-jQuery - jQuery.getScript( url, callback )方法函数

jQuery.getScript(url&#xff0c;[callback])方法使用HTTP GET请求加载并执行JavaScript文件。 该方法返回XMLHttpRequest对象。 jQuery.getScript( url, [callback] ) - 语法 $.getScript( url, [callback] ) 这是此方法使用的所有参数的描述- url - 包含请求…

mac 移动硬盘未正常退出,再次链接无法读取(显示)

&#xff08;1&#xff09;首先插入自己的硬盘&#xff0c;然后找到mac的磁盘工具 &#xff08;2&#xff09;打开磁盘工具&#xff0c;发现自己的磁盘分区在卸载状态&#xff1b;点击无法成功装载。 &#xff08;3&#xff09;打开终端&#xff0c;输入 diskutil list查看自…

Redis应用(1)——生成全局唯一标识ID

1 概述 在实际项目中&#xff0c;根据不同的业务逻辑需要生成唯一的标识id &#xff0c;如购买商品生成的订单号。尽管这个标识id功能非常的简单&#xff0c;但是如果不能成功的生成唯一标识id&#xff0c;那将会影响后续的业务逻辑 。我们可以使用数据库去生成唯一标识id&…

经营在线业务的首选客服工具--SS客服

随着网购正在快速取代传统零售业&#xff0c;各行各业的企业都在大力发展电子商务以取悦客户。但是&#xff0c;有这么多可用的电子商务平台&#xff0c;选择一款符合自己发展的平台确实不容易。电子商务平台不仅是企业在线销售产品和服务的地方&#xff0c;也是他们管理日常运…

Qt Core学习日记——第七天QMetaObject(上)

每一个声明Q_OBJECT的类都具有QMetaObject对象 Q_OBJECT宏源代码&#xff1a; #define Q_OBJECT \ public: \ QT_WARNING_PUSH \ Q_OBJECT_NO_OVERRIDE_WARNING \ static const QMetaObject staticMetaObject; \ virtual const QMetaObject *metaObject() const; \ vir…

深度学习入门教程(2):使用预训练模型来文字生成图片TextToImageGenerationWithNetwork

本深度学习入门教程是在polyu HPCStudio 启发以及资源支持下进行的&#xff0c;在此也感谢polyu以及提供支持的老师。 本文内容&#xff1a;在GoogleColab平台上使用预训练模型来文字生成图片Text To Image Generation With Network &#xff08;1&#xff09;你会学到什么&a…

Fiddler使用教程|渗透测试工具使用方法Fiddler

提示&#xff1a;如有问题可联系我&#xff0c;24小时在线 文章目录 前言一、Fiddler界面介绍二、菜单栏1.菜单Fiddler工具栏介绍Fiddler命令行工具详解 前言 网络渗透测试工具&#xff1a; Fiddler是目前最常用的http抓包工具之一。 Fiddler是功能非常强大&#xff0c;是web…

伦敦金在非农双向挂单

对伦敦金投资有一定经验的投资者都知道&#xff0c;在非农时期&#xff0c;伦敦金市场会出现很大的波动&#xff0c;那么我们如何才能抓住这些波动呢&#xff1f;答案是很难的。但是&#xff0c;有些投资者在多年实践中发明了一种双向挂单的方法&#xff0c;这里和大家一切分享…

向量数据库Milvus的四个版本

目录 MilvusLite版 单机版 分布式版 Milvus Cloud版 Milvus是一个功能强大的向量数据库管理系统,提供了多种版本,以满足不同用户的需求。以下是关于Milvus四个版本的具体介绍。 MilvusLite版 MilvusLite版是Milvus的轻量级版本,适合于小规模数据集和高性能计算场景。…

el-popover在原生table中,弹出多个以及内部取消按钮无效问题

问题&#xff1a;当el-popover和原生table同时使用的时候会失效&#xff08;不是el-table) <el-popover placement"bottom" width"500" trigger"click" :key"popover-${item.id}"></el-popover> 解决&#xff1a; :key…

vue 项目中使用阿里巴巴矢量图标库

1.网址&#xff1a;https://www.iconfont.cn/ 2.手动创建自己的项目图标库 选中图标 → 添加入库&#xff08;点击购物车&#xff09;→ 完成后点击上方菜单栏的购物车 → 添加至项目&#xff08;没有则新建项目&#xff09;→ 自动打开项目图标库 → 点击下载至本地 → 点击de…

【Redis-02】Redis的缓存

Redis的缓存 1.概念1.1什么是缓存1.2为什么使用缓存1.3如何使用1.3.1不适用缓存之前1.3.2 缓存模型和思路&#xff08;使用方法&#xff09;1.3.3 使用之后 2.缓存更新策略2.1数据库缓存不一致解决方案2.2数据库和缓存不一致采用什么方案2.3代码实例 3.缓存穿透3.1缓存穿透是什…

(四)RabbitMQ高级特性(消费端限流、利用限流实现不公平分发、消息存活时间、优先级队列

Lison <dreamlison163.com>, v1.0.0, 2023.06.23 RabbitMQ高级特性&#xff08;消费端限流、利用限流实现不公平分发、消息存活时间、优先级队列 文章目录 RabbitMQ高级特性&#xff08;消费端限流、利用限流实现不公平分发、消息存活时间、优先级队列消费端限流利用限流…

一个简单的 Android 版本目录(Version catalog)实现指南

一个简单的 Android 版本目录实现指南 使用 TOML 格式 在本文中&#xff0c;我们将探讨版本目录以及如何实现它。 版本目录 Gradle 版本目录使您能够以可扩展的方式添加和维护依赖项和插件。因此&#xff0c;不必在各个构建文件中硬编码依赖项名称和版本&#xff0c;而是在目…