每次程序启动会读取配置文件,一般使用INI文件或XML文件或自定义,但是使用这些文件很繁琐

改进?
SharedPreferences! 将NVP(name/valuePair)保存在Android文件系统中
它屏蔽对文件系统的操纵过程
它有三种访问模式:
MODE_PRIVATE,私有
MODE_WORLD_READABLE,全局读
MODE_WORLD_WRITEABLE,全局写

SharedPreferences的实现

  1. 定义访问模式

    public static int MODE = Context.MODE_WORLD_READABLE + Context.MODE_WORLD_WRITEABLE;
  2. 定义名称

    public static final String PREFERENCE_NAME = "SaveSetting";
  3. 将模式和参数名称作为参数传递给getSharedPreferences(),获取其实例
 SharedPreferences sharedPreferences = getSharedPreferences(PREFERENCE_NAME, MODE);
  1. 通过SharedPreferences.Editor对SharedPreferences进行修改,调用commit()进行提交

     private void saveSharedPreferences(){
           SharedPreferences sharedPreferences = getSharedPreferences(PREFERENCE_NAME, MODE);
           SharedPreferences.Editor editor = sharedPreferences.edit();
           
           editor.putString("Name", nameText.getText().toString());
           editor.putInt("Age", Integer.parseInt(ageText.getText().toString()));
           editor.putFloat("Height", Float.parseFloat(heightText.getText().toString()));
           editor.commit();
     }
  2. 获取已经保存的SharedPreferences中的数据

    private void loadSharedPreferences(){
           SharedPreferences sharedPreferences = getSharedPreferences(PREFERENCE_NAME, MODE);
           String name = sharedPreferences.getString("Name","Tom");
           int age = sharedPreferences.getInt("Age", 20);
           float height = sharedPreferences.getFloat("Height",1.81f);
         ...       
     }

SharedPreferences的文件保存在哪?
<data/data/<packege name>/shared_prefs

文件存储->程序如何读写流式文件?
openFileOutput()和openFileInput()

openFileOutput()的使用(为了写入数据而打开文件)

//参数1:文件名称;参数2:操作模式
FileOutputStream fos = openFileOutput(FILE_NAME,Context.MODE_APPEND);
String text = entryText.getText().toString();
fos.write(text.getBytes());
labelView.setText("文件写入成功,写入长度:"+text.length());
entryText.setText("");
fos.flush();
fos.close();

openFileInput()的使用(为了读取数据而打开文件)

FileInputStream fis = openFileInput(FILE_NAME);
byte[] readBytes = new byte[fis.available()];
while(fis.read(readBytes) != -1){
}

外部存储
设置文件访问权限不能使用Micro SD卡,因为它使用的使FAT文件系统,不支持访问模式和权限控制

如何将数据写入SD卡?

