Android 数据存储:SharedPreferences(SP)

android开发过程中的小问题——使用SPUtils工具类获取数据为null值问题 使用SPUtils工具类获取数据为null值问题(SharedPreference) 开发过程中使用SPUtils工具类,有时获取数据正常,有时获取数据为null值的问题,回去查看保存在虚拟机中的sp表单,发现数据都正常。 然后网上搜索各种博客、各种解决方案,却还是没有解决问题,比如: 每次调用 editor 的 put 函数存放对应数据类型数据时,都需要 apply() 或 commit() ... 阅读详情
AI摘要

本文详细介绍了Android中SharedPreferences的使用方法及注意事项,包括数据存储、读取、更新等操作,并提供了一个实用的SPUtils工具类。

作为 Android 的数据存储方式之一的 SharedPreferences(以下简称SP),我们在开发中也是或多或少会用到。今天就来总结一下如何使用 SP 以及使用 SP 的注意事项。

1.首先先聊聊使用 SP 的注意事项

  • SP 适合存储一些轻量级的持久化数据,如果你的数据量很大,那么建议你更换存储方式。
  • SP 提供了数据的一致性,但这是以牺牲程序性能为代价的,所以如果存储的数据需要经常修改,那么建议你更换存储方式。
  • SP 是不支持多进程读写的,如果你需要多进程对数据进行读写访问,那么建议你更换存储方式。
  • SP 的 commit 方法是同步进行的,apply 是异步进行的,两者都是以替换上次数据来进行数据更新的,如果同时有两个地方调用 commit 或者 apply ,以最后一次调用为最终数据更新。
  • 如果你不关心 SP 的操作返回值,同时你还是在 Android 主线程进行操作,那么建议你使用 apply 方法进行数据更新。
  • 因为 SP 的 apply 方法会异步进行数据更新,那么在 apply 方法尚未完成的时候,调用 commit 方法进行数据更新,就会使 commit 方法进行阻塞,直到 apply 方法完成所有的异步数据更新。

2. 好的,接下来我们就来看看 SP 的具体使用

  • SP 使应用程序共享它的同一个实例,通过 XML 以 key-value 的形式保存数据。
  • SP 主要用来保存一些轻量级的数据(字符串、基本数据类型),比如应用程序的各种配置信息,以及一些简单的账号、密码等。
  • SP 的数据文件储存位置:data/data/应用程序包名/shared_prefs/
  • SP 的数据访问模式
MODE_PRIVATR默认模式,创建保存的文件只能本应用程序或者拥有相同用户ID的应用程序访问
MODE_WORLD_READABLE允许所有应用程序对创建的文件进行读操作权限(官方不建议使用,数据不安全)
MODE_WORLD_WRITEABLE允许所有应用程序对创建的文件进行写操作权限(官方不建议使用,数据不安全)
  • SP的方法
adstract  boolean

contains(String key)

检查SP文件是否包含此 key。

adstract  SharedPreferences.Editor

edit()

创建一个SP文件编辑器,通过这个编辑器可以编辑SP里面的内容,并将这些修改提交给SP。

adstract Map<String,?>

getAll()

从SP中查询出所有的 key-value。

adstract  boolean

getBoolean(String key,boolean defValue)

根据 key 从 SP 中查询对应的 boolean 值,如果查不到就返回默认值。

adstract  float

getFloat(String key,float defValue)

根据 key 从 SP 中查询对应的 float 值,如果查不到就返回默认值。

adstract  int

getInt(String key,int defValue)

根据 key 从 SP 中查询对应的 int 值,如果查不到就返回默认值。

adstract  long

getLong(String key,long defValue)

根据 key 从 SP 中查询对应的 long 值,如果查不到就返回默认值。

adstract  String

getString(String key,String defValue)

根据 key 从 SP 中查询对应的 String 值,如果查不到就返回默认值。

adstract  Set<String>

getStringSet(String key,Set<String> defValue)

根据 key 从 SP 中查询对应的一组 String 值,如果查不到就返回默认值。

adstract  void

