天天看點

SharedPreference程序共享及性能優化

程序共享

條件1.sharedUserId相同

我們知道,Android上的各個APP是使用者分離的,每個APP都有不同的UserId,這種共享資料的方式要求這兩個APP必須是相同的UserId。

在AndroidManifest.xml中的manifest标簽,我們需要設定兩個APP的sharedUserId,如下:

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>
           

條件2 簽名一緻

要用這種方式,兩個APP的簽名也要求一緻,是以比較适用于屬于自己的多個APP之間共享資料。

核心代碼

假設有A和B兩個應用,我們來實作AB之間實時的讀取和寫入userId。

A應用

private SharedPreferences mPreference;
mPreference = getSharedPreferences("userId", MODE_WORLD_WRITEABLE | MODE_WORLD_READABLE| MODE_MULTI_PROCESS);

// 寫入EditText中的值
SharedPreferences.Editor editor = mPreference.edit();
editor.putString("userId", mValueET.getText().toString().trim());
editor.commit();

// 讀取
String userId = mPreference.getString("userId", "000");
mResultTV.setText(userId);
           

B應用

private SharedPreferences mPreferences;
private Context targetAPPContext;

try {
     // 嘗試建立A應用的Context
     targetAPPContext = createPackageContext("com.example.xiechen.sourceapp", CONTEXT_IGNORE_SECURITY);
     // 從A應用中取得配置檔案
     mPreferences = targetAPPContext.getSharedPreferences("userId",
     MODE_WORLD_WRITEABLE | MODE_WORLD_READABLE    |MODE_MULTI_PROCESS);
     } catch (PackageManager.NameNotFoundException e) {
     e.printStackTrace();
     }

// 讀取
String userId = mPreferences.getString("userId", "000");

// 寫入
SharedPreferences.Editor editor = mPreferences.edit();
editor.putString("userId", mWriteET.getText().toString().trim());
editor.commit();
           

注意事項

AB應用需要讀寫的配置檔案名稱必須一樣,如上述代碼中的”userId”,最終生成的檔案名是userId.xml;

為了能實時讀寫,SharedPreferences的MODE必須加 MODE_MULTI_PROCESS,讀和寫模式看具體需求情況。

SharedPreferences本質上也屬于檔案的一種,但是系統對它的讀寫有一定的緩存政策,即在記憶體中會有一份SharedPreferences檔案的緩存,雖然可以用MODE_MULTI_PROCESS實作多程序模式,但是依然不可靠,面對高并發的讀寫通路,而且會有很大幾率丢失資料,是以不是很建議在程序間通信使用它。

性能

SharePreference性能優化,可以做程序同步嗎?

在Android中, SharePreferences是一個輕量級的存儲類,特别适合用于儲存軟體配置參數。使用SharedPreferences儲存資料,其背後是用xml檔案存放資料,檔案

存放在/data/data/ < package name > /shared_prefs目錄下.

之是以說SharedPreference是一種輕量級的存儲方式,是因為它在建立的時候會把整個檔案全部加載進記憶體,如果SharedPreference檔案比較大,會帶來以下問題:

  1. 第一次從sp中擷取值的時候,有可能阻塞主線程,使界面卡頓、掉幀。
  2. 解析sp的時候會産生大量的臨時對象,導緻頻繁GC,引起界面卡頓。
  3. 這些key和value會永遠存在于記憶體之中,占用大量記憶體。

優化建議

  1. 不要存放大的key和value,會引起界面卡、頻繁GC、占用記憶體等等。
  2. 毫不相關的配置項就不要放在在一起,檔案越大讀取越慢。
  3. 讀取頻繁的key和不易變動的key盡量不要放在一起,影響速度,如果整個檔案很小,那麼忽略吧,為了這點性能添加維護成本得不償失。
  4. 不要亂edit和apply,盡量批量修改一次送出,多次apply會阻塞主線程。
  5. 盡量不要存放JSON和HTML,這種場景請直接使用JSON。
  6. SharedPreference無法進行跨程序通信,MODE_MULTI_PROCESS隻是保證了在API 11以前的系統上,如果sp已經被讀取進記憶體,再次擷取這個SharedPreference的時候,如果有這個flag,會重新讀一遍檔案,僅此而已。

參考:https://blog.csdn.net/hwe_xc/article/details/50788591

https://www.cnblogs.com/ldq2016/p/9035666.html

版權聲明:本文為部落客原創文章,轉載請附上博文連結!

繼續閱讀