数据持久化:
是将内存中的瞬时数据保存到存储设备中,保证数据在设备关机情况下不会丢失。
主要有五种存储方式:
一、文件存储
简单的文本或二进制数据。如果想保存较为复杂的数据,则要自定义一套自己的格式规范。
代码示例:(《第一行代码》)
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;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.text.TextUtils;
import android.widget.EditText;
import android.widget.Toast;
/**
* 演示文件的存储和读取
* @author Administrator
*
*/
public class MainActivity extends Activity {
private EditText edit;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
edit = (EditText) findViewById(R.id.edit);
// 调用load()方法读取存储的文本内容
String inputText = load();
// 一次性进行两种空值的判断-->传入的字符串等于null或者等于空字符串。默认返回true
if (!TextUtils.isEmpty(inputText)) {
edit.setText(inputText);
// setSelection() 将输入光标移动到文本的末尾位置以便于继续输入
edit.setSelection(inputText.length());
Toast.makeText(this, "Restoring succeeded", Toast.LENGTH_SHORT).show();
}
}
/**
* 从文件中读取数据
*
* @return
*/
private String load() {
FileInputStream in = null;
StringBuilder content = null;
BufferedReader reader = null;
try {
content = new StringBuilder();
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();
}
/**
* 获取EditText中输入的内容,并调用save()方法把输入的内容存储到文件中,文件名为data。
*/
@Override
protected void onDestroy() {
super.onDestroy();
String inputText = edit.getText().toString();
save(inputText);
}
/**
* 将数据存储到文件中
*
* @param inputText
*/
private void save(String inputText) {
FileOutputStream out = null;
BufferedWriter writer = null;
try {
// MODE_PRIVATE 覆盖原文件。生成的data文件在 /data/data/包名/files目录下
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();
}
}
}
}
二、SharedPreference存储
使用键值对的方式来存储数据。当保存一条数据的时候,需要给这条数据提供一个对应的键。
package com.example.sharedpreferences;
import android.app.Activity;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
/**
* sharedpreferences一般用于配置信息(config)
* @author Administrator
*
*/
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
/**
* 按钮点击事件。个人喜欢用这种方式,省去不少代码
*
* @param v
*/
public void onClick(View v) {
switch (v.getId()) {
// 将数据存储到sharedpreferences中
case R.id.btn_sava_data:
// sharedpreferences的具体使用方法
// 1、获取对象
SharedPreferences.Editor editor = getSharedPreferences("data", MODE_PRIVATE).edit();
// 2、向对象中添加数据
editor.putString("name", "Wang Weiwei");
editor.putInt("age", 22);
editor.putBoolean("married", false);
// 3、将添加的数据提交,完成数据存储操作
editor.commit();
// 数据保存在 /data/data/包名/shared_prefs下 ,data.xml文件导出即可查看
break;
// 从sharedpreferences中读取数据
case R.id.btn_restore_data:
SharedPreferences pref = getSharedPreferences("data", MODE_PRIVATE);
// 一一对应即可,第二个参数为默认值
String name = pref.getString("name", "");
int age = pref.getInt("age", 0);
boolean married = pref.getBoolean("married", false);
// 在这里,将取出来的值做具体的用途就可以了
default:
break;
}
}
}
具体用途:
package com.example.brosdcastbestpractice;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast;
/**
* 实现记住密码的功能(《第一行代码》)
*
* @author Administrator
*
*/
public class LoginActivity extends BaseActivity {
private SharedPreferences pref;
private SharedPreferences.Editor editor;
private EditText accountEdit;
private EditText passwordEdit;
private Button login;
private CheckBox rememberPass;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login);
pref = PreferenceManager.getDefaultSharedPreferences(this);
accountEdit = (EditText) findViewById(R.id.account);
passwordEdit = (EditText) findViewById(R.id.password);
rememberPass = (CheckBox) findViewById(R.id.remember_pass);
login = (Button) findViewById(R.id.login);
boolean isRemember = pref.getBoolean("remember_password", false);
if (isRemember) {
String account = pref.getString("account", "");
String password = pref.getString("password", "");
accountEdit.setText(account);
passwordEdit.setText(password);
rememberPass.setChecked(true);
}
login.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
String account = accountEdit.getText().toString();
String password = passwordEdit.getText().toString();
// 为了简单一次性判断,实际中可分开判断,提示用户到底是账户输错了还是密码输错了
if (account.equals("wang") && password.equals("0627")) {
editor = pref.edit();
if (rememberPass.isChecked()) {
editor.putBoolean("remember_password", true);
editor.putString("account", account);
editor.putString("password", password);
} else {
editor.clear();
}
editor.commit();
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
startActivity(intent);
finish();
} else {
Toast.makeText(LoginActivity.this, "账户或密码有误,请重新输入", Toast.LENGTH_SHORT).show();
}
}
});
}
}
三、SQLite数据库存储
轻量级的关系型数据库,占用资源少。用来存储数据量大、结构性复杂的数据。
示例代码
1、创建布局文件
<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"
tools:context="${relativePackage}.${activityClass}" >
<Button
android:id="@+id/btn_create_database"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="创建数据库" />
<Button
android:id="@+id/btn_add_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="添加数据" />
<Button
android:id="@+id/btn_update_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="更新数据" />
<Button
android:id="@+id/btn_delete_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="删除数据" />
<Button
android:id="@+id/btn_query_data"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="查询数据" />
</RelativeLayout>
2、新建一个帮助类
package com.example.sqlite;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.widget.Toast;
/**
* SQLite数据存储。帮助类。(《第一行代码》)
* @author Administrator
*
*/
public class MyDatabaseHelper extends SQLiteOpenHelper {
public static final String CREAT_BOOK = "create table Book("
+ "id integer primary key autoincrement, "
+ "author text, "
+ "price real, "
+ "pages integer, "
+ "name text)";
public static final String CREAT_CATEGORY = "create table Category("
+ "id integer primary key autoincrement, "
+ "category_name text, "
+ "category_code integer)";
private Context mContext;
public MyDatabaseHelper(Context context, String name, CursorFactory factory, int version) {
super(context, name, factory, version);
mContext = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
// 创建表的方法
db.execSQL(CREAT_BOOK);
db.execSQL(CREAT_CATEGORY);
Toast.makeText(mContext, "创建成功", Toast.LENGTH_SHORT).show();
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// 升级表的方法
switch (oldVersion) {
case 1:
db.execSQL(CREAT_CATEGORY);
// 关联表的时候调用
// case 2:
// db.execSQL("alter table Book add column category_id integer");
default:
// 不能使用break
}
}
}
在MainActivity.java中:
package com.example.sqlite;
import android.app.Activity;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends Activity {
private MyDatabaseHelper dbHelper;
private SQLiteDatabase db;// 创建SQLiteDatabase对象
private ContentValues values;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 1);
// 升级数据库时只需要在version版本号传入比之前大的数,就可以执行onUpgrate()方法
dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
}
public void onClick(View v) {
switch (v.getId()) {
// 创建数据库
case R.id.btn_create_database:
dbHelper.getWritableDatabase();
break;
// 添加数据
case R.id.btn_add_data:
// 使用ContentValues对数据进行组装
values = new ContentValues();
db = dbHelper.getWritableDatabase();
values.put("name", "Ha Ha");
values.put("author", "Wang");
values.put("pages", 222);
values.put("price", 22.2);
// 插入数据
db.insert("Book", null, values);
values.clear();
break;
// 更新数据
case R.id.btn_update_data:
values = new ContentValues();
db = dbHelper.getWritableDatabase();
values.put("prive", "19.99");
db.update("Book", values, "name = ?", new String[] { "Ha Ha" });
break;
// 删除数据
case R.id.btn_delete_data:
db = dbHelper.getWritableDatabase();
db.delete("Book", "pages > ?", new String[] { "200" });
break;
// 查询数据
case R.id.btn_query_data:
db = dbHelper.getWritableDatabase();
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"));
// 在这里对取的值做具体操作,比如异步消息处理更新UI界面
} while (cursor.moveToNext());
}
cursor.close();
break;
default:
break;
}
}
}
主要就是以上这三种方式。
四、ContentProvider
几乎用不到,一般情况下去读取其他程序的数据。以后再补充。 。 。
五、网络存储
这一块内容放在“Android网络编程”模块里。