精华内容
下载资源
问答
  • sharepreference是什么
    2021-06-08 03:47:18

    Android提供了SharePreference方便程序存储自己的key-value数据,使用非常方便,不用自己再却写文件了。通过SharePreference保存的文件为一个标准的xml文件。

    public void saveToSharedPreference(View v){

    sp = this.getSharedPreferences("config.txt", Context.MODE_PRIVATE);

    //得到sharedpreference的编辑器

    SharedPreferences.Editor editor = sp.edit();

    editor.putString("title","www.sharejs.com");

    editor.putBoolean("success",true);

    //提交数据

    editor.commit();

    Toast.makeText(this,"保存到sharedpreference成功",Toast.LENGTH_SHORT).show();

    //读取SharePreference的内容

    String tel = sp.getString("title","没有获取到值");

    Toast.makeText(this,tel,Toast.LENGTH_SHORT).show();

    }

    标签:

    版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com

    特别注意:本站所有转载文章言论不代表本站观点!

    本站所提供的图片等素材,版权归原作者所有,如需使用,请与原作者联系。

    更多相关内容
  • SharePreference原理

    千次阅读 2020-08-27 20:19:24
    SharedPreferences是Android提供的数据持久化的一种手段,适合单进程、小批量的数据存储与访问。因为SharedPreferences的实现是基于单个xml文件实现的,并且,所有持久化数据都是一次性加载到内存,如果数据过大,是...

    SharedPreferences是Android提供的数据持久化的一种手段,适合单进程、小批量的数据存储与访问。因为SharedPreferences的实现是基于单个xml文件实现的,并且,所有持久化数据都是一次性加载到内存,如果数据过大,是不合适采用SharedPreferences存放的。而适用的场景是单进程的原因同样如此,由于Android原生的文件访问并不支持多进程互斥,所以SharePreferences也不支持,如果多个进程更新同一个xml文件,就可能存在同不互斥问题。

    SharedPreferences的实现原理之:持久化数据的加载

    首先,从基本使用简单看下SharedPreferences的实现原理:

        mSharedPreferences = context.getSharedPreferences("test", Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = mSharedPreferences.edit();
        editor.putString(key, value);
        editor.apply();

    context.getSharedPreferences其实就是简单的调用ContextImpl的getSharedPreferences,具体实现如下:

           @Override
    public SharedPreferences getSharedPreferences(String name, int mode) {
        SharedPreferencesImpl sp;
        synchronized (ContextImpl.class) {
            if (sSharedPrefs == null) {
                sSharedPrefs = new ArrayMap<String, ArrayMap<String, SharedPreferencesImpl>>();
            }
    
            final String packageName = getPackageName();
            ArrayMap<String, SharedPreferencesImpl> packagePrefs = sSharedPrefs.get(packageName);
            if (packagePrefs == null) {
                packagePrefs = new ArrayMap<String, SharedPreferencesImpl>();
                sSharedPrefs.put(packageName, packagePrefs);
            }
            sp = packagePrefs.get(name);
            if (sp == null) {
            <!--读取文件-->
                File prefsFile = getSharedPrefsFile(name);
                sp = new SharedPreferencesImpl(prefsFile, mode);
                <!--缓存sp对象-->
                packagePrefs.put(name, sp);
                return sp;
            }
        }
        <!--跨进程同步问题-->
        if ((mode & Context.MODE_MULTI_PROCESS) != 0 ||
            getApplicationInfo().targetSdkVersion < android.os.Build.VERSION_CODES.HONEYCOMB) {
            sp.startReloadIfChangedUnexpectedly();
        }
        return sp;
    }

    以上代码非常简单,直接描述下来就是先去内存中查询与xml对应的SharePreferences是否已经被创建加载,如果没有那么该创建就创建,该加载就加载,在加载之后,要将所有的key-value保存到内幕才能中去,当然,如果首次访问,可能连xml文件都不存在,那么还需要创建xml文件,与SharePreferences对应的xml文件位置一般都在/data/data/包名/shared_prefs目录下,后缀一定是.xml,数据存储样式如下:

    这里面数据的加载的地方需要看下,比如,SharePreferences数据的加载是同步还是异步?数据加载是new SharedPreferencesImpl对象时候开始的,

     SharedPreferencesImpl(File file, int mode) {
        mFile = file;
        mBackupFile = makeBackupFile(file);
        mMode = mode;
        mLoaded = false;
        mMap = null;
        startLoadFromDisk();
    }
    

    startLoadFromDisk很简单,就是读取xml配置,如果其他线程想要在读取之前就是用的话,就会被阻塞,一直wait等待,直到数据读取完成。

        private void loadFromDiskLocked() {
       ...
        Map map = null;
        StructStat stat = null;
        try {
            stat = Os.stat(mFile.getPath());
            if (mFile.canRead()) {
                BufferedInputStream str = null;
                try {
        <!--读取xml中配置-->
                    str = new BufferedInputStream(
                            new FileInputStream(mFile), 16*1024);
                    map = XmlUtils.readMapXml(str);
                }...
        mLoaded = true;
        ...
        <!--唤起其他等待线程-->
        notifyAll();
    }
    

    可以看到其实就是直接使用xml解析工具XmlUtils,直接在当前线程读取xml文件,所以,如果xml文件稍大,尽量不要在主线程读取,读取完成之后,xml中的配置项都会被加载到内存,再次访问的时候,其实访问的是内存缓存。

    SharedPreferences的实现原理之:持久化数据的更新

    通常更新SharedPreferences的时候是首先获取一个SharedPreferences.Editor,利用它缓存一批操作,之后当做事务提交,有点类似于数据库的批量更新:

        SharedPreferences.Editor editor = mSharedPreferences.edit();
        editor.putString(key1, value1);
        editor.putString(key2, value2);
        editor.putString(key3, value3);
        editor.apply();//或者commit
    

    Editor是一个接口,这里的实现是一个EditorImpl对象,它首先批量预处理更新操作,之后再提交更新,在提交事务的时候有两种方式,一种是apply,另一种commit,两者的区别在于:何时将数据持久化到xml文件,前者是异步的,后者是同步的。Google推荐使用前一种,因为,就单进程而言,只要保证内存缓存正确就能保证运行时数据的正确性,而持久化,不必太及时,这种手段在Android中使用还是很常见的,比如权限的更新也是这样,况且,Google并不希望SharePreferences用于多进程,因为不安全,手下卡一下apply与commit的区别

        public void apply() {
        <!--添加到内存-->
            final MemoryCommitResult mcr = commitToMemory();
            final Runnable awaitCommit = new Runnable() {
                    public void run() {
                        try {
                            mcr.writtenToDiskLatch.await();
                        } catch (InterruptedException ignored) {
                        }
                    }
                };
    
            QueuedWork.add(awaitCommit);
            Runnable postWriteRunnable = new Runnable() {
                    public void run() {
                        awaitCommit.run();
                        QueuedWork.remove(awaitCommit);
                    }
                };
            <!--延迟写入到xml文件-->
            SharedPreferencesImpl.this.enqueueDiskWrite(mcr, postWriteRunnable);
            <!--通知数据变化-->
            notifyListeners(mcr);
        }
     
     public boolean commit() {
            MemoryCommitResult mcr = commitToMemory();
            SharedPreferencesImpl.this.enqueueDiskWrite(
                mcr, null /* sync write on this thread okay */);
            try {
                mcr.writtenToDiskLatch.await();
            } catch (InterruptedException e) {
                return false;
            }
            notifyListeners(mcr);
            return mcr.writeToDiskResult;
        }     
    

    从上面可以看出两者最后都是先调用commitToMemory,将更改提交到内存,在这一点上两者是一致的,之后又都调用了enqueueDiskWrite进行数据持久化任务,不过commit函数一般会在当前线程直接写文件,而apply则提交一个事务到已给线程池,之后直接返回,实现如下:

     private void enqueueDiskWrite(final MemoryCommitResult mcr,
                                  final Runnable postWriteRunnable) {
        final Runnable writeToDiskRunnable = new Runnable() {
                public void run() {
                    synchronized (mWritingToDiskLock) {
                        writeToFile(mcr);
                    }
                    synchronized (SharedPreferencesImpl.this) {
                        mDiskWritesInFlight--;
                    }
                    if (postWriteRunnable != null) {
                        postWriteRunnable.run();
                    }
                }
            };
       final boolean isFromSyncCommit = (postWriteRunnable == null);
        if (isFromSyncCommit) {
            boolean wasEmpty = false;
            synchronized (SharedPreferencesImpl.this) {
                wasEmpty = mDiskWritesInFlight == 1;
            }
            <!--如果没有其他线程在写文件,直接在当前线程执行-->
            if (wasEmpty) {
                writeToDiskRunnable.run();
                return;
            }
        }
       QueuedWork.singleThreadExecutor().execute(writeToDiskRunnable);
    }
    

    不过如果有线程在写文件,那么就不能直接写,这个时候就跟apply函数一致了,但是,如果直观说两者的区别的话,直接说commit同步,而apply异步应该也是没有多大问题的

    SharePreferences多进程使用问题

    SharePreferences在新建的有个mode参数,可以指定它的加载模式,MODE_MULTI_PROCESS是Google提供的一个多进程模式,但是这种模式并不是我们说的支持多进程同步更新等,它的作用只会在getSharedPreferences的时候,才会重新从xml重加载,如果我们在一个进程中更新xml,但是没有通知另一个进程,那么另一个进程的SharePreferences是不会自动更新的。

    @Override
    public SharedPreferences getSharedPreferences(String name, int mode) {
        SharedPreferencesImpl 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;
    }
    

    也就是说MODE_MULTI_PROCESS只是个鸡肋Flag,对于多进程的支持几乎为0,下面是Google文档,简而言之,就是:不要用

    MODE_MULTI_PROCESS does not work reliably in some versions of Android, and furthermore does not provide any mechanism for reconciling concurrent modifications across processes. Applications should not attempt to use it. Instead, they should use an explicit cross-process data management approach such as ContentProvider。

    响应的Google为多进程提供了一个数据同步互斥方案,那就是基于Binder实现的ContentProvider,关于ContentProvider后文分析。

    总结

    1. SharePreferences是Android基于xml实现的一种数据持久化手段。

    2. sp不适合存储过大的数据,因为它一直保存在内存中,数据过大容易造成内存溢出。

    3. SharePreferences的commit与apply一个是同步一个是异步(大部分场景下),sp的commit方法是直接在当前线程执行文件写入      操作,而apply方法是在工作线程执行文件写入,尽可能使用apply,因为不会阻塞当前线程。

    4. sp并不支持跨进程,因为它不能保证更新本地数据后被另一个进程所知道,而且跨进程的操作标记已经被弃用。

    5. sp批量更改数据时,只需要保留最后一个apply即可,避免添加多余的写文件任务。

    6. 每个sp存储的键值对不宜过多,否则在加载文件数据到内存时会耗时过长,而阻塞sp的相关getput方法,造成ui卡顿。

    7. 频繁更改的配置项和不常更改的配置项应该分开为不同的sp存放,避免不必要的io操作。

    转载地址:https://www.jianshu.com/p/4984f66f9a4b

     

     

     

     

     

     

     

    展开全文
  • sharePreference

    2016-12-06 16:00:53
    封装的一些关于sharePreference的方法
  • sharepreference

    2015-02-26 16:39:08
    Android平台给我们提供了一个SharedPreferences类,它是一个轻量级的存储类,特别适合用于保存软件配置参数。使用SharedPreferences保存数据,其背后是用xml文件存放数据,文件存放在/data/data/<package name>/...
  • SharePreference

    2015-06-30 00:43:18
    SharePreference简单使用
  • Android 序列化对象存储到sharepreference
  • Sharepreference 存储数据

    2022-06-29 20:44:52
    一般用于保存这个编号设置,比如设置里的条目。使用步骤:第一步、​ 拿到 share preference。 上面的this指的是上下文context,在...经过这四个步骤,就能实现将数据保存到sharepreference当中。完整代码: 总结

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

    文章目录


    Sharepreference

    一般用于保存这个编号设置,比如设置里的条目。

    使用步骤:

    第一步、

    ​ 拿到 share preference。

    sharedPreferences = this.getSharedPreferences("settings_info", MODE_PRIVATE)
    

    上面的this指的是上下文context,在Activity里面直接使用this获取它(因为Activity继承自context)。

    第二步、

    ​ 进入编辑模式

    val edit = sharedPreferences.edit()
    

    拿到编辑器

    第三步、

    ​ 保存数据

    edit.putBoolean("state", isChecked)
    

    保存数据,put可以保存很多类型,根据想要的类型进行保存。如put String、putLong等。

    第四步、

    ​ 提交编辑器

    edit.commit()
    

    经过这四个步骤,就能实现将数据保存到sharepreference当中。

    完整代码:

    private lateinit var _binding: ActivityPreferenceDemoBinding
    	
    	override fun onCreate(savedInstanceState: Bundle?) {
    		super.onCreate(savedInstanceState)
    		_binding = ActivityPreferenceDemoBinding.inflate(layoutInflater)
    		setContentView(_binding.root)
    		
    		val sharedPreferences = this.getSharedPreferences("settings_info", MODE_PRIVATE)
    		
    		_binding.isAllowUnknownAppsSourcesSwitch.setOnCheckedChangeListener { buttonView, isChecked ->
    			Log.d("wangzhuo", "current state: $isChecked")
    			val edit = sharedPreferences.edit()
    			edit.putBoolean("state", isChecked)
    			edit.commit()
    		}
    	}
    

    总结

    sharepreference存储也是属于内部存储,会在软件的数据目录下(/data/data/com.example.preferencedemo/shared_prefs)。

    以xml的文件形式保存数据。它有一个特点:内容保存起来都是以健值对的形式进行保存。

    展开全文
  • sharepreference删除文件数据不会丢失.rar,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。
  • SharePreference与MMKV对比

    2022-08-04 03:04:51
    SharePreference的实现类SharePreferenceImpl,使用CountDownLatch做同步,commit是先写入内存,同时同步写入磁盘,等待内存写入成功,就返回结果。而apply是异步写入磁盘。写内存和文件时都加锁。 ...

    本文来自刘兆贤的博客_CSDN博客-Java高级,Android旅行,Android基础领域博主 ,引用必须注明出处!

    先了解一种Android特有的存储机制,快写机制MMap。

    MMap:Memory Mapping,内存映射(升级IPC数据传输)。将一块物理内存(可随时读写的),通过文件操作符,同时映射到用户虚拟内存空间,和内核虚拟地址空间(struct vm_struct *area,属于逻辑地址,区别于物理地址,可通过转换器计算)的一段内存块(两者大小相同)。

    多线程:通过加锁(mutex_lock),保证每次只有一个进程被分配内存。

    实现原理:App进程负责写数据,由操作系统负责将内存写入文件。用于快速存储,解决日志写入慢的问题。

    代表性组件:MMKV,Logan

    MMKV存储目录:/data/user/0/applicationId/files/mmkv

    在我看来MMKV只有三个优势,

    1、增量更新,对比全量更新每次覆盖文件,速度更快,防止数据丢失;

    2、存储利用MMAP机制,效率高于文件IO操作;

    3、多应用进程共享时,加了进程锁,而SP不具备;

    4、如果非加一条就是使用protobuffer协议,数据量较xml更少。

    缺点,当存储空间达到一定量级后,需要重新整理(如重复数据删除,key排序等)。

    处理三个问题:指针增长、内存增长、内存整理。通过指针增长,其他进程获得数据变化情况。

    SharePreference的实现类SharePreferenceImpl,使用CountDownLatch做同步,commit是先写入内存,同时同步写入磁盘,等待内存写入成功,就返回结果。而apply是异步写入磁盘。写内存和文件时都加锁。

    https://developer.android.google.cn/guide/topics/manifest/service-element

    经过LocalService和RemoteService实验,得知只要是当前APP开启的进程,数据均存储在data/data/applicationId/shared_prefs目录下。

    Note: This class does not support use across multiple processes.这句话的意思,应该是非同一APP的进程,不能共享数据。

    put/remove ,都是线程级同步操作。

    SharePreferenceImpl类中取数据方法:

        @Override
        @Nullable
        public String getString(String key, @Nullable String defValue) {
            synchronized (mLock) {
                awaitLoadedLocked();
                String v = (String)mMap.get(key);
                return v != null ? v : defValue;
            }
        }

    SharePreferenceImpl.EditorImpl

         @Override
            public Editor putString(String key, @Nullable String value) {
                synchronized (mEditorLock) {
                    mModified.put(key, value);
                    return this;
                }
            }

    https://developer.android.google.cn/reference/android/content/SharedPreferences

    MMKV对比SharePreference,前者使用ProtoBuffer协议、增量更新,后者使用XML协议、全量更新

    SharePreference使用优化:如果同一时间需要存储很多数据,可以最后再apply,避免多余的任务;常用和不常用的数据,分开保存,避免不必要的IO处理。

    MMKV:使用MMap做快速存储的组件,适用于需要日志写入系统。

    特点:立马生效,不存在异步的问题。

    写数据机制:key/value不断写在文件的后面(即使有相同的key),取值时从后往前查找,使用最新的值。默认映射内存为4kb,不足时扩充1倍。

    区别于SharePreference每次都要重写文件,多进程时有几率造成数据丢失,而MMKV通过MMap映射到内核空间,使用文件锁的方式,可以解决此问题。

    多进程时,需要解决数据同步的问题,采用文件互斥锁(同时只有一个线程拿到),而非pthead_mutex(Binder死亡通知方案-此通知不能自己处理,A、B进程互相注册对方死亡通知,A一直存在就有一个永久加锁的mutext,无法释放)。在健壮性的条件下,还要考虑锁升降级和递归加锁问题,文件锁不支持,但mutext缺点更明显。

    每个进程自己拥有一个写指针,mmap内存中也有一个写指针,对比两者偏移量,来做同步;使用单调递增的序列号,来判断内存是否已经重整(原指针之前的数据全部失效,需要重新加载);重整后内存不足,才需要申请新的内存。

    递归锁:属于状态锁,没有计数器,一次解锁全部解掉。

    锁升级:共享锁升级到互斥锁,读锁升级到写锁,如果多个进程都要升级,则会出现互相等待的死锁情况。

    因此,加写锁时,需要先加写锁,再释放读锁;解写锁时,同样要先加读锁,再解写锁。

    https://github.com/Tencent/MMKV/wiki/android_ipc

    使用:

    默认明文保存,可加密,可换密钥,可转换为明文。

    默认单进程模式,可设置多进程模式。

    默认存放在FileDir目录下,可更换目录。

    可备份和恢复。

    问题:

    某些设备找不到so库,可以用ReLinker(https://github.com/KeepSafe/ReLinker)来解决。

    https://github.com/Tencent/MMKV/wiki/android_advance_cn

    GitHub - Tencent/MMKV: An efficient, small mobile key-value storage framework developed by WeChat. Works on Android, iOS, macOS, Windows, and POSIX.

    展开全文
  • android 使用MMKV代替SharePreference

    千次阅读 2020-12-01 15:32:43
    对比 支持的数据类型 1,支持以下 Java 语言基础类型: boolean、int、long、float、double、byte[] 2,支持以下 Java 类和容器: String、Set< String >...任何实现了Parcelable的类型 ...
  • SharePreference存储demo

    2015-01-07 18:02:03
    不同于文件的存储方式,SharePreference是使用键值对的方式来存储数据的。也就是说 当保存一条数据的时候,需要给这条数据提供一个对应的键,这样在读取数据的时候就可以 通过键把相应的值取出来。
  • android4.0版本通过sharepreference方式共享数据,跨应用程序 访问其他程序的数据
  • Sharepreference

    2013-05-31 11:21:36
    Sharepreference代码测试
  • Favor A easy way of using Android SharedPreferences. How to use this library Using Gradle ... Using Maven ...2 The FavorAdapter class generates an implementation of the interface. account = new ...
  • Android的sharepreference

    2022-02-07 23:21:22
    //sharepreference清除缓存 //关闭其他Activity finishAll(LoginActivity.class);//这里是广播的方法,到了这个界面就都关闭 //账号登陆 findViewById(R.id.button_login).setOnClickListener(v -> startActivity...
  • sharepreference在android中是以xml类型的文件存储在内存中的 那么读写sp,肯定会进行xml文件的序列化和解析过程 那么频繁的对本地xml文件进行序列化和解析,肯定会导致性能消耗,尤其是在当sp很大的情况下,会严重...
  • 什么这么说呢?因为SharedPreferences的实现是基于单个xml文件实现的,并且,所有持久化数据都是一次性加载到内存,如果数据过大,是不合适采用SharedPreferences存放的。而适用的场景是单进程的原因同样如此,...
  • 2…获取SharePreference对象 //获取SharePreference对象(参数1:文件名,参数2:模式) SharedPreferences share = getSharedPreferences("myshare",MODE_PRIVATE); 3.获取Editor对象 SharedPreferences.Editor edr = ...
  • sharepreference工具类

    2015-01-16 10:36:33
    很好用的工具类,使用sharepreference存储数据,节省程序员开发时间
  • SharePreference 优化建议

    2019-12-19 17:22:17
    1、不要存放大的 key 或 value 在 SharedPreferences 中,否则会一直存储在内存中(Map 容器中)得不到释放,内存使用过高会频繁引发 GC,导致界面丢帧甚至 ANR。 2、不相关的配置选项最好不要放在一起,单个文件越...
  • 什么使用 SP 它的优点是什么? 使用SP 为Android开发者提供了更为便利的存储方式,但是相对的他也是有一些缺点的。 当我们首次创建 SharedPreferences 对象时,会根据文件名将文件下内容一次性加载到 mMap...
  • android2.3以及以下版本的跨应用数据调用,通过sharepreference实现
  • SharePreference存Bean对象

    2020-07-30 11:20:26
    由于只是简单的存个人消息,所以选择了SharePreference。 发现比较少用SharePreference存Bean对象,特此记下。 废话不多说,上代码~ SharePreference封装类 package com.lrx.module_base.utils; import ...
  • SharePreference:作为Android数据持久化的一种,具有一定的便捷性,适合存储一些体积小的数据。 存储数据方式:键值对的方式,类似于Map; 利用SharePreference.Editor对象存储数据; 利用SharePreferences对象读取...
  • SharePreference与File详解

    2011-03-19 16:06:34
    个人对经验的见解,这是我以前初期在测试过程中使用的简单组建测试代码,现在没事,现象对初学者应该是很有用的,希望能多提出宝贵的意见......
  • 什么这么说呢?因为SharedPreferences的实现是基于单个xml文件实现的,并且所有持久化数据都是一次性加载到内存,如果数据过大,是不合适采用SharedPreferences存放的。而适用的场景是单进程的原因同样如此,由于...
  • SharePreference学习

    2017-11-27 15:46:09
    SharePreference提供一些基础的信息存储功能,所有的信息都是按照键值对的形式进行保存,只能保存一些基本数据类型,如字符串,整形,布尔型等.本质上是保存在xml文件中的,保存在\data\data\\shared_prefs\目录下面...
  • 在Android中我们经常需要持久化保存数据,这时可以使用文件,SharePreference,以及SQLite等。如果我想保存一个对象呢?有些人会立马想到用orm框架,但是我可能不想依赖这个框架。实际上如果数据量不大,用...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,232
精华内容 1,692
关键字:

sharepreference是什么