文档章节

SharePreference的多进程读写问题

tnjin
 tnjin
发布于 2016/10/10 00:18
字数 808
阅读 970
收藏 0

最近需要写个Demo,对我们公司的SDK做测试,所以遇到这么个问题,记录一下。

SDK是运行在额外的进程的Service的,内部对数据库和SharePreference有操作,我们想测试的时候,直接修改其数据库和SharePreference中的值,从而能够很方便的完成一些功能上的测试,结果发现失败了,原因竟然是:Sharepreference在多进程读写的情况下,不能跨进程同步

写个例子验证一下:

首先定义两个Activity,分别是Activity_A和Activity_B,代码类似,都是对同一个Sharepreference进行读写操作。只是两个运行在不同的进程。

Activity_A的代码如下:

package com.tjz.sp.test;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.TextView;

import com.example.tjz.imageswitcher.R;

public class SharePrefTestActivity extends AppCompatActivity {

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

    /**
     * 写入sharepreference
     * @param view
     */
    public void onWriteClick(View view){
        SpUtil.put(this,"按钮A事件写入");
    }
    /**
     * 读入sharepreference,并显示
     * @param view
     */
    public void onReadClick(View view){
        String result =  SpUtil.get(this);
        result = TextUtils.isEmpty(result)?"null":result;
        TextView tv = (TextView) findViewById(R.id.tv_result);
        tv.setText(result);
    }

    public void onStartClick(View view){
        Intent intent = new Intent(this,SharePrefTestBActivity.class);
        startActivity(intent);
    }
}

Activity_B代码如下:

package com.tjz.sp.test;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.View;
import android.widget.TextView;

import com.example.tjz.imageswitcher.R;

public class SharePrefTestBActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_share_pref_test_b);
    }
    /**
     * 写入sharepreference
     * @param view
     */
    public void onWriteClick(View view){
        SpUtil.put(this,"按钮B事件写入");
    }
    /**
     * 读入sharepreference,并显示
     * @param view
     */
    public void onReadClick(View view){
       String result =  SpUtil.get(this);
        result = TextUtils.isEmpty(result)?"null":result;
        TextView tv = (TextView) findViewById(R.id.tv_result);
        tv.setText(result);
    }
}

除了Activity_A多了一个能够启动Activity_B的方法外,二者几乎一样。

Activity_A与B的布局也类似,就不贴代码了 ,直接放个图:

 

Manifest文件中配置如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.tjz.imageswitcher">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
      
        <activity android:name="com.tjz.sp.test.SharePrefTestActivity"
            android:label="SP_A">

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity android:name="com.tjz.sp.test.SharePrefTestBActivity"
            android:label="SP_B"
            android:process=":newprocess">

        </activity>
    </application>

</manifest>

需要注意的是Activity_B配置了process属性为newprocess。

Sharepreference操作工具类:

package com.tjz.sp.test;

import android.content.Context;
import android.content.SharedPreferences;

/**
 * Created by Tjz on 2016/10/9.
 */

public class SpUtil {

    private static final String SP_NAME = "com.tjz.sp";
    private static final String SP_KEY = "key";

    public static void put(Context context, String value){
        SharedPreferences sp =context.getSharedPreferences(SP_NAME,Context.MODE_PRIVATE);
        sp.edit().putString(SP_KEY,value).commit();
    }

    public static String get(Context context){
        SharedPreferences sp =context.getSharedPreferences(SP_NAME,Context.MODE_PRIVATE);
        return sp.getString(SP_KEY,null);
    }
}

然后看图:

程序最开始启动时,Activity_A读取到sharepreference中为null,这没问题,

然后Activity_A向Sharepreference中写入值,并读取,也没问题:

接下来,启动Activity_B,并且读取Sharepreference,结果也正确:

然后Activity_B写入自己的值,并读取,也没问题:

 

接下来就是回到Activity_A中,再读取一次Sharepreference,发现值并没有改变:

强行中止这个应用,再次启动Activity_A,读取Sharepreference,发现值已经改变为当初Activity_B写入的值。

由此可见,每个进程都维护了自己的一份Sharepreference副本,在其运行过程中,与其他进程完全没有关系,只有应用结束时,才会将自己的修改持久化到文件系统中。

以后再讨论,进程对Sharepreference所做的修改是在这个进程终止时写入文件还是在整个应用终止时才写入。

 

 

© 著作权归作者所有

tnjin

tnjin

粉丝 27
博文 36
码字总数 28535
作品 0
海淀
Android工程师
私信 提问
SharedPreferences使用

默认的PreferenceManager.getDefault(context)在多进程同时读写时,容易被清空 很多程序员为了方便,通常使用默认的sharedPref,事实上,其具有一定的局限性,默认的sharedPref仅支持读写模式...

末日__
2015/11/12
57
0
SharePreference原理及跨进程数据共享的问题

SharedPreferences是Android提供的数据持久化的一种手段,适合单进程、小批量的数据存储与访问。为什么这么说呢?因为SharedPreferences的实现是基于单个xml文件实现的,并且,所有持久化数据...

看书的小蜗牛
2017/11/15
0
0
Android ContentProvider支持跨进程数据共享与"互斥、同步"杂谈

在开发中,假如,A、B进程有部分信息需要同步,这个时候怎么处理呢?设想这么一个场景,有个业务复杂的Activity非常占用内存,并引发OOM,所以,想要把这个Activity放到单独进程,以保证OOM...

看书的小蜗牛
2017/11/15
0
0
Android 缓存框架--ASimpleCache

ASimpleCache 是一个为android制定的 轻量级的 开源缓存框架。轻量到只有一个java文件(由十几个类精简而来)。 1、它可以缓存什么东西? 普通的字符串、json、序列化的java对象,和 字节数字...

michaely
2013/07/29
12.6K
1
Android中SharedPreference多进程数据共享出错

SharedPreference作为android五大存储(网络,数据库,文件,SharedPreference,contentProvider)之中最方便使用的一个,从类名上来看就不是一个存储大数据的工具,以key/value成对的形式来存...

Drealin
2014/01/22
5.6K
0

没有更多内容

加载失败,请刷新页面

加载更多

02.日志系统:一条SQL更新语句是如何执行的?

我们还是从一个表的一条更新语句说起,我们创建下面一张表: create table T(ID int primary key, c int); 如果要将ID=2这一行c的值加1,SQL可以这么写: update T set c=c+1 where ID=2; 前...

scgaopan
27分钟前
6
0
【五分钟系列】掌握vscode调试技巧

调试前端js 准备一个前端项目 index.html <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1......

aoping
27分钟前
3
0
PhotoShop 高级应用:USM锐化/S锐化/防抖

、 高反差锐化+混合模式:叠加模式 【将更多的边缘细节添加到图像中】

东方墨天
38分钟前
7
0
Python数据可视化之matplotlib

常用模块导入 import numpy as npimport matplotlibimport matplotlib.mlab as mlabimport matplotlib.pyplot as pltimport matplotlib.font_manager as fmfrom mpl_toolkits.mplot3d i......

松鼠大帝
昨天
5
0
我用Bash编写了一个扫雷游戏

我在编程教学方面不是专家,但当我想更好掌握某一样东西时,会试着找出让自己乐在其中的方法。比方说,当我想在 shell 编程方面更进一步时,我决定用 Bash 编写一个扫雷游戏来加以练习。 我在...

老孟的Linux私房菜
昨天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部