Android 持久化组件-SharedPreferences 详解
前(fei)言(hua)
SharedPreference(简称SP)是Android上一种非常易用的轻量级存储方式。SP采用key-value(键值对)形式来存储数据,最终以xml格式的文件来持久化到存储介质上。默认的存储位置在/data/data/<包名>/shared_prefs目录下,当用户卸载此应用程序或者清除应用数据时,SP保存的数据会一并清除。
运用场景
- 保存应用的偏好设置(登录状态,业务的开关,临时标志位等);
- 保存格式简单的,数据量较小的数据信息;
使用步骤
获取SharedPreferences对象
- PreferenceManager.java
PreferenceManager.getDefaultSharedPreferences(context)
- ContextImpl.java
@Overridepublic SharedPreferences getSharedPreferences(String name, int mode) {//....此处省略若干行 return getSharedPreferences(file, mode);}@Overridepublic SharedPreferences getSharedPreferences(File file, int mode) {SharedPreferencesImpl sp;//....此处省略若干行 return sp;}复制代码
name:要保存的文件名
mode:Context.MODE_PRIVATE:默认操作模式,代表该文件是私有数据,只能被应用本身访问;Context.MODE_APPEND:该模式会检查文件是否存在,存在就往文件追加内容,否则就创建新文件。
获取Sharedpreferences.Editor对象
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);SharedPreferences.Editor editor = sp.edit();
复制代码
通过Sharedpreferences.Editor接口的putXxx方法保存键值对
editor.putString("author", "wragony");
editor.putInt("year", 2018);
//....
复制代码
通过Sharedpreferences.editor接口的commit()方法或apply()方法保存键值对
editor.commit();
//editor.apply();复制代码
完整示例
public void spDemo(Context context) {SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);SharedPreferences.Editor editor = sp.edit();editor.putString("author", "wragony");editor.putInt("year", 2018);editor.commit();String author = sp.getString("author", "");int year = sp.getInt("year", 0);Log.d("SP-DEMO", String.format("author:%s,year:%d", author, year));
}复制代码
查看Sharedpreferences保存的xml文件内容
源(zhuang)码(bi)分(kai)析(shi)
篇幅有些过长,关键点写在了注释里;
1.获取SharedPreferences对象流程
获取SharedPreferences对象的几种方式最终都会调用ContextImpl.java 中的 getSharedPreferences(String name, int mode) 方法;
【1】 public SharedPreferences getSharedPreferences(String name, int mode) //ContextImpl.java
@Override
public SharedPreferences getSharedPreferences(String name, int mode) {// At least one application in the world actually passes in a null// name. This happened to work because when we generated the file name// we would stringify it to "null.xml". Nice.if (mPackageInfo.getApplicationInfo().targetSdkVersion <Build.VERSION_CODES.KITKAT) {if (name == null) {name = "null";}}File file;synchronized (ContextImpl.class) {//如果SP文件路径的缓存为null则创建一个Map用于缓存SP文件路径if (mSharedPrefsPaths == null) {mSharedPrefsPaths = new ArrayMap<>();}//先从缓存SP文件路径查找否存在相应文件file = mSharedPrefsPaths.get(name);if (file == null) {//如果文件不存在, 则创建新的文件,并放入缓存中file = getSharedPreferencesPath(name);mSharedPrefsPaths.put(name, file);}}//详见【2】中的注释return getSharedPreferences(file, mode);
}
复制代码
【2】 public SharedPreferences getSharedPreferences(File file, int mode) //ContextImpl.java
@Override
public SharedPreferences getSharedPreferences(File file, int mode) {SharedPreferencesImpl sp;//实例的构造被 synchronized 关键字包裹, 因此构造过程是多线程安全的synchronized (ContextImpl.class) {//先从缓存中获取SharedPreferencesImpl 对象final ArrayMap<File, SharedPreferencesImpl> cache = getSharedPreferencesCacheLocked();sp = cache.get(file);if (sp == null) {//如果缓存未命中, 构造SharedPreferencesImpl对象checkMode(mode);if (getApplicationInfo().targetSdkVersion >= android.os.Build.VERSION_CODES.O) {if (isCredentialProtectedStorage()&& !getSystemService(UserManager.class).isUserUnlockingOrUnlocked(UserHandle.myUserId())) {throw new IllegalStateException("SharedPreferences in credential encrypted "+ "storage are not available until after user is unlocked");}}// 第一次构建SP对象 详见【3】sp = new SharedPreferencesImpl(file, mode);// 将构造的SharedPreferencesImpl对象放入缓存中cache.put(file, sp);return sp;}}if ((mode & Context.MODE_MULTI_PROCESS) != 0 ||getApplicationInfo().targetSdkVersion < android.os.Build.VERSION_CODES.HONEYCOMB) {// If somebody else (some other process) changed the prefs// file behind our back, we reload it. This has been the// historical (if undocumented) behavior.sp.startReloadIfChangedUnexpectedly();}return sp;
}复制代码
【3】 SharedPreferencesImpl(File file, int mode) //SharedPreferencesImpl.java
SharedPreferencesImpl(File file, int mode) {mFile = file;mBackupFile = makeBackupFile(file);mMode = mode;mLoaded = false;mMap = null;startLoadFromDisk();
}private void startLoadFromDisk() {synchronized (mLock) {mLoaded = false;}//开启子线程从磁盘文件读取new Thread("SharedPreferencesImpl-load") {public void run() {//详见【4】loadFromDisk();}}.start();
}复制代码
【4】private void loadFromDisk() //SharedPreferencesImpl.java
private void loadFromDisk() {synchronized (mLock) {if (mLoaded) {return;}if (mBackupFile.exists()) {mFile.delete();mBackupFile.renameTo(mFile);}}// Debuggingif (mFile.exists() && !mFile.canRead()) {Log.w(TAG, "Attempt to read preferences file " + mFile + " without permission");}Map map = null;StructStat stat = null;try {stat = Os.stat(mFile.getPath());if (mFile.canRead()) {BufferedInputStream str = null;try {//从文件读取并解析xml为map对象str = new BufferedInputStream(new FileInputStream(mFile), 16*1024);map = XmlUtils.readMapXml(str);} catch (Exception e) {Log.w(TAG, "Cannot read " + mFile.getAbsolutePath(), e);} finally {IoUtils.closeQuietly(str);}}} catch (ErrnoException e) {/* ignore */}synchronized (mLock) {// 标记为已加载状态mLoaded = true;if (map != null) {//将文件信息保存到mMap缓存中mMap = map;// 更新xml文件修改时间及文件大小mStatTimestamp = stat.st_mtim;mStatSize = stat.st_size;} else {mMap = new HashMap<>();}//唤醒处于等待状态的线程mLock.notifyAll();}}复制代码
2.获取数据 getXxx() 的流程
【4】getString(String key, @Nullable String defValue) //SharedPreferencesImpl.java
可见, 所有的 get 操作都是线程安全的. 并且 get 仅仅是从内存中(mMap) 获取数据, 所以无性能问题.
@Nullable
public String getString(String key, @Nullable String defValue) {synchronized (mLock) {//阻塞等待异步加载线程加载完成awaitLoadedLocked();//获取map中key对应的stringString v = (String)mMap.get(key);return v != null ? v : defValue;}
}复制代码
考虑到 配置文件的加载是在单独的线程中异步进行的(参考 ‘SharedPreferences 的构造’), 所以这里的 awaitLoadedLocked 是在等待配置文件加载完毕. 也就是说如果我们第一次构造 SharedPreferences 后就立刻调用 getXxx 方法, 很有可能读取配置文件的线程还未完成, 所以这里要等待该线程做完相应的加载工作. 来看看awaitLoadedLocked 的源码:
【5】awaitLoadedLocked() //SharedPreferencesImpl.java
private void awaitLoadedLocked() {if (!mLoaded) {// Raise an explicit StrictMode onReadFromDisk for this// thread, since the real read will be in a different// thread and otherwise ignored by StrictMode.BlockGuard.getThreadPolicy().onReadFromDisk();}while (!mLoaded) {try {mLock.wait();} catch (InterruptedException unused) {}}
}复制代码
如果加载还未完成(mLoaded == false), getXxx 会卡在 awaitLoadedLocked, 一旦加载配置文件的线程工作完毕, 则这个加载线程会通过 notifyAll 会通知所有在 awaitLoadedLocked 中等待的线程, getXxx 就能够返回了. 不过大部分情况下, mLoaded == true. 这样的话 awaitLoadedLocked 会直接返回
3.存储数据 putXxx() 的流程
【6】putString(String key, @Nullable String value) //SharedPreferencesImpl.EditorImpl.java
public final class EditorImpl implements Editor {private final Object mLock = new Object();@GuardedBy("mLock")private final Map<String, Object> mModified = Maps.newHashMap();@GuardedBy("mLock")private boolean mClear = false;public Editor putString(String key, @Nullable String value) {//加了一个EditorImpl对象的同步锁,主要用来控制mModified的单线程操作synchronized (mLock) {mModified.put(key, value);return this;}}// 此处省略若干行代码....public Editor clear() {synchronized (mLock) {//修改mClear标志为true,在后续 commit及apply操作的时候,修改内存数据 commitToMemory 方法中会使用到mClear = true;return this;}}// 此处省略若干行代码....}复制代码
EditorImpl中创建了mModified缓存用于保存将被put的数据;mClear 表示是否要清空配置
可见,在调用putXxx() 方法之前,需要先获取Editor对象,SP则通过edit()方法获取Editor对象,源码如下:
【7】edit() //SharedPreferencesImpl.java
public Editor edit() {// TODO: remove the need to call awaitLoadedLocked() when// requesting an editor. will require some work on the// Editor, but then we should be able to do://// context.getSharedPreferences(..).edit().putString(..).apply()//// ... all without blocking.synchronized (mLock) {//等待异步加载线程完成加载awaitLoadedLocked();}return new EditorImpl();
}复制代码
可以看到 putXxx()方法并没有真正的将数据保存到磁盘文件,只是临时保存了自身mModified中,只有最终执行commit()或者apply()同步数据到SharedPreferences中的map,随后同步或者异步提交数据到磁盘文件。下面请看commit()或者apply()的源码:
【8】apply() //SharedPreferencesImpl.EditorImpl.java
public void apply() {final long startTime = System.currentTimeMillis();//详见【10】final MemoryCommitResult mcr = commitToMemory();final Runnable awaitCommit = new Runnable() {public void run() {try {//等待写文件结束mcr.writtenToDiskLatch.await();} catch (InterruptedException ignored) {}if (DEBUG && mcr.wasWritten) {Log.d(TAG, mFile.getName() + ":" + mcr.memoryStateGeneration+ " applied after " + (System.currentTimeMillis() - startTime)+ " ms");}}};QueuedWork.addFinisher(awaitCommit);//写入操作完成后Runnable postWriteRunnable = new Runnable() {public void run() {awaitCommit.run();QueuedWork.removeFinisher(awaitCommit);}};// 调用enqueueDiskWrite方法执行文件写入操作,详见【11】SharedPreferencesImpl.this.enqueueDiskWrite(mcr, postWriteRunnable);// Okay to notify the listeners before it's hit disk// because the listeners should always get the same// SharedPreferences instance back, which has the// changes reflected in memory.notifyListeners(mcr);
}复制代码
【9】commit() //SharedPreferencesImpl.EditorImpl.java
public boolean commit() {long startTime = 0;if (DEBUG) {startTime = System.currentTimeMillis();}//与apply方法一样也是先提交内存MemoryCommitResult mcr = commitToMemory();SharedPreferencesImpl.this.enqueueDiskWrite( mcr, null /* sync write on this thread okay */);try {//阻塞等待写操作完成mcr.writtenToDiskLatch.await();} catch (InterruptedException e) {return false;} finally {if (DEBUG) {Log.d(TAG, mFile.getName() + ":" + mcr.memoryStateGeneration+ " committed after " + (System.currentTimeMillis() - startTime)+ " ms");}}//通知监听器notifyListeners(mcr);return mcr.writeToDiskResult;
}复制代码
【10】commitToMemory() //SharedPreferencesImpl.EditorImpl.java
MemoryCommitResult正如它的命名一样,是表示内存提交结果的数据结构,用于标注是否有数据改变、改变的key列表、监听器、需要写入文件的数据、写文件结果等。
// 将Editor的数据同步到SharedPreferences的缓存map中,它返回的是MemoryCommitResult类型的结果
// Returns true if any changes were made
private MemoryCommitResult commitToMemory() {long memoryStateGeneration;List<String> keysModified = null;Set<OnSharedPreferenceChangeListener> listeners = null;Map<String, Object> mapToWriteToDisk;synchronized (SharedPreferencesImpl.this.mLock) {// We optimistically don't make a deep copy until// a memory commit comes in when we're already// writing to disk.if (mDiskWritesInFlight > 0) {// We can't modify our mMap as a currently// in-flight write owns it. Clone it before// modifying it.// noinspection uncheckedmMap = new HashMap<String, Object>(mMap);}//将内存中的mMap赋值给要写到disk的MapmapToWriteToDisk = mMap;mDiskWritesInFlight++;boolean hasListeners = mListeners.size() > 0;if (hasListeners) {keysModified = new ArrayList<String>();listeners = new HashSet<OnSharedPreferenceChangeListener>(mListeners.keySet());}synchronized (mLock) {boolean changesMade = false;// 前面调用了clear方法设置了需要clearif (mClear) {if (!mMap.isEmpty()) {changesMade = true;mMap.clear();}mClear = false;}//遍历mModified,将remove的数据移除,将新数据放进去for (Map.Entry<String, Object> e : mModified.entrySet()) {String k = e.getKey();Object v = e.getValue();// "this" is the magic value for a removal mutation. In addition,// setting a value to "null" for a given key is specified to be// equivalent to calling remove on that key.if (v == this || v == null) {if (!mMap.containsKey(k)) {continue;}mMap.remove(k);} else {if (mMap.containsKey(k)) {Object existingValue = mMap.get(k);if (existingValue != null && existingValue.equals(v)) {continue;}}//把变化和新加的数据更新到SharePreferenceImpl的mMap中mMap.put(k, v);}changesMade = true;if (hasListeners) {keysModified.add(k);}}//清空Editor中临时缓存数据mModified.clear();if (changesMade) {mCurrentMemoryStateGeneration++;}memoryStateGeneration = mCurrentMemoryStateGeneration;}}return new MemoryCommitResult(memoryStateGeneration, keysModified, listeners,mapToWriteToDisk);
}复制代码
【11】enqueueDiskWrite(final MemoryCommitResult mcr, final Runnable postWriteRunnable)
private void enqueueDiskWrite(final MemoryCommitResult mcr,final Runnable postWriteRunnable) {//是否同步提交,也就是是否调用了commit()方法 final boolean isFromSyncCommit = (postWriteRunnable == null);final Runnable writeToDiskRunnable = new Runnable() {public void run() {synchronized (mWritingToDiskLock) {writeToFile(mcr, isFromSyncCommit);}synchronized (mLock) {mDiskWritesInFlight--;}if (postWriteRunnable != null) {postWriteRunnable.run();}}};//commit()提交的方式即同步提交// Typical #commit() path with fewer allocations, doing a write on// the current thread.if (isFromSyncCommit) {boolean wasEmpty = false;synchronized (mLock) {//当前只有一个写操作wasEmpty = mDiskWritesInFlight == 1;}//直接执行写入操作,注意:这里直接调用了run方法,并没有调用线程的start方法,所以这里是同步提交if (wasEmpty) {writeToDiskRunnable.run();return;}}//异步的方式,则加入工作队列异步执行写入操作QueuedWork.queue(writeToDiskRunnable, !isFromSyncCommit);
}复制代码
总结
-
commit()与apply()的区别
(1)commit 操作是把全部数据更新到文件,同步执行的,所以要确保putXxxt(key,value)里的value数据量不要太大;
(2)apply 操作是将修改先提交到内存,再异步执行写入文件;
(3)多并发的提交commit时,需等待正在处理的commit数据更新到磁盘文件后才会继续往下执行,从而降低效率; 而apply只是原子更新到内存,后调用apply函数会直接覆盖前面内存数据,从一定程度上提高很多效率;
-
Sharedpreferences保存的数据不宜过大,如果你的sp文件比较大,那么会带来两个严重问题:
(1)第一次从sp中获取值的时候,有可能阻塞主线程,使界面卡顿、掉帧。
(2)解析sp的时候会产生大量的临时对象,导致频繁GC,引起界面卡顿。
(3)这些key和value会永远存在于内存之中,占用大量内存。
-
高频写操作的key与高频读操作的key可以适当地拆分文件, 由于减少同步锁竞争;
-
不要连续多次edit(), 应该获取一次获取edit(),然后多次执行putxxx(), 减少内存波动;
-
不要高频地使用apply, 尽可能地批量提交;commit直接在主线程操作, 更要注意了;
-
不是进程安全,所以不要用于在多进程间数据通信;
-
从 Android N 开始, 不再支持 MODE_WORLD_READABLE & MODE_WORLD_WRITEABLE;
参考
1.彻底搞懂 SharedPreferences
2.全面剖析SharedPreferences
转载于:https://juejin.im/post/5b7e9396518825430810c13a
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
相关文章
- [zz]Kotlin 和 Checked Exception
Kotlin 和 Checked Exception 最近 JetBrains 的 Kotlin 语言忽然成了热门话题。国内小编们传言说,Kotlin 取代了 Java,成为了 Android 的“钦定语言”,很多人听了之后热血沸腾。初学者们也开始注意到 Kotlin,问出各种“傻问题”,很“功利”的问题,比如“现在学 Kotlin 是…...
2024/5/10 6:01:19 - 使用Python face_recognition 人脸识别 - 5 人脸比对并打分
比对两张人脸编码后的照片,打印出相似度。import face_recognition# Often instead of just checking if two faces match or not (True or False), its helpful to see how similar they are. # You can do that by using the face_distance function.# The model was traine…...
2024/4/20 11:23:20 - 权限管理系统设计
组织模型 资源模型 操作模型 谁能够执行哪些操作 执行资源的范围 资源概念:资源就是想要的到的最终物质,我们可以给每一个资源定义一个权限,也可以给某一类资源定义一个权限 权限概念:权限是对资源的一种保护访问.用户要访问A资源前提是用户必须有A资源的访问权限. 角色…...
2024/4/16 22:44:10 - linux centos 04
1.python的虚拟环境 1.将当前机器上的解释器作为一个 本地,复制出的很多歌 虚拟解释器 物理机上的 本体解释器 ,什么事也不做 分身1: 解释器1;虚拟环境1 运行django 1.11.11业务 分身2 :虚拟环境2 运行django 2.2业务 virtualenv 可以在系统中建立多个不同并且相…...
2024/4/16 22:43:52 - eclipse使用git进行代码修改合并、GitHub代码同步和版本回退等操作
1、修改代码后提交修改的文件回出现在以下位置中,选中右键add index——》填写commit message——》commit将代码push到GitHub:右键项目——》team——》remote——》push——》填写你的GitHub仓库的uri(例如https://github.com/strawHatt/Test)——》next填写如下——》fi…...
2024/4/16 22:43:58 - 从源码看Spring Security的角色和权限之区别
Spring Security中的角色(roles)和权限(authorities)是有区别的。笔者这篇文章将和大家一起从Spring Security源码的角度探讨其区别在何处,以及合理的使用角色和权限,让我们在使用时做到知其然且知其所以然。 项目环境:jdk1.8,Springboot 2.1.0,IntelliJ idea2018 首先…...
2024/4/16 22:43:40 - Android SharedPreferences工具类 ,实现List/Map的保存读取
遇到好的文章要及时转载转载请注明出处:http://blog.csdn.net/a512337862/article/details/73633420/*** Created by ZhangHao on 2016/6/21.* SharedPreferences 工具类*/public class SharedPreferencesUtil {private static SharedPreferencesUtil util;private static Sha…...
2024/4/16 22:44:04 - Kotlin 快速入门
前言人生苦多,快来 Kotlin ,快速学习Kotlin!什么是Kotlin?Kotlin 是种静态类型编程语言 用于现代多平台应用 100%可与Java™和Android™互操作,它是[JetBrains]开发的基于JVM的语言 开发IDE : Intellij / AndroidStudio3.0 preview 参考: Kotlin 官网 / Kotlin 语言中文…...
2024/4/16 22:42:58 - 图论 —— 最短路
【概述】最短路是图论中十分常见的一个问题,可分为单源最短路与全源最短路。对于单源最短路来说,有时间复杂度为 O(E+VlogV) 要求权值非负的 Dijkstra,时间复杂度为 O(VE) 适用于带负权值的 Bellman Ford对于全源最短路来说,有时间复杂度为 O(V*V*V) 的利用动态规划思想的 …...
2024/4/17 3:14:25 - 动态编程和基因序列比对
动态编程和基因序列比对计算机科学助力分子生物学 级别: 高级Paul Reiners (reiners@us.ibm.com), 软件工程师, IBM 2008 年 4 月 17 日分子生物学越来越多地将计算机科学算法作为研究工具。本文将介绍生物信息学 — 用计算机解决生物学问题。学习动态编程 的基本原…...
2024/4/20 9:15:04 - 内容管理系统的设计和选型
内容管理系统概述内容管理系统是一个很泛的概念:从商业门户网站的新闻系统到个人的Weblog都可以称作发布系统。框架型:本身不包含任何应用实现,只是提供了底层框架,具体应用需要一定的二次开发,比如Cocoon,Vignette; 应用型:本身是一个面向具体类型的应用实现,已经包…...
2024/4/16 22:43:40 - SpringSecurity中使用MD5密码加密
前言:在上一篇中说到了SpringSecurity中的表单验证和权限控制,接下来说一下如果你在SpringSecurity中不使用默认的加密方式,而是使用自定义的加密方式,比如MD5,该如何继承呢?一、为什么使用加密我们先来说一下使用加密后的密码处理流程。我们为什么要使用密文呢?也就是加…...
2024/4/16 22:44:04 - PreferenceStore存不进数据
PreferencePage配合PreferenceStore确实是一种解决选项配置问题的极佳办法。但是PreferenceStore是有很多缺陷的,不晓得广大Java同行是怎么应用这玩意的。但是我的用法很特别,一个PreferencePage的实例中关联了两个PreferenceStore。这时,问题来了,Override的performApply(…...
2024/4/16 22:43:40 - 《Kotlin极简教程》第一章 Kotlin简介
最新上架!!! 《 Kotlin极简教程》 陈光剑 (机械工业出版社):https://mp.weixin.qq.com/s/bzRkGSO6T1O2AELM_UqKUQfun max(a: Int, b: Int): Int {return if (a > b) a else b }fun main(args: Array<String>) {println(max(1, 2)) }“我真正关心的是Java虚拟机的…...
2024/4/16 22:44:10 - 学习Linux十(Linux必学60个命令之【其它命令】)
Linux必学的60个命令:其它命令在前面几讲中,我们把Linux命令按照在系统中的作用分成几个部分分别予以介绍。但是,还有一些命令不好划分,然而学习它们同样是比较重要的。 tar1.作用tar命令是Unix/Linux系统中备份文件的可靠方法,几乎可以工作于任何环境中,它的使用权限是所…...
2024/3/31 22:26:53 - Kotlin系列教程——史上最全面、最详细的学习教程,持续更新中....
关于这个系列教程,我是从最基础的开发环境搭建到项目进阶到后面的项目开发这个过程来写的。我一直秉承从实际项目开发以及源码解析的角度去写好这个教程,并让从未接触过编程的朋友能学好kotlin这门语言。所以我想把这个教程写到最详细、最全面。并且也持之以恒的写下去。 前言…...
2024/4/16 22:47:40 - Spring Security 自动踢掉前一个登录用户,一个配置搞定!
登录成功后,自动踢掉前一个登录用户,松哥第一次见到这个功能,就是在扣扣里边见到的,当时觉得挺好玩的。 自己做开发后,也遇到过一模一样的需求,正好最近的 Spring Security 系列正在连载,就结合 Spring Security 来和大家聊一聊这个功能如何实现。 本文是本系列的第十三…...
2024/4/16 22:45:04 - 两个数据库进行数据比对(DataTable对比)
前一段时间做了一个数据比对的工作,大致的要求是这样: 首先从A库导出产品的数据模型到Excel中,导出完成时记录导出产品条目以及产品结构到B库的Model表和Partstr表中。然后就是每隔一段固定时间系统自动进行数据比对(系统自动执行比对服务详见http://blog.csdn.net/u012147…...
2024/3/31 22:26:48 - 使用SharedPreferences实现登录记住密码功能实现
具体实现方法以及步骤请看代码! 登录框 login.xml <?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:l…...
2024/4/18 20:12:04 - 【S2第二学期-使用JSP/Servlet技术开发新闻发布系统】全书知识点总结
使用JSP/Servlet技术开发新闻发布系统 第一章 动态网页开发基础 1. 动态网页的优势: a) 交互性– 响应客户端的请求并回发 b) 自动更新– 自动生成的HTML代码而无须依次手动编写 c) 随机性– 不同客户访问同一网站时会产生不同的效果 2. …...
2024/4/17 3:16:06
最新文章
- 软件设计师考试---访问控制列表、堆,栈和堆栈、防火墙、数据流图、嵌入式操作、绑定方式、uml、模式、传输协议
访问控制列表 访问控制列表(Access Control List,ACL) 是一种用于控制对资源(如文件、目录、网络资源等)访问权限的方法。ACL是在计算机安全领域广泛使用的概念,它允许系统管理员定义哪些用户或系统进程有…...
2024/5/10 7:42:33 - 梯度消失和梯度爆炸的一些处理方法
在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言,在此感激不尽。 权重和梯度的更新公式如下: w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...
2024/5/9 21:23:04 - 【LeetCode热题100】【二叉树】二叉树的中序遍历
题目链接:94. 二叉树的中序遍历 - 力扣(LeetCode) 中序遍历就是先遍历左子树再遍历根最后遍历右子树 class Solution { public:void traverse(TreeNode *root) {if (!root)return;traverse(root->left);ans.push_back(root->val);tra…...
2024/5/5 8:39:08 - 腾讯云容器与Serverless的融合:探索《2023技术实践精选集》中的创新实践
腾讯云容器与Serverless的融合:探索《2023技术实践精选集》中的创新实践 文章目录 腾讯云容器与Serverless的融合:探索《2023技术实践精选集》中的创新实践引言《2023腾讯云容器和函数计算技术实践精选集》整体评价特色亮点分析Serverless与Kubernetes的…...
2024/5/9 9:40:42 - 【外汇早评】美通胀数据走低,美元调整
原标题:【外汇早评】美通胀数据走低,美元调整昨日美国方面公布了新一期的核心PCE物价指数数据,同比增长1.6%,低于前值和预期值的1.7%,距离美联储的通胀目标2%继续走低,通胀压力较低,且此前美国一季度GDP初值中的消费部分下滑明显,因此市场对美联储后续更可能降息的政策…...
2024/5/8 6:01:22 - 【原油贵金属周评】原油多头拥挤,价格调整
原标题:【原油贵金属周评】原油多头拥挤,价格调整本周国际劳动节,我们喜迎四天假期,但是整个金融市场确实流动性充沛,大事频发,各个商品波动剧烈。美国方面,在本周四凌晨公布5月份的利率决议和新闻发布会,维持联邦基金利率在2.25%-2.50%不变,符合市场预期。同时美联储…...
2024/5/9 15:10:32 - 【外汇周评】靓丽非农不及疲软通胀影响
原标题:【外汇周评】靓丽非农不及疲软通胀影响在刚结束的周五,美国方面公布了新一期的非农就业数据,大幅好于前值和预期,新增就业重新回到20万以上。具体数据: 美国4月非农就业人口变动 26.3万人,预期 19万人,前值 19.6万人。 美国4月失业率 3.6%,预期 3.8%,前值 3…...
2024/5/4 23:54:56 - 【原油贵金属早评】库存继续增加,油价收跌
原标题:【原油贵金属早评】库存继续增加,油价收跌周三清晨公布美国当周API原油库存数据,上周原油库存增加281万桶至4.692亿桶,增幅超过预期的74.4万桶。且有消息人士称,沙特阿美据悉将于6月向亚洲炼油厂额外出售更多原油,印度炼油商预计将每日获得至多20万桶的额外原油供…...
2024/5/9 4:20:59 - 【外汇早评】日本央行会议纪要不改日元强势
原标题:【外汇早评】日本央行会议纪要不改日元强势近两日日元大幅走强与近期市场风险情绪上升,避险资金回流日元有关,也与前一段时间的美日贸易谈判给日本缓冲期,日本方面对汇率问题也避免继续贬值有关。虽然今日早间日本央行公布的利率会议纪要仍然是支持宽松政策,但这符…...
2024/5/4 23:54:56 - 【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响
原标题:【原油贵金属早评】欧佩克稳定市场,填补伊朗问题的影响近日伊朗局势升温,导致市场担忧影响原油供给,油价试图反弹。此时OPEC表态稳定市场。据消息人士透露,沙特6月石油出口料将低于700万桶/日,沙特已经收到石油消费国提出的6月份扩大出口的“适度要求”,沙特将满…...
2024/5/4 23:55:05 - 【外汇早评】美欲与伊朗重谈协议
原标题:【外汇早评】美欲与伊朗重谈协议美国对伊朗的制裁遭到伊朗的抗议,昨日伊朗方面提出将部分退出伊核协议。而此行为又遭到欧洲方面对伊朗的谴责和警告,伊朗外长昨日回应称,欧洲国家履行它们的义务,伊核协议就能保证存续。据传闻伊朗的导弹已经对准了以色列和美国的航…...
2024/5/4 23:54:56 - 【原油贵金属早评】波动率飙升,市场情绪动荡
原标题:【原油贵金属早评】波动率飙升,市场情绪动荡因中美贸易谈判不安情绪影响,金融市场各资产品种出现明显的波动。随着美国与中方开启第十一轮谈判之际,美国按照既定计划向中国2000亿商品征收25%的关税,市场情绪有所平复,已经开始接受这一事实。虽然波动率-恐慌指数VI…...
2024/5/7 11:36:39 - 【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试
原标题:【原油贵金属周评】伊朗局势升温,黄金多头跃跃欲试美国和伊朗的局势继续升温,市场风险情绪上升,避险黄金有向上突破阻力的迹象。原油方面稍显平稳,近期美国和OPEC加大供给及市场需求回落的影响,伊朗局势并未推升油价走强。近期中美贸易谈判摩擦再度升级,美国对中…...
2024/5/4 23:54:56 - 【原油贵金属早评】市场情绪继续恶化,黄金上破
原标题:【原油贵金属早评】市场情绪继续恶化,黄金上破周初中国针对于美国加征关税的进行的反制措施引发市场情绪的大幅波动,人民币汇率出现大幅的贬值动能,金融市场受到非常明显的冲击。尤其是波动率起来之后,对于股市的表现尤其不安。隔夜美国股市出现明显的下行走势,这…...
2024/5/6 1:40:42 - 【外汇早评】美伊僵持,风险情绪继续升温
原标题:【外汇早评】美伊僵持,风险情绪继续升温昨日沙特两艘油轮再次发生爆炸事件,导致波斯湾局势进一步恶化,市场担忧美伊可能会出现摩擦生火,避险品种获得支撑,黄金和日元大幅走强。美指受中美贸易问题影响而在低位震荡。继5月12日,四艘商船在阿联酋领海附近的阿曼湾、…...
2024/5/4 23:54:56 - 【原油贵金属早评】贸易冲突导致需求低迷,油价弱势
原标题:【原油贵金属早评】贸易冲突导致需求低迷,油价弱势近日虽然伊朗局势升温,中东地区几起油船被袭击事件影响,但油价并未走高,而是出于调整结构中。由于市场预期局势失控的可能性较低,而中美贸易问题导致的全球经济衰退风险更大,需求会持续低迷,因此油价调整压力较…...
2024/5/8 20:48:49 - 氧生福地 玩美北湖(上)——为时光守候两千年
原标题:氧生福地 玩美北湖(上)——为时光守候两千年一次说走就走的旅行,只有一张高铁票的距离~ 所以,湖南郴州,我来了~ 从广州南站出发,一个半小时就到达郴州西站了。在动车上,同时改票的南风兄和我居然被分到了一个车厢,所以一路非常愉快地聊了过来。 挺好,最起…...
2024/5/7 9:26:26 - 氧生福地 玩美北湖(中)——永春梯田里的美与鲜
原标题:氧生福地 玩美北湖(中)——永春梯田里的美与鲜一觉醒来,因为大家太爱“美”照,在柳毅山庄去寻找龙女而错过了早餐时间。近十点,向导坏坏还是带着饥肠辘辘的我们去吃郴州最富有盛名的“鱼头粉”。说这是“十二分推荐”,到郴州必吃的美食之一。 哇塞!那个味美香甜…...
2024/5/4 23:54:56 - 氧生福地 玩美北湖(下)——奔跑吧骚年!
原标题:氧生福地 玩美北湖(下)——奔跑吧骚年!让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 让我们红尘做伴 活得潇潇洒洒 策马奔腾共享人世繁华 对酒当歌唱出心中喜悦 轰轰烈烈把握青春年华 啊……啊……啊 两…...
2024/5/8 19:33:07 - 扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!
原标题:扒开伪装医用面膜,翻六倍价格宰客,小姐姐注意了!扒开伪装医用面膜,翻六倍价格宰客!当行业里的某一品项火爆了,就会有很多商家蹭热度,装逼忽悠,最近火爆朋友圈的医用面膜,被沾上了污点,到底怎么回事呢? “比普通面膜安全、效果好!痘痘、痘印、敏感肌都能用…...
2024/5/5 8:13:33 - 「发现」铁皮石斛仙草之神奇功效用于医用面膜
原标题:「发现」铁皮石斛仙草之神奇功效用于医用面膜丽彦妆铁皮石斛医用面膜|石斛多糖无菌修护补水贴19大优势: 1、铁皮石斛:自唐宋以来,一直被列为皇室贡品,铁皮石斛生于海拔1600米的悬崖峭壁之上,繁殖力差,产量极低,所以古代仅供皇室、贵族享用 2、铁皮石斛自古民间…...
2024/5/8 20:38:49 - 丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者
原标题:丽彦妆\医用面膜\冷敷贴轻奢医学护肤引导者【公司简介】 广州华彬企业隶属香港华彬集团有限公司,专注美业21年,其旗下品牌: 「圣茵美」私密荷尔蒙抗衰,产后修复 「圣仪轩」私密荷尔蒙抗衰,产后修复 「花茵莳」私密荷尔蒙抗衰,产后修复 「丽彦妆」专注医学护…...
2024/5/4 23:54:58 - 广州械字号面膜生产厂家OEM/ODM4项须知!
原标题:广州械字号面膜生产厂家OEM/ODM4项须知!广州械字号面膜生产厂家OEM/ODM流程及注意事项解读: 械字号医用面膜,其实在我国并没有严格的定义,通常我们说的医美面膜指的应该是一种「医用敷料」,也就是说,医用面膜其实算作「医疗器械」的一种,又称「医用冷敷贴」。 …...
2024/5/9 7:32:17 - 械字号医用眼膜缓解用眼过度到底有无作用?
原标题:械字号医用眼膜缓解用眼过度到底有无作用?医用眼膜/械字号眼膜/医用冷敷眼贴 凝胶层为亲水高分子材料,含70%以上的水分。体表皮肤温度传导到本产品的凝胶层,热量被凝胶内水分子吸收,通过水分的蒸发带走大量的热量,可迅速地降低体表皮肤局部温度,减轻局部皮肤的灼…...
2024/5/9 17:11:10 - 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...
解析如下:1、长按电脑电源键直至关机,然后再按一次电源健重启电脑,按F8健进入安全模式2、安全模式下进入Windows系统桌面后,按住“winR”打开运行窗口,输入“services.msc”打开服务设置3、在服务界面,选中…...
2022/11/19 21:17:18 - 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。
%读入6幅图像(每一幅图像的大小是564*564) f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...
2022/11/19 21:17:16 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...
win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面,在等待界面中我们需要等待操作结束才能关机,虽然这比较麻烦,但是对系统进行配置和升级…...
2022/11/19 21:17:15 - 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...
有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows,请勿关闭计算机”的提示,要过很久才能进入系统,有的用户甚至几个小时也无法进入,下面就教大家这个问题的解决方法。第一种方法:我们首先在左下角的“开始…...
2022/11/19 21:17:14 - win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...
置信有很多用户都跟小编一样遇到过这样的问题,电脑时发现开机屏幕显现“正在配置Windows Update,请勿关机”(如下图所示),而且还需求等大约5分钟才干进入系统。这是怎样回事呢?一切都是正常操作的,为什么开时机呈现“正…...
2022/11/19 21:17:13 - 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...
Win7系统开机启动时总是出现“配置Windows请勿关机”的提示,没过几秒后电脑自动重启,每次开机都这样无法进入系统,此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一:开机按下F8,在出现的Windows高级启动选…...
2022/11/19 21:17:12 - 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...
有不少windows10系统用户反映说碰到这样一个情况,就是电脑提示正在准备windows请勿关闭计算机,碰到这样的问题该怎么解决呢,现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法:1、2、依次…...
2022/11/19 21:17:11 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...
今天和大家分享一下win7系统重装了Win7旗舰版系统后,每次关机的时候桌面上都会显示一个“配置Windows Update的界面,提示请勿关闭计算机”,每次停留好几分钟才能正常关机,导致什么情况引起的呢?出现配置Windows Update…...
2022/11/19 21:17:10 - 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...
只能是等着,别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚,只能是考虑备份数据后重装系统了。解决来方案一:管理员运行cmd:net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...
2022/11/19 21:17:09 - 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?
原标题:电脑提示“配置Windows Update请勿关闭计算机”怎么办?win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢?一般的方…...
2022/11/19 21:17:08 - 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...
关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!关机提示 windows7 正在配…...
2022/11/19 21:17:05 - 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...
钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...
2022/11/19 21:17:05 - 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...
前几天班里有位学生电脑(windows 7系统)出问题了,具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面,长时间没反应,无法进入系统。这个问题原来帮其他同学也解决过,网上搜了不少资料&#x…...
2022/11/19 21:17:04 - 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...
本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法,并在最后教给你1种保护系统安全的好方法,一起来看看!电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中,添加了1个新功能在“磁…...
2022/11/19 21:17:03 - 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...
许多用户在长期不使用电脑的时候,开启电脑发现电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机。。.这要怎么办呢?下面小编就带着大家一起看看吧!如果能够正常进入系统,建议您暂时移…...
2022/11/19 21:17:02 - 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...
配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!配置windows update失败 还原更改 请勿关闭计算机&#x…...
2022/11/19 21:17:01 - 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...
不知道大家有没有遇到过这样的一个问题,就是我们的win7系统在关机的时候,总是喜欢显示“准备配置windows,请勿关机”这样的一个页面,没有什么大碍,但是如果一直等着的话就要两个小时甚至更久都关不了机,非常…...
2022/11/19 21:17:00 - 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...
当电脑出现正在准备配置windows请勿关闭计算机时,一般是您正对windows进行升级,但是这个要是长时间没有反应,我们不能再傻等下去了。可能是电脑出了别的问题了,来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...
2022/11/19 21:16:59 - 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...
我们使用电脑的过程中有时会遇到这种情况,当我们打开电脑之后,发现一直停留在一个界面:“配置Windows Update失败,还原更改请勿关闭计算机”,等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢࿰…...
2022/11/19 21:16:58 - 如何在iPhone上关闭“请勿打扰”
Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...
2022/11/19 21:16:57