天天看點

第一行代碼之SharedPreferences存儲SharedPreferences存儲

SharedPreferences存儲

要想使用 SharedPreferences 來存儲資料,首先需要擷取到 SharedPreferences 對象。Android 提供了三種方法得到 SharedPreferences 對象:

  • Context 類中的 getSharedPreferences()方法

      此方法接收兩個參數,第一個參數指定 SharedPreferences 檔案的名稱,第二個參數指定操作模式,目前隻有 MODE_PRIVATE 一種模式,和直接傳入 0 效果相同。其他幾種模式已被廢棄。

  • Activity 類中的 getPreferences()方法

      此方法和上面的方法相似,但隻接收一個操作模式參數,使用這個方法時會自動将目前活動的類名作為 SharedPreferences 的檔案名。

  • PreferenceManager 類中的 getDefaultSharedPreferences()方法

      這是一個靜态方法,它接收一個 Context 參數,并自動使用目前應用程式的包名作為字首來命名 SharedPreferences 檔案。

得到了 SharedPreferences 對象之後,分為三步實作向 SharedPreferences 檔案中存儲資料:

  (1)調用 SharedPreferences 對象的 edit()方法來擷取一個 SharedPreferences.Editor 對象。

  (2)向 SharedPreferences.Editor 對象中添加資料,如添加一個布爾型資料使用 putBoolean 方法,添加一個字元串使用 putString()方法,以此類推。

  (3) 調用 apply()方法将添加的資料送出,完成資料存儲。

當然,SharedPreference在送出資料時也可用 Editor 的 commit 方法,兩者差別如下:
  • apply() 沒有傳回值而 commit() 傳回 boolean 表明修改是否送出成功
  • apply() 将修改送出到記憶體,然後再異步送出到磁盤上;而 commit() 是同步送出到磁盤上。** 谷歌建議:若在UI線程中,使用 apply() 減少UI線程的阻塞(寫到磁盤上是耗時操作)引起的卡頓。**

建立一個項目

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <Button
        android:id="@+id/save_data"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="儲存資料" />

</LinearLayout>
           

放一個按鈕,将一些資料存儲到SharedPreferences 檔案當中。然後修改 Activity 中的代碼

public class SharePreferencesActivity extends AppCompatActivity {

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

        Button save_data = (Button) findViewById(R.id.save_data);
        save_data.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // 1.指定檔案名為 wonderful,并得到 SharedPreferences.Editor 對象
                SharedPreferences.Editor editor = getSharedPreferences("wonderful",MODE_PRIVATE).edit();
                // 2.添加資料
                editor.putString("name","開心wonderful");
                editor.putInt("age",20);
                editor.putBoolean("married",false);
                // 3.資料送出
                editor.apply();
            }
        });
    }
}
           

點選按鈕後,這時資料已儲存成功了,生成了一個 wonderful.xml 檔案

SharedPreferences 檔案是使用 XML 格式來對資料進行管理的

6.2.2 從 SharedPreferences 中讀取資料

SharedPreferences 對象中提供了一系列的 get 方法用于對存儲的資料進行讀取

每種 get 方法都對應了 SharedPreferences. Editor 中的一種 put 方法

這些 get 方法接收兩個參數,第一個參數是鍵,即傳入存儲資料時使用的鍵;第二個參數是預設值

即當傳入的鍵找不到對應的值時,傳回預設值

修改上面項目中的布局代碼:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"  >

    <Button
        android:id="@+id/save_data"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="儲存資料" />

    <Button
        android:id="@+id/restore_data"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="讀取資料" />
    
    <TextView
        android:id="@+id/show_data"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>
           

增加了一個還原資料的按鈕和 TextView,點選按鈕來從 SharedPreferences 檔案中讀取資料并在 TextView 中顯示讀取的資料

修改 Activity 中的代碼:

public class SharePreferencesActivity extends AppCompatActivity {
    
    private Button save_data,restore_data;
    
    private TextView textView;

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

        save_data = (Button) findViewById(R.id.save_data);
        save_data.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // 1.指定檔案名為 wonderful,并得到 SharedPreferences.Editor 對象
                SharedPreferences.Editor editor = getSharedPreferences("wonderful",MODE_PRIVATE).edit();
                // 2.添加不同類型的資料
                editor.putString("name","開心wonderful");
                editor.putInt("age",20);
                editor.putBoolean("married",false);
                // 3.資料送出
                editor.apply();
            }
        });

        textView = (TextView) findViewById(R.id.show_data);
        restore_data = (Button) findViewById(R.id.restore_data);
        restore_data.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // 獲得 SharedPreferences 對象
                SharedPreferences pref = getSharedPreferences("wonderful",MODE_PRIVATE);
                // 擷取相應的值
                String name = pref.getString("name","");
                int age = pref.getInt("age",0);
                boolean married = pref.getBoolean("married",false);
                // 将擷取到的值顯示
                textView.setText("name is " + name + ",age is "+ age + ",married is "+ married);
            }
        });
    }
}
           

重新運作一下程式,并點選界面上的 讀取資料 按鈕,然後檢視 TextView中顯示的資訊:

第一行代碼之SharedPreferences存儲SharedPreferences存儲

6.2.3 實作記住密碼功能

會用上一章廣播的強制下線的例子

修改項目前,先來簡單封裝下關于 SharedPreferences 的工具類,如下:

public class PrefUtils {

    private static final String PREF_NAME = "config";

