SharedPreferencesUtils 工具類 及 SharedPreferences apply和commit方法異同

SharedPreferencesUtils

</pre></p><p></p><p><pre name="code" class="java">package com.hhh.android.base.common;

import java.util.Map;

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

/**
 * 此類爲工具類
 * 調用setParam就能保存String, Integer, Boolean, Float, Long類型的參數
 * 調用getParam就能獲取到保存在手機裏面的數據 
 * @author geek_xz
 * @version 1.0
 * @time 2015-8-26 上午9:58:11
 * 
 */
public class SharedPreferencesUtils {
	/** 
     * 保存在手機裏面的文件名 
     */  
    private static final String FILE_NAME = "share_date";  
      
      
    /** 
     * 保存數據的方法,我們需要拿到保存數據的具體類型,然後根據類型調用不同的保存方法 
     * @param context 
     * @param key 
     * @param object  
     */  
    public static void setParam(Context context , String key, Object object){  
          
        String type = object.getClass().getSimpleName();  
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);  
        SharedPreferences.Editor editor = sp.edit();  
          
        if("String".equals(type)){  
            editor.putString(key, (String)object);  
        }  
        else if("Integer".equals(type)){  
            editor.putInt(key, (Integer)object);  
        }  
        else if("Boolean".equals(type)){  
            editor.putBoolean(key, (Boolean)object);  
        }  
        else if("Float".equals(type)){  
            editor.putFloat(key, (Float)object);  
        }  
        else if("Long".equals(type)){  
            editor.putLong(key, (Long)object);  
        }  
          
        SharedPreferencesCompat.apply(editor);
    }  
      
      
    /** 
     * 得到保存數據的方法,我們根據默認值得到保存的數據的具體類型,然後調用相對於的方法獲取值 
     * @param context 
     * @param key 
     * @param defaultObject 
     * @return 
     */  
    public static Object getParam(Context context , String key, Object defaultObject){  
        String type = defaultObject.getClass().getSimpleName();  
        SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE);  
          
        if("String".equals(type)){  
            return sp.getString(key, (String)defaultObject);  
        }  
        else if("Integer".equals(type)){  
            return sp.getInt(key, (Integer)defaultObject);  
        }  
        else if("Boolean".equals(type)){  
            return sp.getBoolean(key, (Boolean)defaultObject);  
        }  
        else if("Float".equals(type)){  
            return sp.getFloat(key, (Float)defaultObject);  
        }  
        else if("Long".equals(type)){  
            return sp.getLong(key, (Long)defaultObject);  
        }  
          
        return null;  
    }  
    
    /**
	 * 移除某個key值已經對應的值
	 * @param context
	 * @param key
	 */
	public static void remove(Context context, String key)
	{
		SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
				Context.MODE_PRIVATE);
		SharedPreferences.Editor editor = sp.edit();
		editor.remove(key);
		SharedPreferencesCompat.apply(editor);
	}

	/**
	 * 清除所有數據
	 * @param context
	 */
	public static void clear(Context context)
	{
		SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
				Context.MODE_PRIVATE);
		SharedPreferences.Editor editor = sp.edit();
		editor.clear();
		SharedPreferencesCompat.apply(editor);
	}

	/**
	 * 查詢某個key是否已經存在
	 * @param context
	 * @param key
	 * @return
	 */
	public static boolean contains(Context context, String key)
	{
		SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
				Context.MODE_PRIVATE);
		return sp.contains(key);
	}

	/**
	 * 返回所有的鍵值對
	 * 
	 * @param context
	 * @return
	 */
	public static Map<String, ?> getAll(Context context)
	{
		SharedPreferences sp = context.getSharedPreferences(FILE_NAME,
				Context.MODE_PRIVATE);
		return sp.getAll();
	}
}



SharedPreferencesCompat

package com.hhh.android.base.common;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import android.content.SharedPreferences;

/**
 * 由於editor.commit方法是同步的,並且我們很多時候的commit操作都是UI線程中,畢竟是IO操作,所以儘可能採用異步操作;
 * 所以我們使用apply進行替代,apply異步的進行寫入
 * 
 * @author geek_xz
 * @version 1.0
 * @time 2015-8-26 上午10:04:06
 * 
 */
public class SharedPreferencesCompat {
	private static final Method sApplyMethod = findApplyMethod();

	/**
	 * 反射查找apply的方法
	 * 
	 * @return
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	private static Method findApplyMethod() {
		try {
			Class clz = SharedPreferences.Editor.class;
			return clz.getMethod("apply");
		} catch (NoSuchMethodException e) {
		}

		return null;
	}

	/**
	 * 如果找到則使用apply執行,否則使用commit
	 * 
	 * @param editor
	 */
	public static void apply(SharedPreferences.Editor editor) {
		try {
			if (sApplyMethod != null) {
				sApplyMethod.invoke(editor);
				return;
			}
		} catch (IllegalArgumentException e) {
		} catch (IllegalAccessException e) {
		} catch (InvocationTargetException e) {
		}
		editor.commit();
	}
}



在android 中存儲數據時經常用SharedPreference, 並且在提交數據時一直用的是Editor的commit方法, 今天無意了看到了系統用了apply,看了方法的介紹, 原來這個方法也是可以提交數據的.

apply方法在官方SDK說明如下:

Commit your preferences changes back from this Editor to the SharedPreferences object it is editing. This atomically performs the requested modifications, replacing whatever is currently in the SharedPreferences.

Note that when two editors are modifying preferences at the same time, the last one to call apply wins.

Unlike commit, which writes its preferences out to persistent storage synchronously, apply commits its changes to the in-memory SharedPreferences immediately but starts an asynchronous commit to disk and you won’t be notified of any failures. If another editor on this SharedPreferences does a regular commit while a apply is still outstanding, the commit will block until all async commits are completed as well as the commit itself.

As SharedPreferences instances are singletons within a process, it’s safe to replace any instance of commit with apply if you were already ignoring the return value.

You don’t need to worry about Android component lifecycles and their interaction with apply() writing to disk. The framework makes sure in-flight disk writes from apply() complete before switching states.

The SharedPreferences.Editor interface isn’t expected to be implemented directly. However, if you previously did implement it and are now getting errors about missing apply(), you can simply call commit from apply().

這兩個方法的區別在於: 
1. apply沒有返回值而commit返回boolean表明修改是否提交成功 
2. apply是將修改數據原子提交到內存, 而後異步真正提交到硬件磁盤, 而commit是同步的提交到硬件磁盤,因此,在多個併發的提交commit的時候,他們會等待正在處理的commit保存到磁盤後在操作,從而降低了效率。而apply只是原子的提交到內容,後面有調用apply的函數的將會直接覆蓋前面的內存數據,這樣從一定程度上提高了很多效率。 
3. apply方法不會提示任何失敗的提示。 
由於在一個進程中,sharedPreference是單實例,一般不會出現併發衝突,如果對提交的結果不關心的話,建議使用apply,當然需要確保提交成功且有後續操作的話,還是需要用commit的。





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章