Android 输入和共享偏好设置






4.64/5 (9投票s)
学习如何在 Android 中处理不同的输入类型并将输入数据存储到共享偏好设置存储中。
引言
每个应用程序都涉及数据。大多数数据由用户通过各种输入控件提供,例如文本字段、复选框、单选组、下拉列表和按钮。虽然有些数据是暂时的,但大多数数据在应用程序停止运行后仍需要保留或持久化。Android 提供了许多巧妙的技术来本地存储持久化数据。
在本文中,您将首先学习如何实现和处理文本字段、复选框、单选组、下拉列表和按钮的输入控件。然后,您将学习如何使用共享偏好设置来存储和检索数据。
准备工作
在您喜欢的 Android IDE 中,启动一个新的 Android 应用项目。我们将其应用程序名称设置为“AndroidInputNStorage”,域名设置为“peterleowblog.com”。您的项目的最终包名将是“com.peterleowblog.androidinputnstorage”。
在项目的“res”文件夹中,用以下将在项目中使用的字符串资源替换“strings.xml”的内容。
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Android Input and Storage</string> <string name="action_settings">Settings</string> <string name="shared_preferences">Shared Preferences</string> <string name="email">Email</string> <string name="gender">Gender</string> <string name="female">Female</string> <string name="male">Male</string> <string name="hobbies">Hobbies</string> <string name="coding">Coding</string> <string name="writing">Writing</string> <string name="jogging">Jogging</string> <string name="zodiac">Zodiac</string> <string name="save_me">Save Me</string> <string name="retrieve">Get Me</string> <string-array name="zodiac"> <item>Aries</item> <item>Taurus</item> <item>Gemini</item> <item>Cancer</item> <item>Leo</item> <item>Virgo</item> <item>Libra</item> <item>Scorpio</item> <item>Sagittarius</item> <item>Capricorn</item> <item>Aquarius</item> <item>Pisces</item> </string-array> </resources>
处理输入
创建一个名为“SharedPreferencesActivity”的新 Activity,其布局文件为“activity_shared_preferences.xml”。用以下 XML 代码替换“activity_shared_preferences.xml”中的内容:
<?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingLeft="16dp" android:paddingRight="16dp" android:paddingTop="16dp" android:paddingBottom="16dp"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:text="@string/shared_preferences" android:id="@+id/textView" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" /> <EditText android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="textEmailAddress" android:ems="10" android:id="@+id/txtEmail" android:layout_below="@+id/textView4" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" android:text="@string/email" android:id="@+id/textView4" android:layout_below="@+id/textView" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" android:text="@string/gender" android:id="@+id/textView5" android:layout_below="@+id/txtEmail" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" /> <RadioGroup android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/textView5" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:id="@+id/radioGroupGender"> <RadioButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/male" android:id="@+id/radMale" android:checked="false" /> <RadioButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/female" android:id="@+id/radFemale" android:checked="false" /> </RadioGroup> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" android:text="@string/hobbies" android:id="@+id/textView6" android:layout_below="@+id/radioGroupGender" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" /> <CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/coding" android:id="@+id/chkCoding" android:onClick="onCheckboxClicked" android:checked="false" android:layout_below="@+id/textView6" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" /> <CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/writing" android:id="@+id/chkWriting" android:onClick="onCheckboxClicked" android:layout_below="@+id/chkCoding" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:checked="false" /> <CheckBox android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/jogging" android:id="@+id/chkJogging" android:onClick="onCheckboxClicked" android:layout_below="@+id/chkWriting" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" android:checked="false" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" android:text="@string/zodiac" android:id="@+id/textView7" android:layout_below="@+id/chkJogging" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" /> <Spinner android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/spinnerZodiac" android:layout_below="@+id/textView7" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/save_me" android:id="@+id/btnSave" android:onClick="save" android:layout_below="@+id/spinnerZodiac" android:layout_alignParentLeft="true" android:layout_alignParentStart="true" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/retrieve" android:onClick="retrieve" android:id="@+id/btnRetrieve" android:layout_alignParentBottom="true" android:layout_alignRight="@+id/spinnerZodiac" android:layout_alignEnd="@+id/spinnerZodiac" /> </RelativeLayout> </ScrollView>
“activity_shared_preferences.xml”将呈现如图 1 所示的 UI 页面。
用户界面 (UI) 包含以下控件:
- 一个用于输入电子邮件的“EditText”文本字段。
- 一个带有两个“RadioButtons”的“RadioGroup”控件,用于性别选择。
- 三个“CheckBox”控件,用于兴趣爱好选择。
- 一个用于星座选择的“Spinner”控件。
- 两个“Button”控件——一个用于保存数据,一个用于检索数据。
本章的后续部分将指导您完成“SharedPreferencesActivity.java”的代码:
初始化
在“SharedPreferencesActivity.java”中,添加以下代码以导入必要的 Android 包,并声明和初始化类变量。
package com.peterleowblog.androidinputnstorage; import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; import android.content.res.Resources; import android.os.Bundle; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.CheckBox; import android.widget.EditText; import android.widget.RadioButton; import android.widget.RadioGroup; import android.widget.Spinner; import android.widget.Toast; public class SharedPreferencesActivity extends Activity { private String email; private String gender; private String hobbies; private String zodiac; public static final String STORAGE_NAME = ""; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_shared_preferences); email = ""; gender = ""; hobbies = ""; zodiac = ""; // Add other code } // Add other methods }
处理“EditText”字段
为了捕获“Email” “EditText”字段中的输入值,您必须首先在“activity_shared_preferences.xml”中找到其“<EditText>”节点“android:id”属性的值,即
android:id="@+id/txtEmail"
此“Email” “EditText”字段随后可以在 Java 代码中引用为:
R.id.txtEmail
同样,您可以使用上述方法在 Java 代码中访问所有 Android UI 控件。
从此“Email” “EditText”字段获取值的 Java 代码是:
((EditText)findViewById(R.id.txtEmail)).getText().toString();
将值设置到此“Email” “EditText”字段的 Java 代码是:
((EditText)findViewById(R.id.txtEmail)).setText(“blahblah@gmail.com”);
稍后,您将把获取和设置“Email” “EditText”字段值的代码添加到“SharedPreferencesActivity.java”中。
处理 RadioGroup
为了捕获性别“RadioGroup”中选定的项目以供进一步处理,请将“SharedPreferencesActivity”类设置为其“OnCheckedChangeListener“。过程如下:
首先,在“SharedPreferencesActivity”类上实现“OnCheckedChangeListener”接口。
public class SharedPreferencesActivity extends Activity implements RadioGroup.OnCheckedChangeListener { // ... other code ... }
接下来,将“OnCheckedChangeListener”接口的方法添加到“SharedPreferencesActivity”类中。
// Add other methods @Override public void onCheckedChanged(RadioGroup radioGroup, int i) { int radioButtonId = radioGroup.getCheckedRadioButtonId(); RadioButton radioButton = (RadioButton)radioGroup.findViewById(radioButtonId); gender = radioButton.getText().toString(); }
最后,在“onCreated()”方法中,添加代码将“SharedPreferencesActivity”类设置为“RadioGroup”对象的“OnCheckedChangeListener“。
RadioGroup radioGroupGender = (RadioGroup) findViewById(R.id.radioGroupGender); radioGroupGender.setOnCheckedChangeListener(this);
您已完成了“RadioGroup”控件的代码。每当用户在性别“RadioGroup”中做出选择时,它都会触发“onCheckedChanged()”事件处理程序方法,该方法包含将选定的性别项目分配给“gender”变量的代码。
处理 CheckBox
为了捕获兴趣爱好“CheckBox”控件中选定的项目以供进一步处理,应用程序必须在所有“CheckBox”控件上实现“onClick()”事件处理程序。过程如下:
首先,请注意,已将 `android:onClick=”onCheckboxClicked”` 属性添加到“activity_shared_preferences.xml”中所有“<checkbox>”节点,以将它们绑定到名为“onCheckboxClicked()”的方法,该方法将处理单击事件。
android:onClick="onCheckboxClicked"
接下来,将“onCheckboxClicked()”方法添加到“SharedPreferencesActivity”类中,以处理所有“CheckBox”控件上的“onClick()”事件。
public void onCheckboxClicked(View view) { CheckBox chkJogging = (CheckBox) findViewById(R.id.chkJogging); CheckBox chkCoding = (CheckBox) findViewById(R.id.chkCoding); CheckBox chkWriting = (CheckBox) findViewById(R.id.chkWriting); StringBuilder sb = new StringBuilder(); if (chkJogging.isChecked()) { sb.append(", " + chkJogging.getText()); } if (chkCoding.isChecked()) { sb.append(", " + chkCoding.getText()); } if (chkWriting.isChecked()) { sb.append(", " + chkWriting.getText()); } if (sb.length() > 0) { // No toast if the string is empty // Remove the first comma hobbies = sb.deleteCharAt(sb.indexOf(",")).toString(); } else { hobbies = ""; } }
您已完成了“CheckBox”控件的代码。每当用户选中或取消选中任何兴趣爱好“CheckBox”控件时,它都会触发“onCheckboxClicked()”方法,该方法包含将选定的兴趣爱好连接起来并将其分配给“hobbies”变量的代码。
处理 Spinner
要使用星座数据填充“Spinner”,请创建一个“ArrayAdapter“,它是“Adapter”类的子类,用于桥接数据源(即在“strings.xml”中名为“zodiac”的字符串数组资源,在代码中引用为“R.array.zodiac”)和“View”(即“Spinner”)。“ArrayAdapter”还负责创建一个“TextView”来包含数据源中的每个项目。要实现这一点,请将以下代码添加到“onCreated()”方法中。
Spinner spinnerZodiac = (Spinner) findViewById(R.id.spinnerZodiac); // Populate the spinner with data source ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this, R.array.zodiac, android.R.layout.simple_spinner_item); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinnerZodiac.setAdapter(adapter);
为了捕获星座“Spinner”中选定的项目以供进一步处理,请将“SharedPreferencesActivity”类设置为其“OnItemSelectedListener“。过程如下:
首先,在“SharedPreferencesActivity”类上实现“OnItemSelectedListener”接口。
public class SharedPreferencesActivity extends Activity implements RadioGroup.OnCheckedChangeListener, AdapterView.OnItemSelectedListener { // ... other code ... }
接下来,将“OnItemSelectedListener”接口的方法添加到“SharedPreferencesActivity”类中。
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { zodiac = parent.getItemAtPosition(position).toString(); } public void onNothingSelected(AdapterView<?> parent) { // An interface callback }
最后,返回“onCreated()”方法,添加代码将“SharedPreferencesActivity”类设置为“Spinner”对象的“OnItemSelectedListener“。
// Set a listener on spinner spinnerZodiac.setOnItemSelectedListener(this);
您已完成了“Spinner”控件的代码。每当用户在星座“Spinner”中做出选择时,它都会触发“onItemSelected()”事件处理程序方法,该方法包含将选定的星座项目分配给“zodiac”变量的代码。
处理“Save Me”按钮
当用户单击“Save Me”按钮时,应用程序将把用户输入的数据保存到某个存储中。为了做到这一点,应用程序必须在“Save Me”按钮上实现“onClick()”事件处理程序。过程如下:
首先,请注意,已将 `android:onClick=”save”` 属性添加到“Save Me” “<Button>”节点在“activity_shared_preferences.xml”中,以将“Save Me”按钮绑定到名为“save()”的方法,该方法将处理其单击事件。
android:onClick="save"
接下来,将“save()”方法添加到“SharedPreferencesActivity”类中,以处理“Save Me”按钮上的“onClick()”事件。请注意,已包含从“Email”“EditText”字段获取值的代码。
public void save(View view) { // Capture email input email = ((EditText)findViewById(R.id.txtEmail)).getText().toString(); // To add code to save data to storage later on }
您已完成了“Save Me”按钮的代码。每当用户单击此按钮时,它将触发“save()”方法,该方法包含使用“getText()“方法捕获“EditText”文本字段中的 Email 输入,并将其分配给“email”变量,然后保存到某个存储中的代码。实际的保存到存储的代码将因存储类型而异。
处理“Get Me”按钮
当用户单击“Get Me”按钮时,应用程序将检索存储的数据,并使用该数据填充 UI 控件。与“Save Me”按钮类似,为了做到这一点,应用程序必须在“Get Me”按钮上实现“onClick()”事件处理程序。过程如下:
首先,请注意,已将 `android:onClick=”retrieve”` 属性添加到“Get Me” “<Button>”节点在“activity_shared.xml”中,以将“Get Me”按钮绑定到名为“retrieve()”的方法,该方法将处理其单击事件。
android:onClick="retrieve"
接下来,将“retrieve()”方法添加到“SharedPreferencesActivity”类中,以处理“Get Me”按钮上的“onClick()”事件。
public void retrieve(View view) { // To add code to retrieve data from storage later on setupUI(); // A method to set the data on the UI controls }
您已完成了“Get Me”按钮的代码。每当用户单击此按钮时,它将触发“retrieve()”方法,该方法包含从某个存储中检索存储数据的代码,将数据分配给相应的类变量(即“email”, “gender”, “hobbies”, 和“zodiac”),并调用“setupUI()”方法在相应的 UI 控件上显示数据。
编写“setupUI()”方法
首先,将“setupUI()”方法插入到“SharedPreferencesActivity”类中。
protected void setupUI(){ // Add code here }
开始将代码逐个添加到“setupUI()”方法中。首先是使用“setText()“方法将分配给“email”变量的已检索电子邮件值设置到“Email” “EditText”字段的代码。
((EditText)findViewById(R.id.txtEmail)).setText(email);
继续添加此代码以选择与分配给“gender”变量的已检索性别值对应的“Gender” “RadioButton”控件。
RadioButton radMale = (RadioButton)findViewById(R.id.radMale); RadioButton radFemale = (RadioButton)findViewById(R.id.radFemale); if (gender.equals("Male")){ radMale.setChecked(true); } else if (gender.equals("Female")){ radFemale.setChecked(true); } else { radMale.setChecked(false); radFemale.setChecked(false); }
继续添加此代码以选中与包含在“hobbies”变量中的已检索兴趣爱好对应的“Hobbies” “CheckBox”控件。
CheckBox chkCoding = (CheckBox)findViewById(R.id.chkCoding); CheckBox chkWriting = (CheckBox)findViewById(R.id.chkWriting); CheckBox chkJogging = (CheckBox)findViewById(R.id.chkJogging); chkCoding.setChecked(false); chkWriting.setChecked(false); chkJogging.setChecked(false); if (hobbies.contains("Coding")) { chkCoding.setChecked(true); } if (hobbies.contains("Writing")) { chkWriting.setChecked(true); } if (hobbies.contains("Jogging")) { chkJogging.setChecked(true); }
最后,将选定的“Zodiac” “Spinner”项目设置为分配给“zodiac”变量的已检索星座值。
Resources resource = getResources(); String[] zodiacArray = resource.getStringArray(R.array.zodiac); for(int i = 0; i < zodiacArray.length; i++){ if(zodiacArray[i].equals(zodiac)){ ((Spinner)findViewById(R.id.spinnerZodiac)).setSelection(i); } }
恭喜!您已创建了一个名为“SharedPreferencesActivity”的 Activity,并学习了处理输入类型的不同方法。您现在可以实现共享偏好设置存储了。
共享偏好设置
Android 提供了“SharedPreferences“类,该类允许应用程序以键值对的形式持久化原始类型数据,例如字符串、整数、长整数、浮点数和布尔值。例如:
KEY | VALUE |
“email” | “xyz@gmail.com” |
“gender” | “Male” |
学习基础知识
要开始使用“SharedPreferences”,应用程序必须首先通过调用以下两种方法之一来获取其实例——“getPreferences()“或“getSharedPreferences()“。
- “getPreferences()”方法返回一个仅对当前 Activity 私有的“SharedPreferences”文件。例如:
SharedPreferences sharedPreferences = getPreferences(Context.MODE_PRIVATE);
- “getSharedPreferences()”方法返回由名称标识的多个“SharedPreferences”文件之一,该名称作为第一个参数传递。如果命名的偏好文件不存在,当您写入更改并提交时,它将被创建。例如:
String STORAGE_NAME = "mySharedPreferences"; SharedPreferences sharedPreferences = getSharedPreferences(STORAGE_NAME, Context.MODE_PRIVATE);
“MODE_PRIVATE“参数是默认值,它限制了对调用应用程序或共享相同用户 ID 的应用程序对“SharedPreferences”文件的访问。
要向“SharedPreferences”文件写入值,请按照以下步骤操作:
- 调用“SharedPreferences”实例的“edit()“方法以获取“SharedPreferences.Editor“对象。例如:
SharedPreferences.Editor editor = sharedPreferences.edit();
- 使用“SharedPreferences.Editor”对象的相应“put<DataType>“方法(例如“putBoolean()”, “putFloat()”, “putInt()”, “putLong()“, “putString()”, and“putStringSet()”)将值添加到“SharedPreferences”。这些方法接受两个参数——第一个参数是键,第二个参数是偏好值。例如:
editor.putString("email", email);
- 调用“SharedPreferences.Editor”对象的“commit()“或“apply()“方法,将“SharedPreferences.Editor”中所做的更改复制到“SharedPreferences”。例如:
editor.apply();
要从“SharedPreferences”读取值,只需调用“SharedPreferences”实例的相应“get<DataType>“方法(例如“getBoolean()”, “getFloat()”, “getInt()”, “getLong()”, “getString()”, and“getStringSet()”)。这些方法接受两个参数——第一个参数是偏好键,第二个参数是如果偏好不存在则返回的默认值。例如:
email = sharedPreferences.getString("email", "");
在了解了“SharedPreferences”的基础知识后,您现在将向项目中添加一个“SharedPreferences”存储类型。
实现它
要在“SharedPreferencesActivity”上实现共享偏好设置存储,请按照以下步骤操作:
- 将“MySharedPreferences”分配给“STORAGE_NAME”变量,这将是“SharedPreferences”文件的名称。
public static final String STORAGE_NAME = "MySharedPreferences";
- 将向“SharedPreferences”文件写入代码添加到“save()”方法中。
public void save(View view) { email = ((EditText)findViewById(R.id.txtEmail)).getText().toString(); SharedPreferences sharedPreferences = getSharedPreferences(STORAGE_NAME, Context.MODE_PRIVATE); SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putString("email", email); editor.putString("gender", gender); editor.putString("hobbies", hobbies); editor.putString("zodiac", zodiac); editor.apply(); Toast.makeText(getApplicationContext(), "You have been saved!", Toast.LENGTH_SHORT).show(); }
- 将从“SharedPreferences”文件读取代码添加到“retrieve()”方法中。
public void retrieve(View view) { SharedPreferences sharedPreferences = getSharedPreferences(STORAGE_NAME, Context.MODE_PRIVATE); email = sharedPreferences.getString("email", ""); gender = sharedPreferences.getString("gender", ""); hobbies = sharedPreferences.getString("hobbies", ""); zodiac = sharedPreferences.getString("zodiac", ""); setupUI(); }
测试 1, 2, 3, …
在真实设备或 AVD 上启动该应用程序,您应该会看到如图 1 所示的“Shared Preferences”页面。在此页面上,输入电子邮件、进行一些选择,然后单击“Save Me”按钮将输入值保存到“SharedPreferences”存储中。导航离开应用程序,然后再次导航回“Shared Preferences”页面,单击“Get Me”按钮以检索并显示之前保存的值。如果您对“Shared Preferences”页面进行了更改,然后单击“Save Me”按钮而未保存更改,它将恢复到已保存的值。它应该能正常工作。给自己一个鼓励。
家庭作业
不要止步于此!挑战自己添加一个删除按钮和代码到“SharedPreferencesActivity”以从您已保存的共享偏好设置中删除所有值。我将把它留给您的作业。
后续
恭喜!您已经完成了一个处理不同输入类型并将输入数据存储在共享偏好设置存储中的应用程序。我希望您能尝试本文提供的作业,它将有助于增强您的知识并丰富您的学习体验。
帖子 Android Input and Shared Preferences 最初发布在 Peter Leow's Code Blog。