Android Studio 從外部匯入資料庫並顯示到頁面中
文章目錄
Android Studio從外部匯入資料庫並顯示到頁面中
最近在開發一個單詞學習的App, 準備好單詞的外部資料庫之後突然卡在了將資料庫匯入專案這一步,參考了很多網上的資料,自己動手嘗試了一遍,最後成功了。在這裡將我的操作過程記錄一下。
1. 從外部匯入資料庫
首先,要匯入的資料庫及其內容是這樣的(使用的資料庫工具是SQLite Expert Professional 4.2):
該資料庫儲存在檔案1.db
中。
開啟Android Studio,在要匯入的專案中,切換至Project檢視,新建一個和Java、res同級的目錄assets(這個目錄的位置與開發環境有關,我看網上說使用Eclispe開發環境時它在res/下,但在AS中它必須與res目錄同級),然後將1.db
做到這裡的時候,不知道大家有沒有這樣的疑問:為什麼要將資料庫檔案放在assets下?
有個解釋說,這個資料夾主要用於存放應用程式中使用的外部資原始檔,然後程式可以通過 I/O 流(使用
AssetManager
)對目錄中的檔案進行讀寫,存放在此目錄下的檔案都會被打包到釋出包中。
接著,實現類MyDBOpenHelper.java
;
這個類就是實現從assets目錄讀取資料庫檔案然後寫入SD卡中,如果在SD卡中存在,就開啟資料庫,不存在就從assets目錄下複製過去。
import java.io.OutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import android.database.Cursor; import android.util.Log; public class MyDBOpenHelper extends SQLiteOpenHelper { private static String PACKAGE_NAME = "com.example.wordsofmultilanguage"; //包名 private static String DB_PATH = "/data" + Environment.getDataDirectory().getAbsolutePath() + "/" + PACKAGE_NAME + "/databases/"; private static String DB_NAME = "1"; private SQLiteDatabase db; private final Context context; public MyDBOpenHelper(Context context) { super(context, DB_NAME , null, 1); this. context = context; } public void createDB() throws IOException { this.getReadableDatabase(); try { copyDB(); } catch (IOException e) { throw new Error("Error copying database"); } } public void copyDB() throws IOException{ try { InputStream ip = context.getAssets().open(DB_NAME+".db"); Log.i("Input Stream....",ip+""); String op= DB_PATH + DB_NAME ; OutputStream output = new FileOutputStream( op); byte[] buffer = new byte[1024]; int length; while ((length = ip.read(buffer))>0){ output.write(buffer, 0, length); Log.i("Content.... ",length+""); } output.flush(); output.close(); ip.close(); } catch (IOException e) { Log.v("error", e.toString()); } } public void openDB() throws SQLException { String myPath = DB_PATH + DB_NAME; db = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READWRITE); Log.i("open DB......",db.toString()); } @Override public synchronized void close() { if(db != null) db.close(); super.close(); } @Override public void onCreate(SQLiteDatabase db) { } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }
2. 顯示資料庫內容
在頁面上顯示資料庫內容(即英文單詞和釋義)時,用到了ListView控制元件,新建一個 佈局檔案im.xml
:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <ListView android:id="@+id/word_info" android:layout_width="match_parent" android:layout_height="wrap_content"/> </LinearLayout>
對ListView的每一條item做佈局item.xml
:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/word"
android:textSize="16dp"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/mean1"
android:textSize="16dp"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/mean2"
android:textSize="16dp"
/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/mean3"
android:textSize="16dp"
/>
</LinearLayout>
完成第一步外部資料庫的匯入之後,定義一個類initdate.java
用來例項化資料庫:
public class initdate {
public String word;
public String meaning1;
public String meaning2;
public String meaning3;
public initdate(String word, String meaning1, String meaning2, String meaning3){
this.word = word;
this.meaning1 = meaning1;
this.meaning2 = meaning2;
this.meaning3 = meaning3;
}
}
然後,實現類
package com.example.wordsofmultilanguage;
import android.content.Context;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import java.io.IOException;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.SimpleTimeZone;
import android.database.Cursor;
import android.widget.ListView;
import android.widget.SimpleAdapter;
public class test extends AppCompatActivity {
//建立一個List物件來儲存資料
List<initdate>list = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.im);
ListView listView = (ListView)this.findViewById(R.id.word_info);
MyDBOpenHelper db;
db = new MyDBOpenHelper(this);
try {
db.createDB();
} catch (IOException ioe) {
throw new Error("Database not created....");
}
try {
db.openDB();
} catch (SQLException sqle) {
throw sqle;
}
SQLiteDatabase db1;
db1 = openOrCreateDatabase("1", Context.MODE_PRIVATE, null);
Cursor c = db1.rawQuery("SELECT * FROM words1", null);
c.moveToFirst();
//獲取表資料
while (!c.isAfterLast()) {
list.add(new initdate(c.getString(c.getColumnIndex("word")),c.getString(c.getColumnIndex("meaning1")),
c.getString(c.getColumnIndex("meaning2")),c.getString(c.getColumnIndex("meaning3"))));
c.moveToNext();
}
//將獲取到的資料通過一個迴圈存放到map物件中
List<HashMap<String, Object>> data = new ArrayList<HashMap<String, Object>>();
for(int i = 0; i < list.size(); i++){
HashMap<String, Object>item = new HashMap<String, Object>();
item.put("word", list.get(i).word);
item.put("meaning1", list.get(i).meaning1);
if(list.get(i).meaning2 != null){
item.put("meaning2", list.get(i).meaning2);
}
//item.put("meaning2", list.get(i).meaning2);
if(list.get(i).meaning3 != null){
item.put("meaning2", list.get(i).meaning3);
}
//item.put("meaning3", list.get(i).mmeaning3);
data.add(item);
}
//建立SimpleAdapter介面卡將資料繫結到item顯示控制元件上
SimpleAdapter adapter = new SimpleAdapter(this, data, R.layout.item,
new String[]{"word", "meaning1", "meaning2", "meaning3"}, new int[]{R.id.word, R.id.mean1, R.id.mean2, R.id.mean3});
//實現列表的顯示
listView.setAdapter(adapter);
}
}
效果圖:
3. 踩坑記錄
在操作過程中,匯入資料庫檔案的時候曾經碰到以下問題:
我資料庫使用的編碼形式是UTF-8,這是我匯入1.db
檔案後顯示的內容,全是亂碼,並且提示File was loaded in the wrong encoding: 'UTF-8'
,我的解決辦法是啥也不做,不用管,只要原先的資料庫內容沒問題,繼續往下做就可以。原因好像是因為AS打不開這個型別的檔案,要用專門的SQLite工具開啟,如果嘗試開啟的話就會變成一堆亂碼,而且從此以後不管刪除、重新匯入多少次AS都很”貼心“地給你顯示成亂碼。(小白第一次用 AS 開發專案,啥也不懂,被這玩意兒坑死了,想了各種辦法,最後發現它根本不影響……)