持久化技术---《第一行代码Android》笔记

来源:互联网 发布:网络硬盘 编辑:程序博客网 时间:2024/05/14 02:06

    • 文件存储
    • SharedPreferences存储 键值对存储
    • SQLite数据库存储
    • 开源库 LitePal 操作数据库

文件存储

package com.example.filepersistencetest;import android.content.Context;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.text.TextUtils;import android.widget.EditText;import android.widget.Toast;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;/***启动时加载文件中数据,退出时保存数据到文件*/public class MainActivity extends AppCompatActivity {    private EditText edit;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        edit = (EditText) findViewById(R.id.edit);        String inputText = load();        if (!TextUtils.isEmpty(inputText)) {//TextUtils.isEmpty("")判断字符串是否为null或""            edit.setText(inputText);            edit.setSelection(inputText.length());            Toast.makeText(this, "Restoring succeeded", Toast.LENGTH_SHORT).show();        }    }    @Override    protected void onDestroy() {        super.onDestroy();        String inputText = edit.getText().toString();        save(inputText);    }    /**     * 保存数据到文件     */    public void save(String inputText) {        FileOutputStream out = null;        BufferedWriter writer = null;        try {            /**             * Context类中提供了一个openFileOutput()方法用于将数据存储到指定文件,             *     返回一个FileOutputStream对象。             * 第一个参数是文件名,不可以包含路径,所有文件都             *     默认保存在/data/data/<package name>/files/目录下             * 第二个参数是操作模式。有两个:             *     MODE_PRIVATE:同名时覆盖文件内容;             *     MODE_APPEND:同名时追加数据,无同名文件时新建。             */            out = openFileOutput("data", Context.MODE_PRIVATE);            writer = new BufferedWriter(new OutputStreamWriter(out));            writer.write(inputText);        } catch (IOException e) {            e.printStackTrace();        } finally {            try {                if (writer != null) {                    writer.close();                }            } catch (IOException e) {                e.printStackTrace();            }        }    }    /**     * 读取文件数据     */    public String load() {        FileInputStream in = null;        BufferedReader reader = null;        StringBuilder content = new StringBuilder();        try {            /**             * Context类中提供了一个openFileInput()方法用于文件中读取数据。             * 只有一个参数,文件名,不带路径,系统会自动在默认路径中加载这个文件。             * 该方法返回一个FileInputStream对象。             */                    in = openFileInput("data");            reader = new BufferedReader(new InputStreamReader(in));            String line = "";            while ((line = reader.readLine()) != null) {                content.append(line);            }        } catch (IOException e) {            e.printStackTrace();        } finally {            if (reader != null) {                try {                    reader.close();                } catch (IOException e) {                    e.printStackTrace();                }            }        }        return content.toString();    }}

SharedPreferences存储 键值对存储

文件默认路径:/data/data//shared_prefs/
想要使用SharedPreferences来存储数据,需要先获取SharedPreferences对象,有三种方式

  • Context类中的getSharedPreferences()方法,有两个参数,第一个是文件名,不带路径,保存在默认路径;第二个参数是操作模式,目前只有一种MODE_PRIVATE,也是默认的,与传入0效果相同,表示只有当前应用才可以对这个文件进行读写。
  • Activity类中的getSharedPreferences()方法,与Context中的getSharedPreferences()方法相识,不过只有一个操作模式的参数,默认以这个Activity名为文件名。
  • PreferenceManager类中的静态方法getPreferences(),接受一个Context参数,并自动使用当前应用程序的包名作为前缀来命名文件。

保存数据步骤:
1. 调用SharedPreferences对象的edit()方法获取SharedPreferences.Editor对象。
2. 使用Editor对象的putString()、putBoolean()、putInt()等方法传入要保存的数据。
3. 调用Editor的apply()方法提交保存数据

package com.example.sharedpreferencestest;import android.content.SharedPreferences;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.view.View;import android.widget.Button;public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        Button saveData = (Button) findViewById(R.id.save_data);        saveData.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                //保存数据步骤                SharedPreferences.Editor editor = getSharedPreferences("data", MODE_PRIVATE).edit();                editor.putString("name", "Tom");                editor.putInt("age", 28);                editor.putBoolean("married", false);                editor.apply();            }        });        Button restoreData = (Button) findViewById(R.id.restore_data);        restoreData.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                //读取数据步骤                SharedPreferences pref = getSharedPreferences("data", MODE_PRIVATE);                String name = pref.getString("name", "");                int age = pref.getInt("age", 0);                boolean married = pref.getBoolean("married", false);                Log.d("MainActivity", "name is " + name);                Log.d("MainActivity", "age is " + age);                Log.d("MainActivity", "married is " + married);            }        });    }}

SQLite数据库存储

android内置数据库SQLite。SQLite不仅支持标准的SQL语法,还遵循数据库ACID事务,而且不用设置用户名和密码就能使用。
Android提供了一个SQLiteOpenHelper帮助类对SQLite数据库进行操作。SQLiteOpenHelper是个抽象类,需要新建一个类继承此类,并实现此类中方法:
- onCreate():创建数据库
- onUpgrade():升级数据库

package com.example.databasetest;import android.content.Context;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteOpenHelper;import android.widget.Toast;public class MyDatabaseHelper extends SQLiteOpenHelper {    public static final String CREATE_BOOK = "create table Book ("            + "id integer primary key autoincrement, "            + "author text, "            + "price real, "            + "pages integer, "            + "name text)";    public static final String CREATE_CATEGORY = "create table Category ("            + "id integer primary key autoincrement, "            + "category_name text, "            + "category_code integer)";    private Context mContext;    /**     * 构造函数     * @param context     * @param name 数据库名     * @param factory 允许我们在查询数据的时候返回一个自定义的Cursor,一般都是传入null     * @param version 数据库的版本号,可用于对数据库进行升级操作     */    public MyDatabaseHelper(Context context, String name,                            SQLiteDatabase.CursorFactory factory, int version) {        super(context, name, factory, version);        mContext = context;    }    /**     * 创建数据库     * 若数据库不存在则调用本方法,若数据库已存在,则不再调用     * @param db     */    @Override    public void onCreate(SQLiteDatabase db) {        db.execSQL(CREATE_BOOK);        db.execSQL(CREATE_CATEGORY);        Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show();    }    /**     * 数据库升级     * @param db     * @param oldVersion     * @param newVersion     */    @Override    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {        db.execSQL("drop table if exists Book");        db.execSQL("drop table if exists Category");        onCreate(db);    }}

对数据库进行操作。
SQLiteOpenHelper类还有两个非常重要的实例方法,都是创建和打开一个现有数据库,返回数据库实例SQLiteDatabase,但是有不同之处:
- getReadableDatabase():当数据库不可写入(如磁盘空间已满)时,返回的对象将已只读方式打开数据库。
- getWritableDatabase():当数据库不可写入(如磁盘空间已满)时,报异常

package com.example.databasetest;import android.content.ContentValues;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.view.View;import android.widget.Button;public class MainActivity extends AppCompatActivity {    private MyDatabaseHelper dbHelper;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);//得到SQLiteOpenHelper实例        Button createDatabase = (Button) findViewById(R.id.create_database);        createDatabase.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                dbHelper.getWritableDatabase();//打开或创建数据库            }        });        //插入数据        Button addData = (Button) findViewById(R.id.add_data);        addData.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                SQLiteDatabase db = dbHelper.getWritableDatabase();                ContentValues values = new ContentValues();                // 开始组装第一条数据                values.put("name", "The Da Vinci Code");//第一个参数是数据库列名,第二个参数是要插入的数据                values.put("author", "Dan Brown");                values.put("pages", 454);                values.put("price", 16.96);                db.insert("Book", null, values); // 插入第一条数据,第一个参数是表名,第二个参数用于在未指定添加数据的情况下给某些可空的列自动赋值NULL,一般传入null即可,第三个参数是ContentValues实例,用以存储数据                values.clear();                // 开始组装第二条数据                values.put("name", "The Lost Symbol");                values.put("author", "Dan Brown");                values.put("pages", 510);                values.put("price", 19.95);                db.insert("Book", null, values); // 插入第二条数据            }        });        //更新数据库        Button updateData = (Button) findViewById(R.id.update_data);        updateData.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                SQLiteDatabase db = dbHelper.getWritableDatabase();                ContentValues values = new ContentValues();                values.put("price", 10.99);                db.update("Book", values, "name = ?", new String[] { "The Da Vinci Code" });//第一个参数是表名,第二个参数是限制条件,第三个参数是第二个参数中的"?"中的值            }        });        //删除数据        Button deleteButton = (Button) findViewById(R.id.delete_data);        deleteButton.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                SQLiteDatabase db = dbHelper.getWritableDatabase();                db.delete("Book", "pages > ?", new String[] { "500" });            }        });        //查询数据库        Button queryButton = (Button) findViewById(R.id.query_data);        queryButton.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                SQLiteDatabase db = dbHelper.getWritableDatabase();                // 查询Book表中所有的数据                //7个参数分别代表                //表名、要查询的列名、where、where中具体的值、groupBy、having、orderBy                Cursor cursor = db.query("Book", null, null, null, null, null, null);                if (cursor.moveToFirst()) {                    do {                        // 遍历Cursor对象,取出数据并打印                        String name = cursor.getString(cursor.getColumnIndex("name"));                        String author = cursor.getString(cursor.getColumnIndex("author"));                        int pages = cursor.getInt(cursor.getColumnIndex("pages"));                        double price = cursor.getDouble(cursor.getColumnIndex("price"));                        Log.d("MainActivity", "book name is " + name);                        Log.d("MainActivity", "book author is " + author);                        Log.d("MainActivity", "book pages is " + pages);                        Log.d("MainActivity", "book price is " + price);                    } while (cursor.moveToNext());                }                cursor.close();            }        });        //直接运行sql语句        SQLiteDatabase db = dbHelper.getWritableDatabase();        //插入、修改、删除都调用execSQL()方法        db.execSQL("insert into Book(name,author)values(?,?)" , new String[]{"asdf","qwer"});        //查询用rawQuery()方法        db.rawQuery("select * from Book",null);    }}

开源库 LitePal 操作数据库

LitePal采用对象关系映射(ORM)的模式。

1, 在app/build.gradle文件中在dependencies闭包中添加:

compile ‘org.litepal.android:core:1.4.1’

2, 配置litepal.xml.在app/src/main目录下新建assets目录,在该目录下新建litepal.xml:

<?xml version="1.0" encoding="utf-8"?><litepal>    <!--数据库名-->    <dbname value="BookStore" ></dbname>    <!--数据库版本,更新数据库时,这里+1就行了-->    <version value="2" ></version>    <!--表实体类映射列表-->    <list>        <mapping class="com.example.litepaltest.Book"></mapping>    </list></litepal>

3, 修改AndroidManifest.xml文件:

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.example.litepaltest">    <application        android:name="org.litepal.LitePalApplication"<!--这里加入litePal框架-->        android:allowBackup="true"        android:icon="@mipmap/ic_launcher"        android:label="@string/app_name"        android:supportsRtl="true"        android:theme="@style/AppTheme">        <activity android:name=".MainActivity">            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>    </application></manifest>

4,新建实体类

package com.example.litepaltest;import org.litepal.crud.DataSupport;//继承DataSupport类,才能进行CRUD操作public class Book extends DataSupport {    private int id;    private String author;    private double price;    public int getId() { return id;}    public void setId(int id) { this.id = id;}    public String getAuthor() { return author;}    public void setAuthor(String author) {this.author = author;}    public double getPrice() { return price;}    public void setPrice(double price) {this.price = price; }}

5,对数据库的操作

package com.example.litepaltest;import android.database.Cursor;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.view.View;import android.widget.Button;import org.litepal.crud.DataSupport;import org.litepal.tablemanager.Connector;import java.util.List;public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        //新建数据库        Button createDatabase = (Button) findViewById(R.id.create_database);        createDatabase.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Connector.getDatabase();            }        });        //保存数据        Button addData = (Button) findViewById(R.id.add_data);        addData.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Book book = new Book();                book.setName("The Da Vinci Code");                book.setAuthor("Dan Brown");                book.setPages(454);                book.setPrice(16.96);                book.setPress("Unknow");                book.save();            }        });        //更新数据        Button updateData = (Button) findViewById(R.id.update_data);        updateData.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Book book = new Book();                book.setPrice(14.95);                book.setPress("Anchor");                book.setToDefault("price");//把price字段设置为默认值                book.updateAll("name = ? and author = ?", "The Lost Symbol", "Dan Brown");            }        });        //删除数据,可直接调用实例的delete()方法即可,如book.delete()。        //下面是另一种删除数据的方式        Button deleteButton = (Button) findViewById(R.id.delete_data);        deleteButton.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                DataSupport.deleteAll(Book.class, "price < ?", "15");            }        });        Button queryButton = (Button) findViewById(R.id.query_data);        queryButton.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                List<Book> books = DataSupport.findAll(Book.class);                for (Book book: books) {                    Log.d("MainActivity", "book name is " + book.getName());                    Log.d("MainActivity", "book author is " + book.getAuthor());                    Log.d("MainActivity", "book pages is " + book.getPages());                    Log.d("MainActivity", "book price is " + book.getPrice());                    Log.d("MainActivity", "book press is " + book.getPress());                }                //条件查询                List<Book> books2=DataSupport.select("name","author")//要查询的列                        .where("price > ? and price < ?","100","200")                        .order("id")//排序                        .limit(10)                        .offset(10)//偏移量,与limit()一起实现sql中的limit功能                        .find(Book.class);                //SQL语句查询                Cursor c=DataSupport.findBySQL("select * from Book where price < ?","100");            }        });    }}