• 用对象序列化与文件读写保存用户的设置


      曾经在《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;
            }
        }
    }

      大体思路就是这样子,我也不知道真正的应用程序是如何保存用户的习惯与设置的,不过我使用对象序列化也是一种办法吧。

      祝大家学的愉快,玩的开心!

  • 相关阅读:
    Language Integrated Query
    为什么说 LINQ 要胜过 SQL
    LINQ(Language Integrated Query)
    Rx (Reactive Extensions)介绍
    ReactiveX Operators
    ReactiveX
    给 iOS 开发者的 RxSwift(一)
    The features of Swift
    RxSwift源码与模式分析一:基本类
    智力
  • 原文地址:https://www.cnblogs.com/kross/p/3112615.html
Copyright © 2020-2023  润新知