    /**
     * 讀取布爾資料
     * @param ctx 上下文
     * @param key 鍵
     * @param defaultValue 預設值
     * @return
     */
    public static boolean getBoolean(Context ctx, String key,
                                     boolean defaultValue) {
        SharedPreferences sp = ctx.getSharedPreferences(PREF_NAME,
                Context.MODE_PRIVATE);
        return sp.getBoolean(key, defaultValue);
    }

    /**
     * 添加布爾資料
     * @param ctx 上下文
     * @param key 鍵
     * @param value 添加的資料
     */
    public static void setBoolean(Context ctx, String key, boolean value) {
        SharedPreferences sp = ctx.getSharedPreferences(PREF_NAME,
                Context.MODE_PRIVATE);
        sp.edit().putBoolean(key, value).apply();
    }

    /**
     * 讀取字元串
     * @param ctx
     * @param key
     * @param defaultValue
     * @return
     */
    public static String getString(Context ctx, String key, String defaultValue) {
        SharedPreferences sp = ctx.getSharedPreferences(PREF_NAME,
                Context.MODE_PRIVATE);
        return sp.getString(key, defaultValue);
    }

    /**
     * 添加字元串
     * @param ctx
     * @param key
     * @param value
     */
    public static void setString(Context ctx, String key, String value) {
        SharedPreferences sp = ctx.getSharedPreferences(PREF_NAME,
                Context.MODE_PRIVATE);
        sp.edit().putString(key, value).apply();
    }

    /**
     * 讀取int類型資料
     * @param ctx
     * @param key
     * @param defaultValue
     * @return
     */
    public static int getInt(Context ctx, String key, int defaultValue) {
        SharedPreferences sp = ctx.getSharedPreferences(PREF_NAME,
                Context.MODE_PRIVATE);
        return sp.getInt(key, defaultValue);
    }

    /**
     * 添加int類型資料
     * @param ctx
     * @param key
     * @param value
     */
    public static void setInt(Context ctx, String key, int value){
        SharedPreferences sp = ctx.getSharedPreferences(PREF_NAME,
                Context.MODE_PRIVATE);
        sp.edit().putInt(key, value).apply();
    }

    /**
     * 将資料全部清除掉
     * @param ctx
     */
    public static void clear(Context ctx){
        SharedPreferences sp = ctx.getSharedPreferences(PREF_NAME,
                Context.MODE_PRIVATE);
        sp.edit().clear().apply();
    }
}
           

編輯下登入界面,修改 activity_login.xml 中的代碼:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <!--***************** 賬号 *********************-->
    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="60dp">
        <TextView
            android:layout_width="90dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:gravity="center"
            android:textSize="18sp"
            android:text="賬号:"/>

        <EditText
            android:id="@+id/et_account"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:layout_gravity="center_vertical"/>
    </LinearLayout>

    <!--***************** 密碼 *********************-->
    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="60dp">
        <TextView
            android:layout_width="90dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:gravity="center"
            android:textSize="18sp"
            android:text="密碼:"/>

        <EditText
            android:id="@+id/et_password"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:layout_gravity="center_vertical"
            android:inputType="textPassword"/>
    </LinearLayout>

    <!--***************** 是否記住密碼 *********************-->
    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <CheckBox
            android:id="@+id/cb_remember_pass"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="18sp"
            android:layout_gravity="center_vertical"
            android:text="記住密碼"/>

    </LinearLayout>

    <Button
        android:id="@+id/btn_login"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:layout_margin="10dp"
        android:text="登入"/>

</LinearLayout>
           

添加了個 CheckBox 來勾選記住密碼,接着修改 LoginActivity 的代碼:

public class LoginActivity extends BaseActivity {

    private EditText et_account, et_password;
    private CheckBox cb_remember_pass;
    private Button btn_login;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        et_account = (EditText) findViewById(R.id.et_account);
        et_password = (EditText) findViewById(R.id.et_password);
        cb_remember_pass = (CheckBox) findViewById(R.id.cb_remember_pass);
        btn_login = (Button) findViewById(R.id.btn_login);
        
        Boolean isRemember = PrefUtils.getBoolean(this,"remember_pass",false);
        if (isRemember){
            // 将賬号和密碼都設定到文本框中
            String account = PrefUtils.getString(this,"account","");
            String password = PrefUtils.getString(this,"password","");
            et_account.setText(account);
            et_password.setText(password);
            cb_remember_pass.setChecked(true);
        }

        btn_login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String account = et_account.getText().toString();
                String password = et_password.getText().toString();
                // 若賬号是 wonderful 且密碼是 123456,就認為登入成功
                if (account.equals("wonderful") && password.equals("123456")){
                    // 檢查複選框是否被勾選
                    if (cb_remember_pass.isChecked()){
                        // 儲存資料到SharePreference檔案中
                        PrefUtils.setBoolean(LoginActivity.this,"remember_pass",true);
                        PrefUtils.setString(LoginActivity.this,"account",account);
                        PrefUtils.setString(LoginActivity.this,"password",password);
                    }else {
                        // 清除SharePreference檔案中的資料
                        PrefUtils.clear(LoginActivity.this);
                    }
                    // 登入成功跳轉到主界面
                    IntentUtils.myIntent(LoginActivity.this,ForceOfflineActivity.class);
                    finish();
                }else {
                    ToastUtils.showShort("賬号或密碼無效!");
                }
            }
        });

    }

    @Override
    protected int initLayoutId() {
        return R.layout.activity_login;
    }
}
           

現在運作下程式,輸入賬号和密碼并選中記住密碼複選框後,點選登入,就會跳轉到 ForceOfflineActivity

接着在 ForceOfflineActivity 中發出一條強制下線廣播會讓程式重新回到登入界面

此時你會發現,賬号密碼都已經自動填充到界面上