編輯:關於Android編程
Android中有許多的數據存儲方式,如果我們有少量的數據需要存儲,那麼使用:SharedPreferences、文件存儲就可以了。但是如果有大量數據需要進行讀寫,那麼就需要使用到數據庫了。Android中內置了SQLite數據庫,而SQLite數據庫是一個真正輕量級的數據庫,它並沒有後台進程,整個數據庫就對應於一個文件。Android也給我們提供了大量的API,使用起來很方便。
Android提供了SQLiteDatabase對象來管理數據庫,SQLiteDatabase有提供方法來創建,刪除,執行SQL命令,並執行常見的數據庫管理任務。
SQLiteDatabase提供了如下靜態方法來打開一個文件對應的數據庫:
SQLiteDatabase openDatabase(String path, SQLiteDatabase.CursorFactory factory, int flags):當我們獲取到SQLiteDatabase對象之後,就可以調用SQLiteDatabase如下的方法來對數據庫進行操作了:
Android提供了上面的方法,來幫助開發者更“簡便”的對數據庫進行增刪改查。但是其實這些方法完全可以通過SQL語句來完成。而用記上面復雜的參數的時間,就可以來掌握SQL語句了。
上面的方法,都是返回了一個Cursor接口,該接口提供對由數據庫查詢返回的結果集的隨機讀寫訪問,而Cursor同樣提供了如下方法來移動查詢結果的記錄指針:
一旦通過以上方法移動到指定行後,就可以調用Cursor的getXXX()方法來獲取指定列的數據了。
// 判斷數據庫文件存放的文件夾是否存在,不存在則創建
String mPath = Environment.getExternalStorageDirectory() + "/db/";
File file = new File(mPath);
if(!file.exists() && !file.isDirectory()){
// 創建目錄
file.mkdirs();
}
// 使用靜態方法打開數據庫(不存在則創建),第二個參數用於返回Course工廠,null則表示使用默認工廠。
SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(mPath + "blog.db", null);
創建表:
// 執行創建表SQL語句,創建了一個名為blog_info的表 String createSql = "create table blog_info(blog_id integer primary key, blog_name varchar(255), blog_link varchar(255))"; database.execSQL(createSql);
注意:由於數據庫創建在SD卡中,所以需要加上寫入SD卡權限
在創建好數據庫和表之後就可以對表中的數據進行管理和操作了。我們可以直接通過execSQL()方法執行SQL語句來操作,也可以使用Android給我們直接提供的增刪改查方法。
往剛剛上面創建的數據庫blog_info表中插入一條數據:
ContentValues contentValues = new ContentValues();
contentValues.put("blog_name", "Airsaid");
contentValues.put("blog_link", "http://blog.csdn.net/airsaid");
// line為新添加的行號,該行號是一個內部值,與主鍵id無關,當發生錯誤時,返回-1。
long line = mDatabase.insert("blog_info", null, contentValues);
刪除和”Airsaid”相關的數據:
int num = mDatabase.delete("blog_info", "blog_name like ?", new String[]{"Airsaid"});
Toast.makeText(this, "一共刪除了:" + num + "條數據", Toast.LENGTH_SHORT).show();
將所有主鍵大於5的blog_name改為周游:
ContentValues contentValues = new ContentValues();
contentValues.put("blog_name", "周游");
int num = mDatabase.update("blog_info", contentValues, "_id > ?", new String[]{"5"});
由於查詢條件的不確定性,所以query()方法的參數真的是比較長。。感覺建議在寫查詢語句的時候,可以直接使用rawQuery()方法進行查詢。
下面寫一個實例,用戶分別輸入博客名和博客鏈接,點插入後,將數據存儲到數據庫,並用列表展示出來:
* 布局:
代碼:
public class MainActivity extends AppCompatActivity {
private String mPath = Environment.getExternalStorageDirectory() + "/db/";
private static final String DB_NAME = "blog.db";
private EditText mEdtName;
private EditText mEdtLink;
private ListView mListView;
private SQLiteDatabase mDatabase;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mEdtName = (EditText) findViewById(R.id.edt_blog_name);
mEdtLink = (EditText) findViewById(R.id.edt_blog_link);
mListView = (ListView) findViewById(R.id.listView);
// 判斷數據庫文件存放的文件夾是否存在,不存在則創建
File file = new File(mPath);
if(!file.exists() && !file.isDirectory()){
// 創建目錄
file.mkdirs();
}
// 使用靜態方法打開數據庫(不存在則創建),第二個參數用於返回Course工廠,null則表示使用默認工廠。
mDatabase = SQLiteDatabase.openOrCreateDatabase(mPath + DB_NAME, null);
// 執行創建表SQL語句,創建了一個名為blog_info的表
String createSql = "create table blog_info(_id integer primary key, blog_name varchar(255), blog_link varchar(255))";
mDatabase.execSQL(createSql);
}
/**
* 插入數據
*/
public void insert(View v){
// 獲取用戶輸入信息
String name = mEdtName.getText().toString();
String link = mEdtLink.getText().toString();
// 執行SQL語句插入數據
mDatabase.execSQL("insert into blog_info values(null, ?, ?)", new String[]{name, link});
// 填充數據到ListView
Cursor cursor = mDatabase.rawQuery("select * from blog_info", null);
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.item_listview_blog, cursor
, new String[]{"blog_name", "blog_link"}, new int[]{R.id.txt_name, R.id.txt_link}
, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
mListView.setAdapter(adapter);
}
}
Item布局:
運行結果:
數據庫操作,事務是少不了的,而SQLiteDatabase也提供了如下幾個方法來操作事務:
* beginTransaction():開始事務。
* endTransaction():結束事務。
* inTransaction():判斷當前上下文是否處於事務中。
當調用endTransaction()方法結束事務的時候,那麼到底是提交事務還是進行回滾事務呢?這取決於SQLiteDatabase是否調用了:setTransactionSuccessful()方法來設置事務標志,如果在執行事務的時設置了,當事務成功則提交事務,否則程序將回滾事務。
其實在真實項目開發中,很少使用SQLiteDatabase的方法來打開數據庫,而是通過繼承Android給我們提供的SQLiteOpenHelper抽象類來創建。
SQLiteOpenHelper是一個輔助類,用於來幫助我們建立和管理數據庫。我們只需要繼承它,並實現兩個抽象方法:
* onCreate(SQLiteDatabase db):在初次生成數據庫的時候會被調用,用於生成表結構。
* onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion):在數據庫版本發生更新時會被調用,oldVersion為舊數據庫版本號,newVersion為新版本數據庫版本號。
SQLiteOpenHelper有如下方法:
public class MyDatabaseHelper extends SQLiteOpenHelper {
public MyDatabaseHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}
@Override
public void onCreate(SQLiteDatabase db) {
// 創建表結構
db.execSQL("create table dict(_id integer primary key autoincrement, word, detail)");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
布局很簡單,分別為單詞輸入框和釋義輸入框,輸入完成後點擊按鈕保存到數據庫,保存數據後,用戶可以輸入要查詢的生詞進行查詢,點擊查詢將結果作為dialog展示出來。添加生詞的方法如下:
public void add(View v) {
// 添加生詞
String word = mEdtWord.getText().toString();
String detail = mEdtDetail.getText().toString();
if(TextUtils.isEmpty(word) || TextUtils.isEmpty(detail)){
Toast.makeText(this, "輸入的數據不能為空", Toast.LENGTH_SHORT).show();
return;
}
SQLiteDatabase database = mDb.getReadableDatabase();
database.execSQL("insert into dict values(null, ? , ?)", new String[]{word, detail});
Toast.makeText(this, "添加成功", Toast.LENGTH_SHORT).show();
}
主要是通過SQLiteOpenHelper的 getReadableDatabase()方法獲取了SQLiteDatabase對象。這裡需要注意的是:
getReadableDatabase()方法會先以讀寫方式打開數據庫,如果數據庫的磁盤空間已經滿了,那麼就會打開失敗,然後再嘗試以只讀的方式打開數據庫。
而通過getWritableDatabase()方法,如果磁盤空間已滿,打開時就會出錯。
public void seek(View v) {
// 查看生詞
String dict = mEdtInput.getText().toString();
SQLiteDatabase database = mDb.getReadableDatabase();
Cursor cursor = database.rawQuery("select * from dict where word like ? or detail like ?"
, new String[]{"%" + dict + "%", "%" + dict + "%"});
List dicts = new ArrayList<>();
while (cursor.moveToNext()){
String word = cursor.getString(1);
String detail = cursor.getString(2);
dicts.add("生詞:" + word + " 解釋:" + detail);
}
showData(dicts);
}
將結果展示:
private void showData(Listdicts) { if(dicts.size() < 1) { Toast.makeText(this, "沒有找到到該生詞數據", Toast.LENGTH_SHORT).show(); return; } String[] strings = dicts.toArray(new String[dicts.size()]); for (String string : strings) { Log.e("test", string); } new AlertDialog.Builder(this) .setTitle("查詢出來的單詞結果") .setItems(dicts.toArray(new String[dicts.size()]), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }).create().show(); }
運行結果:

如何開啟Android 4.4.x系統的ART模式
如今很多Android手機新品都已經預裝或可升級到Android 4.4.x版本了,而該版本最大特色就是引入了ART模式。那麼,如何才能啟動這個模式呢?AR
Android中fragment與activity之間的交互(兩種實現方式)
(未給Fragment的布局設置BackGound)之前關於Android中Fragment的概念以及創建方式,我專門寫了一篇博文《詳解Android中Fragment的
Android Studio添加aar
1、把aar復制到項目中的 libs 裡面 2、在module 裡面的build.gradle 的根目錄添加repositories{ flatDir {
Listview嵌套Viewpager實現仿淘寶搜狐廣告主頁,並實現listview的下拉刷新
Android實現功能:Listview嵌套viewpager仿淘寶搜狐視頻主頁面,和listview的下拉刷新。直接上圖下面給出我源碼的主要文件構成:MyListVie
我的Android進階之旅------)Android Activity的singleTask加載模式和onActivityResult方法之間的沖突
今天調試一個bug的時候,情景如下:一個Activity A,需要用st