Vậy là chúng ta đã đi qua 3 cách lưu trữ trong lập trình Android rồi đúng không nào, nào là : Shared Preferences, Internal Storage, External Storage, còn hôm nay là bài cuối cùng chúng ta sẽ đi tìm hiểu về cách lưu trữ cuối cùng đó là lưu vào database.
Đây là bài rất quan trọng và cần thiết phải biết đến đó các bạn bởi vì nó là kiến thức bắt buộc, đi làm mà không biết thằng này thì xin việc cũng hơi khó rồi đó.
Bài này mình dự kiến sẽ có đến hơn 1 video để hướng dẫn đó các bạn bởi vì kiến thức về Database là khá nhiều trong cụm từ “CRUD” :
- C: Create
- R: Read
- U: Update
- D: Delete
Nghe thấy là đã nhiều cái để học rồi đúng không các bạn, nếu học xong bài này thì chúng ta có thể làm được những dự án về lưu dữ liệu rồi đó ví dụ ứng dung: quản lí chi tiêu… rồi đó.
Vậy trong lập trình Android thì dùng hệ cơ sở dữ liệu nào để lưu trữ thì mình xin nói luôn đó là SQLite nhé các bạn, đây là cơ sở dữ liệu mà Androdi tích hợp sẵn và bạn rất dễ sử dụng chứ không khó khăn như việc sử dụng Mysql, SqlServer…Xong bài này mình sẽ làm một ứng dụng gì đó thật kinh điển ha 😛
Thôi! Chúng ta bay vào tìm hiểu nó ngay cho nóng nào!
Nội dung
SQLite trong android là gì?
Là cơ sở dữ liệu nhỏ tương tự như MySQL, SQL server… với đặc điểm là nhỏ , gọn và nhẹ.Trong lập trình android thì SQLite sẽ được lưu trong ổ đĩa của thiết bị chứ không phải lưu trên server hay bất kì nơi nào khác.
Việc truy vấn trong SQLite sẽ tương tự như các hệ cơ sở dữ liệu khác nên bạn sẽ không phải gặp khó khăn gì khi sử dụng và bạn cũng chẳng cần user , mật khẩu khi truy cập vào trong database gì cả.
Tại sao dùng SQLite để lưu trữ
Tiêu đề trên có vẽ hơi “ngu người” 1 tí nhỉ :D, đơn giản là nó dùng để lưu trữ thôi cơ mà nó so với 3 cách chúng ta đã học ở bài trước thì sao nhỉ? Nghe đến Database là biết nó thường lưu những gì rồi đúng không he, SQLite sẽ dùng để lưu các đối tượng, model dưới dạng bảng và sau đó là truy xuất để lấy ra một cách nhanh chóng.
Với các bài trước ta học thì việc lưu trữ một đối tượng khá là khó, với Shared Preferences thì bạn phải chuyển nó sang String rồi sau đó dưới dạng Key – Value, còn với kiểu lưu External hay Internal thì lại khá cực.
Bây giờ có SQLite sẽ giải quyết cho bạn vấn đề này, nó được sử dụng khi nào các bạn biết không?
SQLite được sử dụng khi nào?
Nó được sử dụng khi yêu cầu bài toán đưa ra là hãy lưu những dữ liệu lớn ở dạng Object, dạng text… xuống thiết bị để có thể lấy ra bất kỳ khi nào.Dữ liệu lớn ở đây không phải là nặng đâu nhé các bạn mà nó nhiều ấy vì dữ kiệu dạng text, object lưu xuống cũng khá nhẹ cho dù nó nhiều.
Mình sẽ đưa ra những ví dụ kinh điển bạn sẽ hình dung ra ngay như sau:
Ex1:
Ứng dụng ZingMp3 tiếp đi ha, bạn sẽ có chức năng là lưu bài hát vào danh sách yêu thích đúng không? Một bài hát thường sẽ có các thuộc tính như: tên, url, lyric, ca sĩ… Đây là một Oject đúng không nào? Ứng dụng sẽ lưu danh sách bài hát yêu thích vào database để sau này truy xuất ta hiển thị thôi.
Ex2:
Ứng dụng có chức năng lưu trữ lịch sử tìm kiếm thì cũng có thể sử dụng sql để lưu lại danh sách này.
Ex3:
Ứng dụng báo thức có thể sử dụng sqlite để lưu danh sách các báo thức đã cài đặt.
Tuy nhiên theo mình thấy thì SQLite lưu trữ dữ liệu không được lớn như những hệ cơ sở dữ liệu khác vì nó tích hợp trong thiết bị android mà, nếu quá nặng thì ứng dụng đó sẽ rất chậm.Nói gì nói thì nó chỉ đáp ứng với khoảng dữ liệu nhỏ vài ngàn dòng gì đó thôi chứ lớn quá thì nó sẽ không dùng SQLite để lưu đâu các bạn.
Cách sử dụng SQLite trong lập trình Android
Tương tự như các hệ quản trị cơ sở dữ liệu khác thì khi thao tác với Database thì bạn sẽ có những hành động cổ điển đó là CRUD mà mình đã nói ở trên rồi, ở loạt này chúng ta cũng sẽ tìm hiểu những cái chính đó thôi chứ không đi quá sâu được vì còn rất nhiều bài ở đằng sau nữa.
Bài toán mình đưa ra là lưu lại danh sách Student vào trong SQLite, chính vì thế mình sẽ đi phân tích tất cả những thuộc tính mà chúng ta sẽ phải khởi tạo cho lớp Student từ đó đi xây dựng Database cho dữ liệu này.
Dự kiến class model Student.java sẽ có bao gồm những thuộc tính như sau: id, name, number, email, address.
Vậy class Student.java sẽ có những thuộc tính và các phương thức getter, setter sau:
package cheng.com.bai4sqlite.model; /** * Created by chien on 11/13/16. */ public class Student { private int id; private String name; private String number; private String email; private String address; public Student() { } public Student(String name, String number, String email, String address) { this.name = name; this.number = number; this.email = email; this.address = address; } public Student(int id, String name, String number, String email, String address) { this.id = id; this.name = name; this.number = number; this.email = email; this.address = address; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "Name:" +getName() + " \n" +"Number: "+getNumber() +"\n" + "Email: "+getEmail() +"\n" + "Address:" +getAddress(); } }
Vậy bản mô phỏng các thuộc tính trong Table Student khi lưu vào database sẽ như sau:
Field | Type | Key |
---|---|---|
id | int | primary key |
name | Text | |
number | Text | |
Text | ||
address | Text |
Vậy quy trình chúng ta sẽ làm làm gì nhỉ? Khởi tạo một database có tên là “student_list“, một table tên là “student” và sau đó là có câu truy vấn CRUD.
Đây là class DBManager.java , ở đây mình đã khởi tạo một SQLite tên là student_list và một table là student, và sau đó là tất cả các phương thức truy vấn và bên dưới mình sẽ giải thích cụ thể cho các bạn hiểu nhé.
package com.cheng.sqlite.database; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.util.Log; import android.widget.Toast; import com.cheng.sqlite.model.Student; import java.util.ArrayList; import java.util.List; /** * Created by chien on 11/13/16. */ public class DBManager extends SQLiteOpenHelper { public static final String DATABASE_NAME ="student_list"; private static final String TABLE_NAME ="student"; private static final String ID ="id"; private static final String NAME ="name"; private static final String EMAIL ="email"; private static final String NUMBER ="number"; private static final String ADDRESS ="address"; private Context context; public DBManager(Context context) { super(context, DATABASE_NAME,null, 1); Log.d("DBManager", "DBManager: "); this.context = context; } @Override public void onCreate(SQLiteDatabase db) { String sqlQuery = "CREATE TABLE "+TABLE_NAME +" (" + ID +" integer primary key, "+ NAME + " TEXT, "+ EMAIL +" TEXT, "+ NUMBER+" TEXT," + ADDRESS +" TEXT)"; db.execSQL(sqlQuery); Toast.makeText(context, "Create successfylly", Toast.LENGTH_SHORT).show(); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("DROP TABLE IF EXISTS "+TABLE_NAME); onCreate(db); Toast.makeText(context, "Drop successfylly", Toast.LENGTH_SHORT).show(); } //Add new a student public void addStudent(Student student){ SQLiteDatabase db = this.getWritableDatabase(); ContentValues values = new ContentValues(); values.put(NAME, student.getName()); values.put(NUMBER, student.getNumber()); values.put(EMAIL, student.getEmail()); values.put(ADDRESS, student.getAddress()); //Neu de null thi khi value bang null thi loi db.insert(TABLE_NAME,null,values); db.close(); } /* Select a student by ID */ public Student getSdtudentById(int id){ SQLiteDatabase db = this.getReadableDatabase(); Cursor cursor = db.query(TABLE_NAME, new String[] { ID, NAME, EMAIL,NUMBER,ADDRESS }, ID + "=?", new String[] { String.valueOf(id) }, null, null, null, null); if (cursor != null) cursor.moveToFirst(); Student student = new Student(cursor.getString(1),cursor.getString(2),cursor.getString(3),cursor.getString(4)); cursor.close(); db.close(); return student; } /* Update name of student */ public int Update(Student student){ SQLiteDatabase db = this.getWritableDatabase(); ContentValues values = new ContentValues(); values.put(NAME,student.getName()); return db.update(TABLE_NAME,values,ID +"=?",new String[] { String.valueOf(student.getId())}); } /* Getting All Student */ public List<Student> getAllStudent() { List<Student> listStudent = new ArrayList<Student>(); // Select All Query String selectQuery = "SELECT * FROM " + TABLE_NAME; SQLiteDatabase db = this.getWritableDatabase(); Cursor cursor = db.rawQuery(selectQuery, null); if (cursor.moveToFirst()) { do { Student student = new Student(); student.setId(cursor.getInt(0)); student.setName(cursor.getString(1)); student.setEmail(cursor.getString(2)); student.setNumber(cursor.getString(3)); student.setAddress(cursor.getString(4)); listStudent.add(student); } while (cursor.moveToNext()); } cursor.close(); db.close(); return listStudent; } /* Delete a student by ID */ public void deleteStudent(Student student) { SQLiteDatabase db = this.getWritableDatabase(); db.delete(TABLE_NAME, ID + " = ?", new String[] { String.valueOf(student.getId()) }); db.close(); } /* Get Count Student in Table Student */ public int getStudentsCount() { String countQuery = "SELECT * FROM " + TABLE_NAME; SQLiteDatabase db = this.getReadableDatabase(); Cursor cursor = db.rawQuery(countQuery, null); cursor.close(); // return count return cursor.getCount(); } }
Đây là class chúng ta sẽ thao tác với SQLite nhé các bạn, bạn muốn làm gì chỉ cần khởi tạo đối tượng DBManager rồi gọi phương thức tương ứng ra thôi.Tuy nhìn thấy nó nhiều vậy thôi chứ thực chất nó không có gì ghê gớm cả, mình sẽ giải thích từng phương thức cho các bạn hiểu ngay thôi.
Để sử dụng được SQLite trong Android thì bạn phải tạo một Class implement class SQLiteOpenHelper, đây là điều bắt buộc nhé và khi implement class này thì bạn phải ghi đè các phương thức onCreate() và phương thức onUpgrade() và phải khởi tạo constructor cho class đó.Ở ví dụng trên là mình tạo class DBManager và implement SQLiteOpenHelper và các phương thức mà mình phải ghi đè đó là:
@Override public void onCreate(SQLiteDatabase db) { String sqlQuery = "CREATE TABLE "+TABLE_NAME +" (" + ID +" integer primary key, "+ NAME + " TEXT, "+ EMAIL +" TEXT, "+ NUMBER+" TEXT," + ADDRESS +" TEXT)"; db.execSQL(sqlQuery); Toast.makeText(context, "Create successfylly", Toast.LENGTH_SHORT).show(); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("DROP TABLE IF EXISTS "+TABLE_NAME); onCreate(db); Toast.makeText(context, "Drop successfylly", Toast.LENGTH_SHORT).show(); }
Và constructor:
public DBManager(Context context) { super(context, DATABASE_NAME,null, 1); this.context = context; }
Tại sao phải ghi đè các phương thức trên nhỉ? Như chúng ta đã biết thì một quá trình lưu một Student xuống database thì phải trải qua các bước là:
- Tạo database
- Tạo table
- Add student
Vây ở trên constructer DBManager() chính là quá trình tạo database, còn hàm onCreate() chính là quá trình tạo table.Còn thằng OnUpdate() sẽ được gọi khi có một sự thay đổi liên quan đến cấu trúc dữ liệu như thêm 1 table, xoá table…
Vậy nó được chạy khi nào, bây giờ nếu như ban gọi như sau trong MainActivity:
DBManager dbManager = new DBManager(this);
Thì sẽ chẳng có chuyện gì xảy ra cả đâu nhé, 2 phương thức trên chẳng cái nào chạy cả đâu và nó sẽ chạy khi các bạn thực hiện các lệnh truy vấn như thêm, tìm kiếm, sửa… và sau đó nó sẽ chẳng chạy vào nữa nếu như nó đã được gọi 1 lần.
Dưới đây là các phức mà chúng ta sẽ viết tuỳ theo mục đích của mình, cùng đi phân tích nhé:
Add – Thêm mới
//Add new a student public void addStudent(Student student){ SQLiteDatabase db = this.getWritableDatabase(); ContentValues values = new ContentValues(); values.put(NAME, student.getName()); values.put(NUMBER, student.getNumber()); values.put(EMAIL, student.getEmail()); values.put(ADDRESS, student.getAddress()); //Neu de null thi khi value bang null thi loi db.insert(TABLE_NAME,null,values); db.close(); }
Phương thức trên dùng để thêm một Student vào trong sqlite, đầu tiên nó sẽ gọi phương thức getWritableDatabase() để mở database lên để đọc và ghi, nếu như ở đây database chưa được tạo thì phương onCreate() sẽ được gọi rồi sau đó mới thực hiện mở database lên.
Sau đó bạn tạo một đối tượng thuộc ContentValues để có thể put các giá trị vào trong các column, thằng này kiểu tương tự như Editor mà chúng ta đã học ở bài Shared Preferences ấy các bạn.
values.put(NAME, student.getName());
Ở trên mình đang đưa vào column “name” với giá trị là tên của student (student.getName()),
Sau khi đã put hết giá trị rồi bạn gọi phương thức insert() và truyền vào các params là xong.Nhớ là nên đóng database lại mỗi lần mở nó ra nhé các bạn!
Read – Đọc
Sau khi đã lưu xuống được một danh sách student thì chúng ta tiến hành đọc lên thôi:
public Student getSdtudentById(int id){ SQLiteDatabase db = this.getReadableDatabase(); Cursor cursor = db.query(TABLE_NAME, new String[] { ID, NAME, EMAIL,NUMBER,ADDRESS }, ID + "=?", new String[] { String.valueOf(id) }, null, null, null, null); // Cursor cursor; // cursor = db.rawQuery("SELECT * FROM "+TABLE_NAME +" WHERE id = '1'",null); if (cursor != null) cursor.moveToFirst(); Student student = new Student(cursor.getString(1),cursor.getString(2),cursor.getString(3),cursor.getString(4)); cursor.close(); db.close(); return student; }
Ở đây chúng ta sẽ get thông tin một sinh viên ra theo id nhé các bạn, bạn sẽ thực hiện các câu query quen thuộc rồi lấy ra thôi.
Lấy toàn bộ danh sách Student thì làm như sau:
public List<Student> getAllStudent() { List<Student> listStudent = new ArrayList<Student>(); // Select All Query String selectQuery = "SELECT * FROM " + TABLE_NAME; SQLiteDatabase db = this.getWritableDatabase(); Cursor cursor = db.rawQuery(selectQuery, null); if (cursor.moveToFirst()) { do { Student student = new Student(); student.setId(cursor.getInt(0)); student.setName(cursor.getString(1)); student.setEmail(cursor.getString(2)); student.setNumber(cursor.getString(3)); student.setAddress(cursor.getString(4)); listStudent.add(student); } while (cursor.moveToNext()); } cursor.close(); db.close(); return listStudent; }
Update – Cập nhật
public int Update(Student student){ SQLiteDatabase db = this.getWritableDatabase(); ContentValues values = new ContentValues(); values.put(NAME,student.getName()); return db.update(TABLE_NAME,values,ID +"=?",new String[] { String.valueOf(student.getId())}); }
Ở trên mình đang thay đổi tên của một Student với điệu kiện đang xét theo id, cái này nếu bạn không hiểu mình sẽ giải thích kĩ ở trong video nhé.
Delete – Xoá
public void deleteStudent(Student student) { SQLiteDatabase db = this.getWritableDatabase(); db.delete(TABLE_NAME, ID + " = ?", new String[] { String.valueOf(student.getId()) }); db.close(); }
Câu lệnh trên để xoá đi một Student khi theo điệu kiện là id luôn.
Lấy ra tổng số dòng trong Table
public int getStudentsCount() { String countQuery = "SELECT * FROM " + TABLE_NAME; SQLiteDatabase db = this.getReadableDatabase(); Cursor cursor = db.rawQuery(countQuery, null); cursor.close(); // return count return cursor.getCount(); }
Vẫn là những câu truy vấn cổ điên thôi đúng không nào? Nói chung cũng không có gì khó cả.Mình sẽ nói chi tiết hơn trong video bên dưới và kèm theo mã nguồn của dự án các bạn xem nếu có thắc mắc hay ý kiến gì cứ để lại comment nhé.
Video hướng dẫn SQLite
Download Source Code
[sociallocker id=”635″] [/sociallocker]
Tiếp theo
Chúc các bạn học tập vui vẽ!
anh ơi , làm về Fragment đi ạ 🙂
cảm ơn ad 😀 bài giảng của ad rất dễ hiểu ạ 😀
Like .Bạn viết rất dễ hiểu . đang theo dõi bài viết của bạn .
mong ra bài thường xuyên hơn
Bạn ơi, cho tôi hỏi, nếu chương trình đang chạy mà thoát ra, rồi hôm sau mở lại thì khi update dữ liệu mới thì dữ liệu cũ có mất không? Vì tôi thấy mỗi khi chạy, chương trình tạo ra 1 database mới
Dữ liệu này tạo sẽ nằm trong app rồi bạn, chỉ có xoá app đi hoặc clear data thì nó mới bị mất thôi.Mỗi lần chạy sao lại tạo database mới đc bạn, chỉ khi bạn xoá rồi nó mới tạo mới lại thôi chứ.
MainActivity:
dbManager.addStudent(student);
DBManager:
public void addStudent(Student student){
SQLiteDatabase db = this.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(NAME,student.getmName());
values.put(PHONE_NUMBER,student.getmNumberPhone());
values.put(ADDRESS,student.getmAddress());
values.put(EMAIL,student.getmEmail());
db.insert(TABLE_NAME,null,values);
db.close();
Log.d(TAG,”AddStudent Successfuly”);
}
sao khi chạy nó lại báo lỗi ở chổ này zạ bạn
Cậu gửi mình log lỗi để mình xem coi nguyên nhân do đâu vậy bạn nhé…
Mình muốn tạo nhiều bảng trong một csdl thì làm sao hả ad?
Anh dạy rất chi tiết và dễ hiểu. dễ nhớ nhất là bài viết. Khi đọc xong bài viết, rồi coi video thực hành theo thật là dễ hiểu. Cám ơn anh!
Mong anh sớm có bài nói về HTTPs connection hay Request API
Chào bạn, rất hóng các bài tiếp theo của bạn, bài giảng rất hay và dễ hiểu
cho e hỏi, e làm khi chọn vào 1 Student trong listView nó sẽ show 1 cái dialog hỏi có muốn xóa hay ko, hàm xóa a đã viết sẵn rồi, vậy cho e hỏi, làm sao để nó lấy được cái student mình đang chọn để mình đưa vào hàm nhỉ?
Có cách nào nữa để xóa theo id mà các dòng row của em k có thuộc tính id e chỉ để id chạy ngầm và tự tăng,,vậy làm sao để em có thấy lấy ra id của 1 view để xóa ạ
thank ad viết bài rất dễ hiểu. web đẹp
Bạn ơi cho mình hỏi, ứng dụng messenger có sẳn trên điện thoại thì dùng cách nào lưu lại dữ liệu là tốt nhất? Lúc đầu mình nghĩ là nên dùng SharedPreferences vì khi mở ứng dụng lên, mọi tin nhắn vẫn còn đó. Internal Storage và SQLite mình thấy vẫn ổn, nhưng mình vẫn muốn biết là cách nào sẽ tốt hơn hoặc là có cách nào khác tốt hơn 3 cách trên không?
Lấy theo id trong list view, id bắt đầu từ 0