registerOnSharedPreferencesChangeListener(SharedPreferences.OnSharedPreferencesChangeListener

  listener )

注册SP发生改变的监听回调

adstract  void

unregisterOnSharedPreferencesChangeListener(SharedPreferences.OnSharedPreferencesChangeListener

  listener )

取消SP发生改变的监听回调

  • SharedPreferences.Editor 接口的方法
adstract  void

apply()

将SP的修改返回给当前正在被编辑的SP。(异步提交,不保证数据完整性,如果你在apply() 未完成前调用commit(),则会造成commit()阻塞,直到apply()执行完成,才会执行commit(),如果你不在乎返回值的话,可以将 commit() 替换成 apply()。)

adstract  SharedPreferences.Editor

clear()

清空SP中的所有数据。

adstract  boolean

commit()

将SP的修改返回给当前正在被编辑的SP。(同步提交)

如果您不关心返回值并且正在从应用程序的主线程中使用它,请考虑使用apply()。

adstract  SharedPreferences.Editor

PutBoolean(String key,boolean value)

在SP编辑器中设置一个布尔值,一旦调用commit()或apply(),就会被写入。

adstract  SharedPreferences.Editor

PutFloat(String key,float value)

在SP编辑器中设置一个float值,一旦调用commit()或apply(),就会被写入。

adstract  SharedPreferences.Editor

PutInt(String key,int value)

在SP编辑器中设置一个int值,一旦调用commit()或apply(),就会被写入。

adstract  SharedPreferences.Editor

PutLong(String key,long value)

在SP编辑器中设置一个long值,一旦调用commit()或apply(),就会被写入。

adstract  SharedPreferences.Editor

PutString(String key,String value)

在SP编辑器中设置一个String值,一旦调用commit()或apply(),就会被写入。

adstract  SharedPreferences.Editor

PutStringSet(String key,Set<String> value)

在SP编辑器中设置一组String值,一旦调用commit()或apply(),就会被写入。

adstract  SharedPreferences.Editor

remove(String key)

根据key,删除SP中的值。

至此SP的功能已经介绍完了。

我们接下来就看看具体的用法以及自己实现一个SPUtils。

  • 我们先动手封装一个SPUtils,这样大大减少了很多的模板代码,你也可以根据自己的业务自定义封装,以下是我封装的。
import android.content.Context;
import android.content.SharedPreferences;

import java.util.Map;

public class SPUtils {

    private final static String spName = "Test";

    public static void putValue(Context context, String key, Object value) {
        SharedPreferences sp = context.getSharedPreferences(spName, Context.MODE_PRIVATE);
        SharedPreferences.Editor edit = sp.edit();
        if (value instanceof Boolean) {
            edit.putBoolean(key, (Boolean) value);
        } else if (value instanceof Float) {
            edit.putFloat(key, (Float) value);
        } else if (value instanceof Integer) {
            edit.putInt(key, (Integer) value);
        } else if (value instanceof Long) {
            edit.putLong(key, (Long) value);
        } else if (value instanceof String) {
            edit.putString(key, (String) value);
        }
        edit.apply();
    }

    public static Object getValue(Context context, String key, Object defValue) {
        SharedPreferences sp = context.getSharedPreferences(spName, Context.MODE_PRIVATE);
        if (defValue instanceof Boolean) {
            return sp.getBoolean(key, (Boolean) defValue);
        } else if (defValue instanceof Float) {
            return sp.getFloat(key, (Float) defValue);
        } else if (defValue instanceof Integer) {
            return sp.getInt(key, (Integer) defValue);
        } else if (defValue instanceof Long) {
            return sp.getLong(key, (Long) defValue);
        } else if (defValue instanceof String) {
            return sp.getString(key, (String) defValue);
        }
        return null;
    }

    public static void clearSP(Context context) {
        context.getSharedPreferences(spName, Context.MODE_PRIVATE)
                .edit()
                .clear()
                .apply();
    }

    public static void removeSP(Context context, String Key) {
        context.getSharedPreferences(spName, Context.MODE_PRIVATE)
                .edit()
                .remove(Key)
                .apply();
    }
    
