最近須要寫個Demo,對咱們公司的SDK作測試,因此遇到這麼個問題,記錄一下。java
SDK是運行在額外的進程的Service的,內部對數據庫和SharePreference有操做,咱們想測試的時候,直接修改其數據庫和SharePreference中的值,從而可以很方便的完成一些功能上的測試,結果發現失敗了,緣由居然是:Sharepreference在多進程讀寫的狀況下,不能跨進程同步。android
寫個例子驗證一下:數據庫
首先定義兩個Activity,分別是Activity_A和Activity_B,代碼相似,都是對同一個Sharepreference進行讀寫操做。只是兩個運行在不一樣的進程。app
Activity_A的代碼以下:ide
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文件中配置以下:this
<?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。code
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所作的修改是在這個進程終止時寫入文件仍是在整個應用終止時才寫入。