曾經在《Java核心技術卷II》中看到可以把對象序列化,也就是輸出到一個文件上,保存對象的信息,我當時就想到,可以使用這個保存用戶的一些設置信息,比如窗口的大小,位置等等一些用戶習慣。加上最近看到Android的Saving Data,想試一試Android上的文件讀寫功能。於是,將這兩個功能結合在一起寫了一個保存用戶設置的功能。
這次講兩個內容:
1.對象序列化。
2.Android系統中的文件讀寫。
先來看下對象序列化是怎麼回事,Java中有一個接口叫Serializable,對象實現這個接口後,就可以進行使用ObjectOutputStream和ObjectInputStream對其進行寫入與讀取。參考以下代碼:
class UserSetting implements Serializable {
private String username;
private int gender;
private String qqNumber;
...Getter and Setter methods...
}
以上代碼構建了一個實現序列化接口的類,裡面有三個屬性,並且有相應的構造方法與Getter,Setter方法。接下來,看看如何將其輸出。
UserSetting us = new UserSetting(username, gender, qqNumber);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("data")));
oos.writeObject(us);
OK!我們已經把對象us存入了名為data的文件中(這個文件沒有後綴名,有沒有後綴都無所謂,想怎麼起都看自己高興)。接下來我們用ObjectInputStream對象來讀取對象。
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("data")));
UserSetting us = (UserSetting)ois.readObject();
us.getUsername();
...and than, you can do anything you want!
通過以上的小實驗,就能很快熟悉如何寫入讀取對象。接下來就是如何在Android系統中讀寫文件。
在Android系統中,可以通過Environment對象來獲取用於使用的目錄,Environment有好幾個獲取目錄的方法,我都試了一下,以下是每個方法返回的路徑。
getDataDirectory -> /data getExternalStorageState -> mounted getExternalStorageDirectory -> /storage/sdcard0 getDownloadCacheDirectory -> /cache getExternalStoragePublicDirectory -> /storage/sdcard0/Alarms getRootDirectory -> /system 斜槓'/'表示的是根目錄,根目錄內部都是內部存儲,也就是手機的“硬盤”,而/storage/sdcard0是我的手機的外部存儲,就是所謂的SD卡,關於內部存儲,與外部存儲可以參考Google的官方文檔Saving Data。我想的是把用戶的設置信息存儲到/storage/sdcard0/testSavingUserSetting/user.setting中。只要訪問SD卡,並在裡面寫文件就可以了。不過操作外部存儲需要相應的權限,需要在Manifest文件中聲明權限。<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
我寫了一個用戶的設置界面,一個EditText填寫username,一個RadioGroup選擇gender,一個EditText填寫QQnumber,最底下還有一個Button用來保存用戶的信息。
activity_main.xml代碼如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<TextView
android:id="@+id/label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/label"
android:gravity="center_horizontal"/>
<EditText
android:id="@+id/username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/label"
android:hint="@string/username_hint"/>
<RadioGroup
android:id="@+id/gender"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/username"
android:orientation="horizontal">
<RadioButton
android:id="@+id/man"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="choiceGender"
android:text="@string/man"/>
<RadioButton
android:id="@+id/female"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="choiceGender"
android:text="@string/female"/>
</RadioGroup>
<EditText
android:id="@+id/qq_number"
android:inputType="number"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/gender"
android:hint="@string/qq_number_hint"/>
<Button
android:id="@+id/save_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="20dp"
android:text="@string/save_button"
android:onClick="saveUserSetting"/>
</RelativeLayout>
在MainActivity.java文件中,我在onCreate()方法中構造了SD卡的文件路徑,應用程序的文件路徑,已經設置文件,在onCreate()方法中判斷我們程序目錄是否存在,即/storage/sdcard0/testSavingUserSetting這個目錄。如果不存在的話,就創建目錄,如果存在的話就就讀取裡面的文件,並且把值都更新到UI控件上。
再寫一個saveUserSetting()方法,用來相應Button的onClick事件,在這個方法裡面,將控件的值獲取,寫入文件即可。這些就是代碼的思路。以下是代碼:
package com.kross.saveusersetting;
...there are many import.
public class MainActivity extends Activity {
private static final String RadioButton = null;
private UserSetting mUserSetting = null;
private File mSdcard = null;
private File mAppDir = null;
private File mUserSettingFile = null;
private ObjectOutputStream oos = null;
private ObjectInputStream ois = null;
private EditText mUsername = null;
private RadioGroup mGender = null;
private EditText mQqNumber = null;
private String username = null;
private int gender = 0;
private int qqNumber = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mUsername = (EditText)findViewById(R.id.username);
mGender = (RadioGroup)findViewById(R.id.gender);
mQqNumber = (EditText)findViewById(R.id.qq_number);
//sd卡的目錄
mSdcard = Environment.getExternalStorageDirectory();
//該應用程序的目錄
mAppDir = new File(mSdcard, "saveUserSetting");
//該應用程序的設置文件
mUserSettingFile = new File(mAppDir, "user.settiong");
//判斷應用程序目錄是否存在
if (mAppDir.exists()) {
//如果存在,判斷應用程序設置文件是否存在
if (mUserSettingFile.exists()) {
try {
//文件存在的情況下,讀取裡面的對象,設置UI控件
ois = new ObjectInputStream(new FileInputStream(mUserSettingFile));
mUserSetting = (UserSetting)ois.readObject();
mUsername.setText(mUserSetting.getUsername());
if (mUserSetting.getGender() == 1) {
RadioButton manButton = (RadioButton)mGender.getChildAt(0);
manButton.setChecked(true);
} else {
RadioButton femaleButton = (RadioButton)mGender.getChildAt(1);
femaleButton.setChecked(true);
}
mQqNumber.setText(mUserSetting.getQqNumber() + "");
} catch (StreamCorruptedException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//文件不存在,什麼也不做
} else {
}
//目錄不存在就創建目錄
} else {
mAppDir.mkdir();
}
}
@SuppressLint("NewApi")
public void saveUserSetting(View v) {
//判斷兩個輸入框的值是否為空
if (!(mUsername.getText().toString().isEmpty()) && !(mQqNumber.getText().toString().isEmpty())) {
this.username = mUsername.getText().toString();
this.qqNumber = Integer.parseInt(mQqNumber.getText().toString());
mUserSetting = new UserSetting(this.username, this.gender, this.qqNumber);
try {
//寫入文件
oos = new ObjectOutputStream(new FileOutputStream(this.mUserSettingFile));
oos.writeObject(mUserSetting);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} else {
Toast.makeText(this, "不能為空", Toast.LENGTH_SHORT).show();
}
}
public void choiceGender(View v) {
RadioButton userClickButton = (RadioButton)v;
if (userClickButton.getId() == R.id.man) {
this.gender = 1;
} else if (userClickButton.getId() == R.id.female) {
this.gender = 0;
}
}
}
大體思路就是這樣子,我也不知道真正的應用程序是如何保存用戶的習慣與設置的,不過我使用對象序列化也是一種辦法吧。
祝大家學的愉快,玩的開心!