    public static Map<String, ?> getAllSP(Context context) {
        return context.getSharedPreferences(spName, Context.MODE_PRIVATE).getAll();
    }

}
  • 我们现在模拟登录页面保存账号密码的功能。我创建了两个button,一个用来存储账号密码,一个用来读取账号密码并且进行删除和清空操作。具体如下:
public class MainActivity extends AppCompatActivity {

    public static final String SP_USERNAME_KEY = "SP_USERNAME_KEY";
    public static final String SP_PASSWORD_KEY = "SP_PASSWORD_KEY";
    public static final String TAG = "Main_Activity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        findViewById(R.id.btn_put).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SPUtils.putValue(MainActivity.this, SP_USERNAME_KEY, "哈哈");
                SPUtils.putValue(MainActivity.this, SP_PASSWORD_KEY, 123456);
            }
        });

        findViewById(R.id.btn_get).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                //1.首次正常获取
                Map<String, ?> allSP = SPUtils.getAllSP(MainActivity.this);
                int size = allSP.size();
                Log.d(TAG, "1.getAllSP.size() --> " + size);

                String username = (String) SPUtils.getValue(MainActivity.this, SP_USERNAME_KEY, "");
                int password = (int) SPUtils.getValue(MainActivity.this, SP_PASSWORD_KEY, -1);
                Log.d(TAG, "1.username --> " + username + " ,1.password --> " + password);

                //2.删除 SP_USERNAME_KEY 后,打印sp数量,以及数据情况
                SPUtils.removeSP(MainActivity.this, SP_USERNAME_KEY);

                Map<String, ?> allSP2 = SPUtils.getAllSP(MainActivity.this);
                int size2 = allSP2.size();
                Log.d(TAG, "2.getAllSP.size() --> " + size2);

                String username2 = (String) SPUtils.getValue(MainActivity.this, SP_USERNAME_KEY, "");
                int password2 = (int) SPUtils.getValue(MainActivity.this, SP_PASSWORD_KEY, -1);
                Log.d(TAG, "2.username --> " + username2 + " ,2.password --> " + password2);

                //清空sp后,打印sp数量,以及数据情况
                SPUtils.clearSP(MainActivity.this);

                Map<String, ?> allSP3 = SPUtils.getAllSP(MainActivity.this);
                int size3 = allSP3.size();
                Log.d(TAG, "3.getAllSP.size() --> " + size3);

                String username3 = (String) SPUtils.getValue(MainActivity.this, SP_USERNAME_KEY, "");
                int password3 = (int) SPUtils.getValue(MainActivity.this, SP_PASSWORD_KEY, -1);
                Log.d(TAG, "3.username --> " + username3 + " ,3.password --> " + password3);

            }
        });
    }
}
  • 此为Log输出信息:
D/Main_Activity: 1.getAllSP.size() --> 2
D/Main_Activity: 1.username --> 哈哈 ,1.password --> 123456
D/Main_Activity: 2.getAllSP.size() --> 1
D/Main_Activity: 2.username -->  ,2.password --> 123456
D/Main_Activity: 3.getAllSP.size() --> 0
D/Main_Activity: 3.username -->  ,3.password --> -1

至此SP的介绍以及使用就完毕了,希望对你有帮助。

欢迎加入Q群一起探讨Android问题。

 

Android dp sp 的区别 因此通常情况下,我们还是建议使用sp作为字体的单位,除非一些特殊的情况,不想跟随系统字体变化的,可以使用dp。由此可以看出使用sp作为字体大小单位,会随着系统的字体大小改变,而dp作为单位则不会。而 dp 也叫 dip,是 device independent pixels。 阅读详情

相关推荐

通过AndroidStudio找到数据库文件

1、 2、在右方出现的列表中找data文件夹下的data文件夹 3、然后找到相应的包名,包名下方就有数据库文件.db文件 注意:如果数据库文件没有.db作为后缀,那么直接重命名添加即可 4、然后右键将其保存在桌面 5、然后可以通过Navicat 创建一个新的连接,选择 SQLite , 6、然后输入连接名称(自定义),然后选择db文件,然后测试连接,如果连接成功,就可以点击确定 7、效果图: ...

