Khi bạn đang gặp khó khăn, sau đây là một hướng dẫn tổng hợp vội vàng cùng với mã.
-
Tạo cơ sở dữ liệu và bảng trong một công cụ SQLite, thêm dữ liệu theo yêu cầu rồi Lưu nó.
-
Đóng cơ sở dữ liệu và mở lại để kiểm tra xem các bảng và dữ liệu có như mong đợi hay không. Nếu không thực hiện thay đổi, sau đó lặp lại 2 cho đến khi bạn chắc chắn rằng cơ sở dữ liệu đã lưu khớp.
-
Lấy tên tệp của cơ sở dữ liệu đã lưu và ghi lại nó bao gồm cả phần mở rộng tệp.
-
Nếu bạn chưa tạo Dự án cho Ứng dụng, hãy làm như vậy và lưu dự án.
-
Bên ngoài IDE, hãy điều hướng đến ứng dụng dự án / src / thư mục chính và tạo một thư mục có tên tài sản nếu nó chưa tồn tại.
-
Sao chép tệp cơ sở dữ liệu vào thư mục nội dung.
-
Mở Dự án trong Android Studio.
-
Tạo một lớp Java mới có tên là DatabaseHelper với SuperClass là SQLiteOpenHelper (sẽ giải quyết thành
android.database.sqlite.SQLiteOpenHelper
) và đánh dấu vào nút Hiển thị phần ghi đè đã chọn Hộp kiểm hộp thoại. Nhấp vào OK.
Nó sẽ giống như sau:-
public class DatabaseHelper extends SQLiteOpenHelper {
public Databasehelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
super(context, name, factory, version);
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
}
-
Thêm một dòng, dưới dạng một biến lớp, sau
public class DatabaseHelper extends SQLiteOpenHelper {
nó giống như:-public static final String DBNAME = "my_dic.db";
- Lưu ý rằng điều quan trọng là giá trị trong dấu ngoặc kép phải giống hệt như tên tệp đã được sao chép vào thư mục nội dung.
.
- Thêm các biến lớp sau đây
:-
public static final int DBVERSION = 1;
public static final String TB_BOOKMARK = "Bookmark";
public static final String COL_BOOKMARK_KEY = "key";
public static final String COL_BOOKMARK_VALUE = "value";
public static final String COL_BOOKMARK_DATE = "date";
SQLiteDatabase mDB;
- Lưu ý rằng các giá trị trong dấu ngoặc kép cần phải khớp với tên cột / bảng báo cáo lại đã được xác định trong cơ sở dữ liệu cho TB_BOOKMARK, COL_BOOKMARK_KEY, COL_BOOKMARK_VALUE và COl_BOOKMARK_DATE.
- DBVERSION sẽ là số phiên bản được lưu trữ trong trường user_version của cơ sở dữ liệu.
- SQliteDatabase mDB là một khai báo cho một biến để giữ SQLiteDatabase khi nó đã được mở. LƯU Ý hiện tại giá trị của nó là rỗng cho đến khi nó được đặt.
.
-
Thay đổi hàm tạo cho lớp Databasehelper từ:-
public DatabaseHelper (Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {super (context, name, factory, version);}
tới:-
public DatabaseHelper(Context context) {
super(context, DBNAME, null, DBVERSION);
}
- Điều này làm cho một phiên bản của lớp Databasehelper có thể được tạo chỉ với một tham số, ngữ cảnh. Các giá trị khác đã được xác định hoặc trong trường hợp của nhà máy sẽ không được sử dụng, vì vậy giá trị null biểu thị điều này.
.
- Thêm một phương thức,
ifDBExists
vào lớp DatabaseHelper để kiểm tra xem cơ sở dữ liệu có tồn tại hay không (bạn chỉ muốn sao chép nó từ tệp nội dung một lần)
:-
private boolean ifDBExists(Context context) {
String dbparent = context.getDatabasePath(DBNAME).getParent();
File f = context.getDatabasePath(DBNAME);
if (!f.exists()) {
Log.d("NODB MKDIRS","Database file not found, making directories."); //<<<< remove before the App goes live.
File d = new File(dbparent);
d.mkdirs();
//return false;
}
return f.exists();
}
- Ngoài việc kiểm tra xem tệp cơ sở dữ liệu có tồn tại hay không (lưu ý rằng nó được giả định là tệp cơ sở dữ liệu hợp lệ),
- Ngoài ra, nếu cơ sở dữ liệu không tồn tại thì có thể thư mục cơ sở dữ liệu không tồn tại, điều này sẽ tạo ra nó nếu nó không tồn tại.
.
- Thêm một phương pháp khác
copyDBFromAssets
để sao chép tệp nội dung vào cơ sở dữ liệu
:-
private boolean copyDBFromAssets(Context context) {
Log.d("CPYDBINFO","Starting attemtpt to cop database from the assets file.");
String DBPATH = context.getDatabasePath(DBNAME).getPath();
InputStream is;
OutputStream os;
int length = 8192;
long bytes_read = 0;
long bytes_written = 0;
byte[] buffer = new byte[length];
try {
is = context.getAssets().open(DBNAME);
} catch (IOException e) {
Log.e("CPYDB FAIL - NO ASSET","Failed to open the Asset file " + DBNAME);
e.printStackTrace();
return false;
}
try {
os = new FileOutputStream(DBPATH);
} catch (IOException e) {
Log.e("CPYDB FAIL - OPENDB","Failed to open the Database File at " + DBPATH);
e.printStackTrace();
return false;
}
Log.d("CPYDBINFO","Initiating copy from asset file" + DBNAME + " to " + DBPATH);
while (length >= 8192) {
try {
length = is.read(buffer,0,length);
} catch (IOException e) {
Log.e("CPYDB FAIL - RD ASSET",
"Failed while reading in data from the Asset. " +
String.valueOf(bytes_read) +
" bytes read ssuccessfully."
);
e.printStackTrace();
return false;
}
bytes_read = bytes_read + length;
try {
os.write(buffer,0,length);
} catch (IOException e) {
Log.e("CPYDB FAIL - WR ASSET","failed while writing Database File " +
DBPATH +
". " +
String.valueOf(bytes_written) +
" bytes written successfully.");
e.printStackTrace();
return false;
}
bytes_written = bytes_written + length;
}
Log.d("CPYDBINFO",
"Read " + String.valueOf(bytes_read) + " bytes. " +
"Wrote " + String.valueOf(bytes_written) + " bytes."
);
try {
os.flush();
is.close();
os.close();
} catch (IOException e ) {
Log.e("CPYDB FAIL - FINALISING","Failed Finalising Database Copy. " +
String.valueOf(bytes_read) +
" bytes read." +
String.valueOf(bytes_written) +
" bytes written."
);
e.printStackTrace();
return false;
}
return true;
}
- Xin lưu ý rằng điều này là cố ý dài dòng, vì vậy bất kỳ lỗi nào có thể được xác định.
Lớp DatabaseHelper hoàn chỉnh bây giờ sẽ là:-
public class DatabaseHelper extends SQLiteOpenHelper {
public static final String DBNAME = "my_dic.db"; // <<<< VERY IMPORTANT THAT THIS MATCHES DATABASE FILE NAME
public static final int DBVERSION = 1;
public static final String TB_BOOKMARK = "Bookmark";
public static final String COL_BOOKMARK_KEY = "key";
public static final String COL_BOOKMARK_VALUE = "value";
public static final String COL_BOOKMARK_DATE = "date";
SQLiteDatabase mDB;
public DatabaseHelper(Context context) {
super(context, DBNAME, null, DBVERSION);
if (!ifDBExists(context)) {
if (!copyDBFromAssets(context)) {
throw new RuntimeException("Failed to Copy Database From Assets Folder");
}
}
mDB = this.getWritableDatabase();
}
@Override
public void onCreate(SQLiteDatabase sqLiteDatabase) {
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
private boolean ifDBExists(Context context) {
String dbparent = context.getDatabasePath(DBNAME).getParent();
File f = context.getDatabasePath(DBNAME);
if (!f.exists()) {
Log.d("NODB MKDIRS","Database file not found, making directories.");
File d = new File(dbparent);
d.mkdirs();
//return false;
}
return f.exists();
}
private boolean copyDBFromAssets(Context context) {
Log.d("CPYDBINFO","Starting attemtpt to cop database from the assets file.");
String DBPATH = context.getDatabasePath(DBNAME).getPath();
InputStream is;
OutputStream os;
int length = 8192;
long bytes_read = 0;
long bytes_written = 0;
byte[] buffer = new byte[length];
try {
is = context.getAssets().open(DBNAME);
} catch (IOException e) {
Log.e("CPYDB FAIL - NO ASSET","Failed to open the Asset file " + DBNAME);
e.printStackTrace();
return false;
}
try {
os = new FileOutputStream(DBPATH);
} catch (IOException e) {
Log.e("CPYDB FAIL - OPENDB","Failed to open the Database File at " + DBPATH);
e.printStackTrace();
return false;
}
Log.d("CPYDBINFO","Initiating copy from asset file" + DBNAME + " to " + DBPATH);
while (length >= 8192) {
try {
length = is.read(buffer,0,length);
} catch (IOException e) {
Log.e("CPYDB FAIL - RD ASSET",
"Failed while reading in data from the Asset. " +
String.valueOf(bytes_read) +
" bytes read ssuccessfully."
);
e.printStackTrace();
return false;
}
bytes_read = bytes_read + length;
try {
os.write(buffer,0,length);
} catch (IOException e) {
Log.e("CPYDB FAIL - WR ASSET","failed while writing Database File " +
DBPATH +
". " +
String.valueOf(bytes_written) +
" bytes written successfully.");
e.printStackTrace();
return false;
}
bytes_written = bytes_written + length;
}
Log.d("CPYDBINFO",
"Read " + String.valueOf(bytes_read) + " bytes. " +
"Wrote " + String.valueOf(bytes_written) + " bytes."
);
try {
os.flush();
is.close();
os.close();
} catch (IOException e ) {
Log.e("CPYDB FAIL - FINALISING","Failed Finalising Database Copy. " +
String.valueOf(bytes_read) +
" bytes read." +
String.valueOf(bytes_written) +
" bytes written."
);
e.printStackTrace();
return false;
}
return true;
}
}
.
- Thay đổi hàm tạo để chạy
copyDBFromAssets
phương thức khi / nếu Cơ sở dữ liệu không tồn tại (sử dụngifDBExists
phương pháp)
:-
public DatabaseHelper(Context context) {
super(context, DBNAME, null, DBVERSION);
if (!ifDBExists(context)) {
if (!copyDBFromAssets(context)) {
throw new RuntimeException("Failed to Copy Database From Assets Folder");
}
}
mDB = this.getWritableDatabase();
}
- Lưu ý nếu có sự cố khi sao chép Cơ sở dữ liệu thì Ứng dụng sẽ bị dừng do
RunTimeExcpetion
ban hành.
.
- Sửa đổi lần cuối phương thức onCreate của một hoạt động (thường sẽ là hoạt động chính) để tạo một phiên bản của lớp DatabaseHelper. Sau đó, chạy Ứng dụng (nếu Ứng dụng đã được chạy, tốt nhất là xóa dữ liệu của Ứng dụng trước khi làm như vậy, đề phòng trường hợp một cơ sở dữ liệu, có thể là trống, đã được tạo.)
Đoạn mã sau cũng bao gồm một truy vấn sẽ cho bạn biết bảng nào tồn tại trong cơ sở dữ liệu:-
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DatabaseHelper mDBHlpr = new DatabaseHelper(this);
Cursor csr = mDBHlpr.getWritableDatabase().query(
"sqlite_master",
null,null,null,null,null,null
);
while (csr.moveToNext()) {
Log.d("DB TABLES", csr.getString(csr.getColumnIndex("name")));
}
csr.close();
}
}
Dựa trên ảnh chụp màn hình và tệp cơ sở dữ liệu có tên my_dic.db
. Kết quả trong Nhật ký là:-
06-16 02:28:45.208 4467-4467/? D/NODB MKDIRS: Database file not found, making directories.
06-16 02:28:45.208 4467-4467/? D/CPYDBINFO: Starting attemtpt to cop database from the assets file.
Initiating copy from asset filemy_dic.db to /data/data/com.mydictionaryapp.mydictionaryapp/databases/my_dic.db
Read 12288 bytes. Wrote 12288 bytes.
06-16 02:28:45.224 4467-4467/? D/DB TABLES: Bookmark
sqlite_autoindex_Bookmark_1
android_metadata
- Điều này chỉ ra rằng:-
- Cơ sở dữ liệu không tồn tại và thư mục cơ sở dữ liệu đã được tạo (tức là
data/data/<package name>/databases
) - 12288 byte đã được sao chép từ tệp nội dung sang tệp cơ sở dữ liệu (tức là một bản sao thành công đã được tạo).
- Cơ sở dữ liệu kết quả có ba mục nhập trong bảng sqlite_master, bảng BookMark, một bảng có tên android_metadata (một bảng tự động tạo cho các thiết bị android bởi SDK lưu trữ ngôn ngữ) và một chỉ mục được tạo tự động cho bảng BookMark.
- Cơ sở dữ liệu không tồn tại và thư mục cơ sở dữ liệu đã được tạo (tức là
Sự cố tiếp theo
Về cơ bản, đối tượng không có phương thức gọi là getClass, thay vào đó bạn cần sử dụng phương thức getClass kế thừa của Fragment. Vì vậy, bạn cần đặt đoạn được trả về trong dấu ngoặc đơn.
Vì vậy, thay vì:-
String activeFragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container).getClass().getSimpleName();
Bạn có thể sử dụng:-
String activeFragment = (getSupportFragmentManager().findFragmentById(R.id.fragment_container)).getClass().getSimpleName();
Ngoài ra, bạn có thể sử dụng:-
Fragment activeFragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
cùng với việc sử dụng:-
if (activeFragment instanceOf BookmarkFragment) { ...... rest of your code
thay vì sử dụng if (activeFragment.equals(BookmarkFragment.class.getSimpleName())) { ......