目录
1 SharedPreferences
1.1 简介
SharedPreferences 是 Android 系统中一个轻量级的存储类,主要是保存一些常用的配置比如:应用的配置属性,用户的数据(比如用户名,密码等)。这种方式适合存储少量的数据,它提供了很方便的接口方法。
SharedPreferences 的实现主要是通过使用 XML 文件来存储数据,每一个 SharedPreferences 对象对应一个文件。数据会按照键值对的方式存储在文件中。
1.2 存储的位置和格式
SharedPreferences 的数据存储在设备的内部存储空间,在以下的路径:
/data/data/<package name>/shared_prefs/<name>.xml
其中,<package name>
是你的应用的包名,<name>
是你在创建 SharedPreferences 实例时提供的名字。
SharedPreferences 的数据存储为 XML 格式,比如你存储了一个名为 "username" 的字符串 "User" 和一个名为 "age" 的整数 25,那么生成的 XML 文件可能是这样的:
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<string name="username">User</string>
<int name="age" value="25" />
</map>
请注意,由于这些文件存储在应用的内部存储空间,所以它们默认情况下只能被你的应用访问。如果你想要让其他应用也能访问这些数据,那么你可能需要使用其他的存储方案。
1.3 示例代码
存储数据的代码如下:
SharedPreferences sharedPreferences = getSharedPreferences("MyPreferences", MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("username", "User");
editor.putString("password", "123456");
editor.apply();
读取数据的代码如下:
SharedPreferences sharedPreferences = getSharedPreferences("MyPreferences", MODE_PRIVATE);
String username = sharedPreferences.getString("username", "");
String password = sharedPreferences.getString("password", "");
2 Filter存储
Android提供了两种文件存储方式,内部存储和外部存储。内部存储的文件默认只能被自己的应用访问,而外部存储的文件则可以被其他应用访问。
2.1 打开应用数据文件的 I/O 流
在Android中写入数据到文件的代码如下:
String filename = "myfile";
String fileContents = "Hello world!";
try (FileOutputStream fos = openFileOutput(filename, Context.MODE_PRIVATE)) {
fos.write(fileContents.getBytes());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
读取数据的代码如下:
String filename = "myfile";
try (FileInputStream fis = openFileInput(filename)) {
InputStreamReader inputStreamReader = new InputStreamReader(fis, StandardCharsets.UTF_8);
StringBuilder stringBuilder = new StringBuilder();
try (BufferedReader reader = new BufferedReader(inputStreamReader)) {
String line = reader.readLine();
while (line != null) {
stringBuilder.append(line).append('\n');
line = reader.readLine();
}
} catch (IOException e) {
// Error occurred when opening raw file for reading.
} finally {
String contents = stringBuilder.toString();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
2.2 读写SD卡上的文件
首先,你需要在你的应用的 manifest 文件中添加读写 SD 卡的权限:
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
然后,你可以使用以下的代码来读写 SD 卡上的文件:
写入数据的代码:
File sdcard = Environment.getExternalStorageDirectory();
File file = new File(sdcard, "myFile.txt");
try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write("Hello world!".getBytes());
}
读取数据的代码:
File sdcard = Environment.getExternalStorageDirectory();
File file = new File(sdcard, "myFile.txt");
try (FileInputStream fis = new FileInputStream(file)) {
InputStreamReader inputStreamReader = new InputStreamReader(fis, StandardCharsets.UTF_8);
StringBuilder stringBuilder = new StringBuilder();
BufferedReader reader = new BufferedReader(inputStreamReader);
String line = reader.readLine();
while (line != null) {
stringBuilder.append(line).append('\n');
line = reader.readLine();
}
String contents = stringBuilder.toString();
}
请注意,在 Android 10(API 等级 29)及更高版本中,直接访问外部存储(如 SD 卡)的方式已经发生了变化,你需要使用 Storage Access Framework (SAF) 或者 MediaStore API 来读写外部存储上的文件。
3 SQLite数据库
3.1 SQLiteDatabase简介
SQLite 是一款轻型的数据库,是由 C 语言编写的,体积非常小,运行速度非常快。它占用资源极少,并且能够支持绝大多数的 SQL 语言标准,是一款非常出色的嵌入式数据库。Android 系统内置了 SQLite 数据库,开发者可以直接使用。
3.2 创建数据库和表
在 Android 中,我们通常会通过继承 SQLiteOpenHelper
类并重写 onCreate()
方法来创建数据库和表。下面是一个例子:
public class MySQLiteHelper extends SQLiteOpenHelper {
public static final String DATABASE_NAME = "my_database.db";
public static final String TABLE_NAME = "my_table";
public static final String COLUMN_ID = "_id";
public static final String COLUMN_NAME = "name";
private static final int DATABASE_VERSION = 1;
// Database creation sql statement
private static final String DATABASE_CREATE = "create table "
+ TABLE_NAME + "(" + COLUMN_ID
+ " integer primary key autoincrement, " + COLUMN_NAME
+ " text not null);";
public MySQLiteHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase database) {
database.execSQL(DATABASE_CREATE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);
}
}
3.3 使用 SQL 语句操作数据库
Android 提供了 SQLiteDatabase
类来进行数据库操作,我们可以使用它提供的 execSQL()
方法来执行 SQL 语句。以下是插入一条数据的例子:
SQLiteDatabase db = mySQLiteHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(MySQLiteHelper.COLUMN_NAME, "example");
long newRowId = db.insert(MySQLiteHelper.TABLE_NAME, null, values);
查询数据的例子:
String[] projection = {
MySQLiteHelper.COLUMN_ID,
MySQLiteHelper.COLUMN_NAME
};
String sortOrder = MySQLiteHelper.COLUMN_NAME + " DESC";
Cursor cursor = db.query(
MySQLiteHelper.TABLE_NAME,
projection,
null,
null,
null,
null,
sortOrder
);
List<String> itemIds = new ArrayList<>();
while(cursor.moveToNext()) {
long itemId = cursor.getLong(
cursor.getColumnIndexOrThrow(MySQLiteHelper.COLUMN_ID));
itemIds.add(itemId);
}
cursor.close();
3.4 使用特定方法操作SQLite数据库
对于SQLite数据库的操作,除了使用SQL语句之外,Android还提供了一些特定的方法来进行操作,这些方法更加方便和安全。以下是使用这些方法来插入、查询、更新和删除数据的例子:
3.4.1 插入数据
ContentValues values = new ContentValues();
values.put(MySQLiteHelper.COLUMN_NAME, "example");
SQLiteDatabase db = mySQLiteHelper.getWritableDatabase();
long newRowId = db.insert(MySQLiteHelper.TABLE_NAME, null, values);
insert()方法需要一个表名和一个ContentValues对象,这个对象包含了你要插入的数据。
3.4.2 查询数据
String[] projection = {
MySQLiteHelper.COLUMN_ID,
MySQLiteHelper.COLUMN_NAME
};
Cursor cursor = db.query(
MySQLiteHelper.TABLE_NAME,
projection,
null,
null,
null,
null,
null
);
List<String> itemIds = new ArrayList<>();
while(cursor.moveToNext()) {
long itemId = cursor.getLong(
cursor.getColumnIndexOrThrow(MySQLiteHelper.COLUMN_ID));
itemIds.add(itemId);
}
cursor.close();
query()方法需要一个表名和一个列名数组,返回一个 Cursor 对象,你可以通过这个对象来遍历查询结果。
3.4.3 更新数据
ContentValues values = new ContentValues();
values.put(MySQLiteHelper.COLUMN_NAME, "new_example");
String selection = MySQLiteHelper.COLUMN_NAME + " LIKE ?";
String[] selectionArgs = { "example" };
int count = db.update(
MySQLiteHelper.TABLE_NAME,
values,
selection,
selectionArgs);
update() 方法需要一个表名,一个 ContentValues 对象和一些用于定义 WHERE 子句的参数。
3.4.4 删除数据
String selection = MySQLiteHelper.COLUMN_NAME + " LIKE ?";
String[] selectionArgs = { "example" };
int deletedRows = db.delete(MySQLiteHelper.TABLE_NAME, selection, selectionArgs);
delete()方法需要一个表名和一些用于定义 WHERE 子句的参数。
这些特定的方法比直接使用SQL语句更安全,因为它们可以自动防止SQL注入攻击。同时,使用这些方法也更方便,因为你不需要手动拼接SQL语句。
3.5 事务
在操作数据库的过程中,如果涉及到多个操作,且这些操作需要作为一个整体来处理,那么就需要用到事务。
在SQLite 中,可以通过beginTransaction()、setTransactionSuccessful()
和 endTransaction()
方法来开启、设置成功和结束一个事务。
db.beginTransaction();
try {
db.execSQL("...");
db.execSQL("...");
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
3.6 SQLiteOpenHelper 类
SQLiteOpenHelper
是一个辅助类,用来管理数据库的创建和版本管理。它提供了两个回调方法来实现这些功能:
onCreate(SQLiteDatabase db)
:这个方法会在数据库第一次被创建的时候调用,可以在这个方法中执行一些初始化操作,比如创建表,初始化数据等。onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
:这个方法会在数据库需要升级的时候调用,可以在这个方法中进行数据库的升级操作。
这样的设计使得数据库的创建和版本管理变得更加简单。
4 手势
在 Android 中,你可以使用 Gesture Detector 类来识别用户的各种手势。同时,你也可以通过 Gesture Library 来保存和识别用户定义的手势。
4.1 手势检测
你可以使用 GestureDetector
类来检测各种手势,如单击、双击、滑动等。以下是一个简单的例子:
public class MyActivity extends Activity implements GestureDetector.OnGestureListener {
private GestureDetector gestureDetector;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
gestureDetector = new GestureDetector(this, this);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
@Override
public boolean onDown(MotionEvent event) {
// 用户按下屏幕时触发
return false;
}
@Override
public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY) {
// 用户在屏幕上“滑动”时触发
return false;
}
// 其他的回调方法...
}
你需要在 onTouchEvent()
方法中调用 GestureDetector
的 onTouchEvent()
方法,然后根据需要重写 onDown()
、onFling()
等方法。
4.2 增加手势
要识别用户自定义的手势,你需要使用 GestureOverlayView
和 GestureLibrary
。用户可以在 GestureOverlayView
上绘制手势,然后你可以把这个手势保存到 GestureLibrary
,以便以后识别。
以下是一个简单的例子:
public class MyActivity extends Activity {
private GestureLibrary gestureLib;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
GestureOverlayView gestures = findViewById(R.id.gestureOverlayView);
gestures.addOnGesturePerformedListener(new GestureOverlayView.OnGesturePerformedListener() {
@Override
public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
// 当用户在 GestureOverlayView 上绘制手势时,将这个手势保存到 GestureLibrary
gestureLib.addGesture("myGesture", gesture);
gestureLib.save();
}
});
gestureLib = GestureLibraries.fromRawResource(this, R.raw.gestures);
if (!gestureLib.load()) {
finish();
}
}
}
在这个例子中,当用户在 GestureOverlayView
上绘制手势时,这个手势会被保存到 GestureLibrary
。然后你可以调用 GestureLibrary
的 recognize()
方法来识别这个手势。