郭宝的博客 1万+

Android 数据存储、SP的简单使用

数据保存分类(目前主流):SP、SQLite、Room 1 SP:sharedPreference首选项 很小,简单的数据可以保存在SP window 的.ini文件,android 的.xml文件(存储格式是key-value) 存储软件的配置信息(比如自动登录,记住密码,主题记录,书看到69页记住): 不能存太多的信息,因为当程序运行首选项里的数据会全部加载进内容 把数据保存到app本身......

m0_45877477的博客 4042

数据存储之——SharedPreferences不要再误用了!(Android Q)

SharedPreferences(简称sp)Android平台上一个轻量级的存储辅助类,它提供了key-value键值对的接口,用来保存应用的一些常用配置,在应用中通常做一些简单数据的持久化缓存。本文将详细的分析SharedPreferences的实现方式、存储机制、如何正确使用它以及sp的性能问题等方面。 SharedPreferences实现详解 我们在Android开发中,如果想要保存一个相对较小的键值对集合,则应使用SharedPreferences API。SharedPreferences对

卜大爷的博客 6万+

Android本地数据存储(SP、SQLite、Room)

Android本地数据存储常用的有三种方式 1、SP存储,key-value的方式存储在本地的xml文件中,/data/data/xxx.xx/shared_prefs/xxx.xml 2、sqlite存储 3、room存储。

不积跬步无以至千里,不积小流无以成江海。一个喜欢学习分享的程序员 6478

腾讯初级Android面经:四大组件、SharedPreferences的坑、权限模型,鹅厂基础题有多细

摘要:腾讯Android面试与字节风格差异显著,更注重基础广度和扎实性。本文解析7道腾讯初级高频题:1)Activity启动模式场景应用;2)Service两种启动方式组合使用;3)广播注册限制与有序广播机制;4)SharedPreferences性能优化方案;5)运行时权限处理要点;6)五种数据存储方案选型;7)RecyclerView相比ListView的四大优势。面试强调知识面覆盖+项目细节,需掌握腾讯自研的MMKV,算法要求LeetCode Medium难度。

郑伟强dev的专栏 21

避坑指南:Livox Mid-360双雷达SLAM配置中,那些官方文档没说的细节(IP设置、话题分离与时间同步)

本文详细解析了Livox Mid-360双雷达SLAM配置中的关键优化点,包括IP设置、话题分离与时间同步等官方文档未提及的细节。通过实战案例和代码示例,帮助开发者解决点云错位、IMU数据混乱等问题,提升SLAM系统的稳定性和精度。特别针对网络架构设计、驱动修改和时间同步机制提供了专业指导。

weixin_29745609的博客 425

在Android开发中,如何使用SharedPreferences(简称SP)一个轻量级的数据存储方式

在Android开发中,(简称SP)是一个轻量级的数据存储方式,常用于保存应用的配置信息或少量的数据。为了便于在全局使用,可以将其封装到一个工具类中。以下是一个带有详细中文注释的全局。

LLZjiayou的博客 1023

MATLAB实现灰雁优化算法(GGO):从原理到实战的详细级教程

灰雁优化算法(GGO)是一种新型群体智能算法,模拟灰雁迁徙和觅食行为。算法通过领导更替机制、V形编队飞行和群体觅食策略,平衡全局探索与局部开发能力,具有收敛精度高、避免局部最优等特点。在MATLAB环境中,算法实现包括初始化种群、迭代更新领导雁、执行编队飞行和觅食行为等核心模块。用户可根据问题维度设置参数,通过收敛曲线和可视化分析评估性能。关键参数如领导更替频率、V形编队强度和觅食强度需根据问题复杂度调整,以获得最佳优化效果。该算法适用于各类优化问题,具有较好的鲁棒性和稳定性。

fx666_的博客 1212