String fileName = "SdcardFile-"+System.currentTimeMillis()+".txt";    
            File dir = new File("/sdcard/");                                     
            if (dir.exists() && dir.canWrite()) { 
                File newFile = new File(dir.getAbsolutePath() + "/" + fileName);   
                FileOutputStream fos  = null;
                    try {
                        newFile.createNewFile();
                        if (newFile.exists() && newFile.canWrite()) { 
                            fos  = new FileOutputStream(newFile); 
                            fos.write(randomNumbersString.getBytes());    
                            TextView labelView = (TextView)findViewById(R.id.label);
                            labelView.setText(fileName + "文件写入SD卡");
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    } finally { 
                     if (fos != null) { 
                         try { 
                             fos.flush(); 
                             fos.close(); 
                             } 
                         catch (IOException e) { } 
                             } 
                     } 
                }

除此之外,还要在AndroidManifest.xml中注册两个用户权限

<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> 
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

访问资源文件(访问/res/raw或res/xml中的文件)

读取原始文件
  1. 调用getResource()函数获取资源实例
  2. 调用资源实例的openRawResource()函数,以二进制流的形式打开指定的原始根式文件
  3. 读取文件结束,调用close()函数关闭文件流

    Resources resources = this.getResources(); //第一步
    InputStream inputStream = null;    
                 try { 
                     inputStream = resources.openRawResource(R.raw.raw_file);//第二步 
                     byte[] reader = new byte[inputStream.available()]; 
                     while (inputStream.read(reader) != -1) { 
                     } 
                     displayView.setText(new String(reader,"utf-8")); 
                 } catch (IOException e) { 
                     Log.e("ResourceFileDemo", e.getMessage(), e); 
                 } finally {     
                     if (inputStream != null) { 
                         try { 
                             inputStream.close(); //第三步
                         } 
                         catch (IOException e) { } 
                     }
                }
    读取XML文件
    1. 调用getXml()函数获取XML解析器XmlPullParser
     XmlPullParser parser = resources.getXml(R.xml.people);  
             String msg = "";
             try { 
                 while (parser.next() != XmlPullParser.END_DOCUMENT) {     
                     String people = parser.getName(); //END_DOCUMENT表示文档魔为,其他属性见课本p209
                     String name = null; 
                     String age = null; 
                     String height = null;
                     if ((people != null) && people.equals("person")) { 
                         int count = parser.getAttributeCount();        
                         for (int i = 0; i < count; i++) { 
                             String attrName = parser.getAttributeName(i);    
                             String attrValue = parser.getAttributeValue(i);  
                             if ((attrName != null) && attrName.equals("name")) { 
                                 name = attrValue; 
                             } else if ((attrName != null) && attrName.equals("age")) { 
                                 age = attrValue; 
                             } else if ((attrName != null) && attrName.equals("height")) { 
                                 height = attrValue; 
                             } 
                          } 
                         if ((name != null) && (age != null) && (height != null)) { 
                             msg += "姓名:"+name+",年龄:"+age+",身高:"+height+"\n";
                         } 
                      } 
                 } 
             } catch (Exception e) { 
                 Log.e("ResourceFileDemo", e.getMessage(), e); 
             } 
             displayView.setText(msg); 

    SQLite数据库
    采用模块式设计
    最核心的部分是虚拟机,B-树
    保存在/data/data/<package name>/databases目录下
    如何用代码建库?
    将数据库的操作都封装在一个类中
    代码示例

    public class DBAdapter {
    
     private static final String DB_NAME = "people.db";
     private static final String DB_TABLE = "peopleinfo";
     private static final int DB_VERSION = 1;
      
     public static final String KEY_ID = "_id";
     public static final String KEY_NAME = "name";
     public static final String KEY_AGE = "age";
     public static final String KEY_HEIGHT = "height";
     
     private SQLiteDatabase db;
     private final Context context;
     private DBOpenHelper dbOpenHelper;//帮助类,辅助建立更新和打开数据库
     
     public DBAdapter(Context _context) {
         context = _context;
       }
    
       /** Close the database */
       public void close() {
           if (db != null){
               db.close();
               db = null;
           }
         }
    
       /** Open the database */
       public void open() throws SQLiteException {  
           dbOpenHelper = new DBOpenHelper(context, DB_NAME, null, DB_VERSION);
           try {
               db = dbOpenHelper.getWritableDatabase();//判断是否建立数据库
           }
           catch (SQLiteException ex) {
               db = dbOpenHelper.getReadableDatabase();
           }      
         }

DBOpenHelper的实现

      /** 静态Helper类,用于建立、更新和打开数据库*/
      private static class DBOpenHelper extends SQLiteOpenHelper {

          public DBOpenHelper(Context context, String name, CursorFactory factory, int version) {
            super(context, name, factory, version);
          }

          private static final String DB_CREATE = "create table " + 
            DB_TABLE + " (" + KEY_ID + " integer primary key autoincrement, " +
            KEY_NAME+ " text not null, " + KEY_AGE+ " integer," + KEY_HEIGHT + " float);";

          @Override
          public void onCreate(SQLiteDatabase _db) {
            _db.execSQL(DB_CREATE);
          }

          @Override
          public void onUpgrade(SQLiteDatabase _db, int _oldVersion, int _newVersion) {            
            _db.execSQL("DROP TABLE IF EXISTS " + DB_TABLE);
            onCreate(_db);
          }
        }

让DBAdaper类支持数据添加、删除更新和查找等功能,在DBAdapter类中增加下面的函数


public class DBAdapter {
      //插入
      public long insert(People people) {
        ContentValues newValues = new ContentValues();
      
        newValues.put(KEY_NAME, people.Name);
        newValues.put(KEY_AGE, people.Age);
        newValues.put(KEY_HEIGHT, people.Height);
        
        return db.insert(DB_TABLE, null, newValues);
      }

     //查询所有数据
      public People[] queryAllData() {  
          Cursor results =  db.query(DB_TABLE, new String[] { KEY_ID, KEY_NAME, KEY_AGE, KEY_HEIGHT}, 
                  null, null, null, null, null);
          return ConvertToPeople(results);   
      }
      
     //查询一条数据
      public People[] queryOneData(long id) {  
          Cursor results =  db.query(DB_TABLE, new String[] { KEY_ID, KEY_NAME, KEY_AGE, KEY_HEIGHT}, 
                  KEY_ID + "=" + id, null, null, null, null);
          return ConvertToPeople(results);   
      }
      
      //将返回的值转换为people类
      private People[] ConvertToPeople(Cursor cursor){
          int resultCounts = cursor.getCount();
          if (resultCounts == 0 || !cursor.moveToFirst()){
              return null;
          }
          People[] peoples = new People[resultCounts];
          for (int i = 0 ; i<resultCounts; i++){
              peoples[i] = new People();
              peoples[i].ID = cursor.getInt(0);
              peoples[i].Name = cursor.getString(cursor.getColumnIndex(KEY_NAME));
              peoples[i].Age = cursor.getInt(cursor.getColumnIndex(KEY_AGE));
              peoples[i].Height = cursor.getFloat(cursor.getColumnIndex(KEY_HEIGHT));
              
              cursor.moveToNext();
          }      
          return peoples; 
      }
      
      //删除所有数据
      public long deleteAllData() {
          return db.delete(DB_TABLE, null, null);
      }

      public long deleteOneData(long id) {
          return db.delete(DB_TABLE,  KEY_ID + "=" + id, null);
      }

      //更新某一条数据
      public long updateOneData(long id , People people){
          ContentValues updateValues = new ContentValues();      
          updateValues.put(KEY_NAME, people.Name);
          updateValues.put(KEY_AGE, people.Age);
          updateValues.put(KEY_HEIGHT, people.Height);
          
          return db.update(DB_TABLE, updateValues,  KEY_ID + "=" + id, null);
      }
      

数据库查询结果返回值是数据集的指针,这个指针就是Cursor类

ContentProvider是应用程序之间共享数据的一种接口机制
通过使用ContentResolver对象,用URI来操纵ContentProvider
image.png
ContentProvider使用的URI语法结构

content://<authority>/<data_path>/<id>

如请求整个people数据集的URI应写为

content://edu.hrbeu.peopleprovider/people

如请求people数据集的的第三条数据的URI应写为

content://edu.hrbeu.peopleprovider/people/3

实现ContentProvider

  • 继承ContentProvider,并重载6个函数
  • 声明CONTENT_URI,并实现UriMatcher
  • 注册ContentProvider

注册ContentProvider在AndroidManifest.xml

<application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
<provider android:authorities="edu.hrbeu.peopleprovider" android:name=".PeopleProvider"/>
</application>

获取ContentResolver对象

ContentResolver resolver =getContentResolver();

自由自在像小鸟
4 声望1 粉丝