Ở bài hôm trước chúng ta đã tạo một ứng dụng hiện thị danh sách các sản phẩm lên ListView và biết thêm các thao tác thêm, xóa, sửa trên ListView.
Hôm nay chúng ta tiếp tục sử dụng lại Project đó, nhưng các sản phẩm chúng ta sẽ được lưu ở dạng Database sử dụng SQLite.(Nhấn vào tên class để xem toàn bộ source class đó)
1. Ta thêm thuộc tính private long ProductID; vào trong class Product
2. Tạo thêm package com.androidtmc.sales.repository. Ta tạo thêm 2 class để xử lý Database SQLite
- DatabaseHelper
- ProductRepository
Giải thích:
− Class SQLiteOpenHelper giúp chúng ta định nghĩa tên database (phải truyền tên database cho constructor)
− SQLiteOpenHelper cung cấp hàm ảo onCreate để thực hiện các lệnh tạo bảng lần đầu tiên và hàm ảo onUpgrade để thi hành các lệnh bổ sung, chỉnh sửa bảng nếuchúng ta cần thay đổi. Điều này được thực hiện thông qua biến version:
• Lần đầu chạy với version là 1, SQLite gọi hàm onCreate để thi hành cáclệnh tạo bảng ban đầu. Database được ghi nhận là ở version 1.
• Nếu version được sửa lại là 2, SQLite gọi hàm onUpgrade với oldVersion = 1 và newVersion = 2. Lúc đó ta có thể thi hành lệnh chỉnh sửa bảng hoặc bổ sung bảng mới. Database được ghi nhận là ở version 2.
• Nếu version được sửa tiếp là 3, SQLite gọi hàm onUpgrade với oldVersion = 2 và newVersion = 3. Lúc đó ta có thể thi hành lệnh chỉnh sửa tiếp. Sau đó database được ghi nhận là ở version 3.
• Nếu ở các lần chạy tiếp theo version không được sửa thì SQLiteOpenHelper sẽ không gọi làm onCreate cũng như onUpgrade. Cấutrúc database vẫn giữ nguyên.
Hôm nay chúng ta tiếp tục sử dụng lại Project đó, nhưng các sản phẩm chúng ta sẽ được lưu ở dạng Database sử dụng SQLite.(Nhấn vào tên class để xem toàn bộ source class đó)
1. Ta thêm thuộc tính private long ProductID; vào trong class Product
2. Tạo thêm package com.androidtmc.sales.repository. Ta tạo thêm 2 class để xử lý Database SQLite
- DatabaseHelper
- ProductRepository
package com.androidtmc.sales.repository; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; public class DatabaseHelper extends SQLiteOpenHelper { static final String DB_NAME = "Sales"; public DatabaseHelper(Context context) { super(context, DB_NAME, null, 1); // 1: version } @Override public void onCreate(SQLiteDatabase db) { String sql = ProductRepository.getCreateTableSQL(); db.execSQL(sql); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }
Giải thích:
− Class SQLiteOpenHelper giúp chúng ta định nghĩa tên database (phải truyền tên database cho constructor)
− SQLiteOpenHelper cung cấp hàm ảo onCreate để thực hiện các lệnh tạo bảng lần đầu tiên và hàm ảo onUpgrade để thi hành các lệnh bổ sung, chỉnh sửa bảng nếuchúng ta cần thay đổi. Điều này được thực hiện thông qua biến version:
• Lần đầu chạy với version là 1, SQLite gọi hàm onCreate để thi hành cáclệnh tạo bảng ban đầu. Database được ghi nhận là ở version 1.
• Nếu version được sửa lại là 2, SQLite gọi hàm onUpgrade với oldVersion = 1 và newVersion = 2. Lúc đó ta có thể thi hành lệnh chỉnh sửa bảng hoặc bổ sung bảng mới. Database được ghi nhận là ở version 2.
• Nếu version được sửa tiếp là 3, SQLite gọi hàm onUpgrade với oldVersion = 2 và newVersion = 3. Lúc đó ta có thể thi hành lệnh chỉnh sửa tiếp. Sau đó database được ghi nhận là ở version 3.
• Nếu ở các lần chạy tiếp theo version không được sửa thì SQLiteOpenHelper sẽ không gọi làm onCreate cũng như onUpgrade. Cấutrúc database vẫn giữ nguyên.
Bây giờ, để thực hiện các thao tác thêm, xóa, sửa, truy xuất dữ liệu trên bảng Product, tạo class ProductRepository cũng trong package com.androidtmc.repository:
package com.androidtmc.sales.repository; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import com.androidtmc.sales.models.Product; import java.util.ArrayList; /** * Created by minhc_000 on 13/08/2015. */ public class ProductRepository { static final String TAB_PRODUCT = "Product"; static final String COL_PRODUCTID = "ProductID"; static final String COL_PRODUCTNAME = "ProductName"; static final String COL_UNIT = "Unit"; static final String COL_PRICE ="Price"; public static String getCreateTableSQL() { String sql = "CREATE TABLE " + TAB_PRODUCT + "(" + COL_PRODUCTID + " integer primary key autoincrement, " + COL_PRODUCTNAME + " text, " + COL_UNIT + " text, " + COL_PRICE + " real)"; return sql; } private DatabaseHelper dbhelper; public ProductRepository(Context context) { dbhelper = new DatabaseHelper(context); } private ContentValues MakeProductContentValues(Product p) { ContentValues cv = new ContentValues(); cv.put(COL_PRODUCTNAME, p.getProductName()); cv.put(COL_UNIT, p.getUnit()); cv.put(COL_PRICE, p.getPrice()); return cv; } public void insertProduct(Product p) { ContentValues cv = MakeProductContentValues(p); SQLiteDatabase db = dbhelper.getWritableDatabase(); long id = db.insert(TAB_PRODUCT, null, cv); if (id!= -1) p.setProductID(id); } public void updateProduct(Product p) { ContentValues cv = MakeProductContentValues(p); SQLiteDatabase db = dbhelper.getWritableDatabase(); db.update(TAB_PRODUCT, cv, COL_PRODUCTID + "=?", new String[] { String.valueOf(p.getProductID()) }); }public void deleteProduct(long id) { SQLiteDatabase db = dbhelper.getWritableDatabase(); db.delete(TAB_PRODUCT,COL_PRODUCTID + " = " + id,null); } public ArrayList<Product> getAllProduct() { ArrayList<Product> products = new ArrayList<Product>(); SQLiteDatabase db = dbhelper.getReadableDatabase(); String sql = "SELECT * FROM " + TAB_PRODUCT; Cursor cursor = db.rawQuery(sql, null); int indexProductID = cursor.getColumnIndex(COL_PRODUCTID); int indexProductName = cursor.getColumnIndex(COL_PRODUCTNAME); int indexUnit = cursor.getColumnIndex(COL_UNIT); int indexPrice = cursor.getColumnIndex(COL_PRICE); if (cursor.moveToFirst()) { while (!cursor.isAfterLast()) { Product p = new Product(); p.setProductID(cursor.getLong(indexProductID)); p.setProductName(cursor.getString(indexProductName)); p.setUnit(cursor.getString(indexUnit)); p.setPrice(cursor.getDouble(indexPrice)); products.add(p); cursor.moveToNext(); } } cursor.close(); return products; } }
Giải thích:
− Các hằng số TAB_PRODUCT, COL_PRODUCTID, COL_PRODUCTNAME,
COL_UNIT, COL_PRICE xác định tên bảng và tên các thuộc tính.
− Hàm getCreateTableSQL(): tạo câu lệnh tạo bảng dùng cho DatabaseHelper. Câu lệnh
tạo bảng này có giá trị như sau:
CREATE Product (
ProductID integer primary key autoincrement,
ProductName text,
Unit text,
Price real)
primary key nhằm xác định khóa chính, autoincrement nhắm xác định ProductID là biến tự động tăng khi thêm record vào cơ sở dữ liệu.
− Khi thêm hay sửa record, Android yêu cầu cung cấp giá trị của các cột thông qua biến ContentValues. Ta sử dụng hàm MakeProductContentValues để chuyển giá trị từ đối
tượng Product sang ContentValues.
− Hàm insertProduct: thêm sản phẩm vào database. Ta gọi hàm insert của SQLiteDatabase. Hàm insert này cũng trả về giá trị của cột ProductID (tự tăng), ta cập
nhật ngược lại vào đối tượng Product.
− Hàm updateProduct: sửa thông tin một sản phẩm. Ta gọi hàm update của SQLiteDatabase, sử dụng ProductID của sản phẩm để xác định sản phẩm nào cần update.
− Hàm getAllProduct: Truy xuất tất cả các sản phẩm có trong database và chuyển thành ArrayList
cursor để truy xuất kết quả. Cursor có các phương thức moveToFirst(), moveToNext() và IsAfterLast()
Cuối cùng để sử dụng ProductRepository để truy xuất cơ sở dữ liệu, ta sửa hàm OnCreate trong MainActivity lại như sau:
lv = (ListView) findViewById(R.id.lvProducts); //Khởi tạo các sản phẩm //lấy sản phẩm từ database repo = new ProductRepository(this); if(repo.getAllProduct().size()>0)//nếu đã có //lưu lấy ra mảng SaleManager.get().setProducts(repo.getAllProduct()); else{//nếu chưa có trong database //dùng hàm tạo sẳn để test saleManager.generateProducts(); } adapter = new ProductAdapter(this,SaleManager.get().getProducts());//khởi tạo adapter lv.setAdapter(adapter);//hiển lên listview
Ta sửa lại class OKClickListener trong class ProductActivity để lưu sản phẩm mới vào Database khi click OK
class OKClickListener implements View.OnClickListener { @Override public void onClick(View v) { //lấy dữ liệu từ layout để cập nhật lại các sản phẩm trong mảng product.setProductName(txtProductName.getText().toString()); product.setUnit(txtUnit.getText().toString()); String s = txtPrice.getText().toString(); s = s.replace(",", ""); double price = Double.parseDouble(s); product.setPrice(price); //nếu position = -1 ta thực hiện chứ năng thêm sp mới vào mảng if (position == -1){ SaleManager saleManager = new SaleManager(); SaleManager.get().getProducts().add(product); ProductRepository repo = new ProductRepository(ProductActivity.this); repo.insertProduct(product);// lưu vào database } Intent returnIntent = new Intent(); setResult(Activity.RESULT_OK, returnIntent); finish(); } }
Để xóa sản phẩm trong Database ta sửa lại class OnItemClickRemve trong MainActivity
private class ItemLongClickRemove implements AdapterView.OnItemLongClickListener { @Override public boolean onItemLongClick(AdapterView<?> parent, View view, final int position, long id) { AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(MainActivity.this); alertDialogBuilder.setMessage("Bán có muốn xóa sản phẩm này!"); alertDialogBuilder.setPositiveButton("Có", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // xóa sp đang nhấn giữ Product pro = (Product)SaleManager.get().getProducts().get(position); //xóa sản phẩm đang chọn trong Database repo.deleteProduct(pro.getProductID()); SaleManager.get().getProducts().remove(position); //cập nhật lại listview adapter.notifyDataSetChanged(); } }); alertDialogBuilder.setNegativeButton("Không", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { //không làm gì } }); alertDialogBuilder.show(); return true; } }
Bây giờ chúng ta có thể chạy ứng dụng và kiểm tra

a up code lên được không ạ? tại em thấy có một số chỗ bị lỗi và thiếu a
Trả lờiXóađây bạn :)
XóaĐây bạn
Xóahttps://github.com/cuongloveit/Sales
ko chạy được @
XóaCho mình hỏi với ạ? Làm sao có thể copy dữ liệu từ layout cũ sang 1 layout mới chỉ khác hình nhưng nội dung hay button thì vẫn y nguyên vậy ạ
Trả lờiXóa