android 清空sp,Android SP的具体内容

username = findViewById(R.id.username); 输入账户的password= findViewById(R.id.password); 输入密码的CheckBox checkBox=findViewById(R.id.remember); 复选框Button log_in=findViewById(R.id.login);  登录按钮Button registe...

weixin_39589394的博客 1150

Matlab实战:用Transformer+LSTM+SVM搞定股票价格预测(附完整代码)

本文介绍了一种基于Transformer、LSTM和SVM的混合建模方法,用于股票价格预测。该方法结合了Transformer的全局依赖捕捉能力、LSTM的时序特征提取优势以及SVM的非线性回归能力,有效应对金融时间序列的非平稳性和噪声问题。文章提供了完整的Matlab实现代码,并展示了混合模型在实盘测试中的优异表现,方向预测准确率达62%,最大回撤控制在3.2%以内。

milk8的博客 254

【ELF2学习板】基于OpenMP与RK3588多核架构优化FFTW的并行计算效率

本文详细介绍了如何在ELF2学习板上利用OpenMP与RK3588多核架构优化FFTW的并行计算效率。通过编译支持OpenMP的FFTW库、合理设置线程绑定与调度策略,以及内存访问优化等技巧,显著提升了FFT计算的性能。实测数据显示,多核并行优化可使4096点FFT计算速度提升一倍以上,特别适合信号处理、图像分析等高性能计算场景。

weixin_30352645的博客 604

Android SharedPreferences转为MMKV

由图片可以看出MMKV相比SP的优势还是比较大的,除了需要引入库,有一些修改上的成本以外,就没有什么能够阻挡MMKV了。当然了,MMKV也有着不广为人知的缺点,放在最后。 MMKV还直接支持了将SharedPreferences的历史数据转换为MMKV进行存储,只不过需要注意一点,不可回退。

quanzhan_King的博客 1734

《软件工程——实践者的研究方法》重难点复习笔记(第八章——理解需求)

8项需求工程任务 inception 开始 8.1.1 identify stakeholders 定义:从软件开发中收益 例如:市场人员、销售经理、顾客、顾问、维护团队等(P139) 8.1.2 这个阶段的问题是context-free的。有三套(P140) 8.1.3 提到NFR(nonfunctional requirement)和QFD(quality

whooiif的博客 1814

Android开发sp存储

我整理的一些关于【Java】的项目学习资料(附讲解~~)和大家一起分享、学习一下:https://d.51cto.com/bLN8S1Android开发中的SP存储教程 在Android开发中,SharedPreferences(简称SP)是一种轻量级的数据存储方式,通常用于保存简单的数据,例如用户的设置或小块信息。本文...

weixin_34820751的博客 415

WD西部数据2TB,2.5寸移动硬盘,因为磁头坏了,长时间通电导致划片划伤,维修过程通过反复更换磁头

WD西部数据2TB,2.5寸移动硬盘,因为磁头坏了,长时间通电导致划片划伤,维修过程通过反复更换磁头,才能利用专业设备,里面找到,镜像,把内容数据恢复出来。 1.说一下经历,借用的别人移动硬盘,去帮别人维修,拷数据出来,别人的文件,数据比较多,且复杂,而且是在PE系统,接口什么的是2.0,没有很好的思考就全选复制拷贝了; 2,拷贝的过程,极其慢,文件多,且文件有损坏,移动硬盘一直处于通电的状态,大概从下午,两点多开始100多G的数据,一直卡住,到,晚上7 。8点拷完还是没拷完。打开的时候就已经,就一直

weixin_43766920的博客 4301

金蝶云星空v8.0私有化部署与cpolar内网穿透:构建企业级远程ERP访问通道

本文详细介绍了金蝶云星空v8.0企业版的私有化部署流程与cpolar内网穿透技术,帮助企业构建安全高效的远程ERP访问通道。从系统环境准备、SQL Server配置到内网穿透安全加固,提供全流程实战指导,助力企业实现本地部署与远程办公的无缝衔接。

weixin_28736335的博客 376

SharedPreferences和File<一>

一,SharedPreferences: (1)简称:SP存储 (2)位置:用它时,将会默认在data/data/包名/下创建一个名字为:shared_prefs的文件夹,    然后再在shared_prefs目录下创建你命名的文件. (3)创建步骤: 获取上下文的SharedPreferences对象 调用刚刚获取的SharedPreferences对象的editor()方法,返回

小样 784

一.镜头知识之焦点,焦距,有效焦距,前焦距,后焦距

由光学系统中镜片的最后一面到像面的距离。

AIoT深度探索者 | 嵌入式系统架构师 深耕物联网(IoT)与人工智能(AI)融合技术,聚焦​​边缘计算、图像开发、低功耗通信协议​​,致力于智能硬件,关注我获取最新技术文章信息与海量资源~ 5576

详解DataStore,SharedPreferences终结者

小马快跑的博客地址:https://blog.youkuaiyun.com/u013700502DataStore介绍Jetpack DataStore 是一种改进的新数据存储解决方案,允许使用协议缓...

Android技术之家 867

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

android sp文件一个键值保存多条信息

之前碰到过这样的问题,sp文件只能够append,或者清空。其实一个键值,通过,分割,或者替代可以实现多条信息的存储。下面是一个举例: package com.ctbri.weather.utils; import android.content.SharedPreferences; public class StringUtil { public static Str...

weixin_30892889的博客 284

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Sp使用

package com.example.sp; import android.content.Context; import android.content.SharedPreferences; public class Sp { public static void set(Context context,String key,int id){ SharedPr

195

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Android-SharedPreferences

简称Sp,是一种轻量级的数据存储方式,采用key/value的方式进行映射,最终会在手机的/data/data/package_name/shared_prefs/目录下以xml的格式存在。Sp通常用于记录一些参数配置、行为标记等。但是不要使用Sp去存储大的数据和文件,否则会大大影响应用性能,甚至出现ANR(Application Not Response)。 获取Sp的方式 1、调用Cont...

金溪的博客 257

移动应用开发-Android数据存储

本文系统介绍了Android开发中四种核心数据存储方案:1)XML解析(SAX/DOM/PULL三种方式对比及SD卡存储实践);2)JSON处理(原生API与FastJSON库应用,含网络权限配置);3)SharedPreferences轻量级存储(配置参数保存与多进程注意事项);4)SQLite数据库(CRUD操作与事务管理)。针对不同场景给出技术选型建议:轻量配置用SharedPreferences、跨平台传输选JSON、复杂数据用SQLite,并强调数据安全与性能优化要点,提供配套实践案例帮助开发者快

m0_73873908的博客 777

SharedPreferences 存储流程

1 sp的读取 sp 以 map形式,在读取时,一次性,整体进入内存. 所以 存时会出现两个步骤,更新内存中的值,更新文件中的值. 2 sp的清除 sp在使用中,如果只删除文件, 那么由于内存中存在map缓存,在更新sp时,源文件中的值依然会被恢复 正确的清除sp的方法是 sp.edit().clear().commit()//删除内存中的数据 context.deleteSharedPreferences()//删除sp文件 sp无法跨进程 由于读取时,会有内存缓存.在跨进程过程中,并没有通知另一个进.

xianrenli38的博客 534

Android 文件与数据存储实战:SharedPreferences、SQLite 与 Room 的渐进式实现

SharedPreferences、SQLite 与 Room 的 Android 数据库增删改查

OuO-1 的博客 1084

android 数据存储之SharePreference 的几种方式

1. 常见的 getSharedPreferences(String filename,mode) 指定sp文件的名称,生成的文件名为 filename.xml 2.getPreferences(mode) getPreferences只有一个参数,不能指定文件名,文件名固定为 当前Activity的名字,不包含包名。 3.PreferenceManager.getDefaultSha...

weixin_34248849的博客 182
上一篇: Android Studio 使用Git创建本地分支和远程分支以及合并
下一篇: Android Studio 提交代码出现:Push failed: Failed with error: fatal: unable to access 错误
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值