[Android căn bản] Bài 14: Sử dụng SQLite trong Android.

[Android căn bản] Bài 14: Sử dụng SQLite trong Android.

Chào các bạn chúng ta lại gặp nhau trong Series Android truyền kì.Trong các bài trước tôi đã giới thiệu tới các bạn các lữu trữ dữ liệu trên Android nhưng các bạn thấy rằng cách lưu trữ này chỉ phù hợp để lưu trữ những dữ liệu nhỏ lẻ và nó sẽ khó truy xuất và quản lí khi dữ liệu lớn lên. Vậy ta có giải pháp nào để lưu trữ những dữ liệu lớn và phúc tạp không. Xin thưa là có như các bạn thấy trên các phần mềm máy tính hay web người ta sẽ sử dụng một hệ quản trị cơ sở dữ liệu nào đó để quản lí những dữ liệu phức tạp của phần mềm và hệ quản trị này cũng giúp bảo trì dữ liệu dễ dàng, vậy trên mobile có hệ quản trị nào như thế không? Xin thưa là có đó là SQlite ngôi sao sáng của chúng ta.

SQLite là gì.

Như các bạn thấy trên máy tính có một phần mềm quản trị cơ sở dữ liệu nhỏ là Access đúng không nào nó sẽ tạo ta một file cơ sở dữ liệu Access trên máy cục bổ và quản lí các dữ liệu được lưu trong file đó và SQLite cũng tương tự nó được cài đặt sẵn đi kèm với Android giống như Windows Phone thì có SQL Compact đi kèm vậy. Nó sẽ quản tạo ra một file cơ sở dữ liệu có phần mở rộng là .db được lưu trong bộ nhớ trong thuộc ứng dụng tức là nếu gỡ ứng dụng thì nó cũng đi theo luôn.

Cách sử dụng SQLite.

Thông thường trong Android đã được cài đặt sẵn thư viện để làm việc với SQLite nhưng thư viện này làm việc cũng chưa được tối ưu lắm và khi truy vấn dữ liệu ta vẫn sẽ phải viết những câu lệnh truy vấn thủ công. Với cơ sở dữ liệu nhỏ và đơn giản thì OK dùng nó cũng OK nhưng với những cơ sở dữ liệu lớn và phức tạp thì thật là cực hình nếu bạn dùng cách này thì chắc bạn hẳn có máu M trong người rồi :D. Và tôi không có máu M cũng như thích sự tiện dụng và hạn chế lỗi thì tôi sẽ dùng thư viện GreenDao. GreenDao là gì thì xin mời các bạn hỏi sư phụ Google thầy ấy sẽ cung cấp rất nhiều thông tin về anh chàng này cho bạn.

Giờ chúng ta vô ví dụ nhé.

Ví dụ: Danh sách bạn bè.

Đầu tiên ta thêm thư viện plugin green dao vào project

Mở file gradle(project) ra thêm dòng classpath 'org.greenrobot:greendao-gradle-plugin:3.2.1' vô.

Rồi mở file gradle(Module) thêm ba dòng sau:

apply plugin: 'org.greenrobot.greendao' // dòng cần thêm vô để áp dụng plugin greendao rất quan trọng đấy nhá
dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.0.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.1'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
    implementation 'com.android.support:design:27.0.0'
    compile 'org.greenrobot:greendao:3.2.0'// Thư viện green dao
    compile 'de.greenrobot:greendao-generator:2.1.0'// Thư viện tự khởi tạo thuộc tính green dao
    implementation 'com.android.support:recyclerview-v7:27.0.0'
}

Tạo layout cho dialog thêm bạn bè

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >
<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textSize="20dp"
    android:text="Họ và tên"

    />
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/Inputname"
        />
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/save"
        android:text="Lưu"
        android:textAlignment="center"
        android:textSize="18dp"
        android:textStyle="bold"
        />
</LinearLayout>

Tạo layout cho item

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    >
<TextView
    android:layout_width="300dp"
    android:layout_height="wrap_content"
    android:id="@+id/Name"
    android:text="Name"
    />
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/menu"
        android:src="@drawable/ic_menu_black_24dp"
        />
</LinearLayout>

Tạo menu cho nút menu. Nhấn chuột phải vào resource > New > Android resource directory > chọn type là menu.

Rồi lại nhấn new vào thư mục menu chọn new> Menu resource file.

File menu sẽ như sau:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
    android:title="Xóa"
    android:id="@+id/xoa"
    />
    <item
        android:title="Sửa"
        android:id="@+id/sua"
        />
</menu>

Tạo đối tượng Friend

package com.chamcong.akinosora.sqlite;

import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Generated;

/**
 * Created by Akinosora on 09/11/2017.
 */
@Entity // Từ khóa ra lệnh tạo bảng
public class Friend {
    @org.greenrobot.greendao.annotation.Id(autoincrement = true)// Từ khóa ra lệnh tạo trường Id tự tăng
    private Long Id;
    private String Name;

    @Generated(hash = 530982555)
    public Friend(Long Id, String Name) {
        this.Id = Id;
        this.Name = Name;
    }

    public Friend(String name) {
        Name = name;
    }

    @Generated(hash = 287143722)
    public Friend() {
    }

    public Long getId() {
        return Id;
    }

    public void setId(Long id) {
        Id = id;
    }

    public String getName() {
        return Name;
    }

    public void setName(String name) {
        Name = name;
    }
}

Tạo lớp SqliteOpenHelper

package com.chamcong.akinosora.sqlite;

import android.content.Context;

import org.greenrobot.greendao.database.Database;

/**
 * Created by Akinosora on 09/11/2017.
 */

public class SqliteOpenHelper extends DaoMaster.DevOpenHelper {
    public SqliteOpenHelper(Context context, String name) {
        super(context, name);
    }

    @Override
    public void onUpgrade(Database db, int oldVersion, int newVersion) {
        super.onUpgrade(db, oldVersion, newVersion);
    }
}

Tạo file LocalDatabaseHelper

package com.chamcong.akinosora.sqlite;

import android.content.Context;

import org.greenrobot.greendao.database.Database;

import java.util.InputMismatchException;

/**
 * Created by Akinosora on 09/11/2017.
 */

public class LocalDatabaseHelper {
    private static LocalDatabaseHelper localDatabaseHelper;

    private DaoSession daoSession;
    private Database database;


    private LocalDatabaseHelper(Context context) {
        DaoMaster.DevOpenHelper helper =
                new SqliteOpenHelper(context.getApplicationContext(), "friend-db");
        database = helper.getWritableDb();// Khởi tạo các bảng của database
        daoSession = new DaoMaster(database).newSession();// khởi tạo phiên làm việc với database
    }
    Kiểm tra xem đã khởi tạo đối tượng LocalDatabaseHelper hay chưa
    public static LocalDatabaseHelper getInstance(Context context) {
        if (localDatabaseHelper == null) {
            throw new InputMismatchException("Please setting LocalDatabaseHelper.init() "
                    + "in onCreate from Application class");
        }
        return localDatabaseHelper;
    }
    Khởi tạo đối tượng LocalDatabaseHelper
    public static void init(Context context) {
        if (localDatabaseHelper == null) {
            localDatabaseHelper = new LocalDatabaseHelper(context);
        }
    }

    public DaoSession getDaoSession() {
        return daoSession;
    }

    public Database getDatabase() {
        return database;
    }
}

Tạo file Controller xử lý dữ liệu.

package com.chamcong.akinosora.sqlite;

import android.content.Context;

import java.util.List;

/**
 * Created by Akinosora on 09/11/2017.
 */

public class Controllers {
    private Context mContext;
    private FriendDao friendDao;


    public Controllers(Context mContext) {
        this.mContext = mContext;
        LocalDatabaseHelper.init(mContext);// Gọi hàm khởi tạo kết nối Database
        friendDao = LocalDatabaseHelper.getInstance(mContext).getDaoSession().getFriendDao();// Khởi tạo phiên làm việc với Database với 1 bảng
    }
    // Thêm một record vào database
    public boolean AddFriend(Friend objFriend){
        if (friendDao.insert(objFriend) > 0){
            return  true;
        }
        return false;
    }
    //Sử một record
    public void EditFriend(Friend objFriend){
        friendDao.update(objFriend);
    }
    //Xóa 1 record
    public void DeleteFriend(Friend objFriend){
        friendDao.delete(objFriend);
    }
    // Lấy danh sách record từ database
    public List<Friend> FriendList(){
        return friendDao.loadAll();
    }
    // Lấy 1 record với Id
    public Friend getFriend(Long Id){
        return friendDao.load(Id);
    }
}

Tạo Recycleview Adapter chắc cái này khỏi nói quen quá rồi.

package com.chamcong.akinosora.sqlite;

import android.app.Dialog;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.PopupMenu;
import android.widget.TextView;

import java.util.List;

/**
 * Created by Akinosora on 09/11/2017.
 */

public class Adapter extends RecyclerView.Adapter<Adapter.FriendViewHolder> {
    private Context mContext;
    private List<Friend> danhsach;

    public Adapter(Context mContext, List<Friend> danhsach) {
        this.mContext = mContext;
        this.danhsach = danhsach;
    }

    @Override
    public FriendViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View objView = LayoutInflater.from(mContext).inflate(R.layout.lt_item, parent, false);
        return new FriendViewHolder(objView);
    }

    @Override
    public void onBindViewHolder(final FriendViewHolder holder, final int position) {
        holder.Name.setText(danhsach.get(position).getName());
        holder.Menu.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                final PopupMenu popupMenu = new PopupMenu(mContext, holder.Menu);
                popupMenu.getMenuInflater().inflate(R.menu.sub_menu, popupMenu.getMenu());
                popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
                    @Override
                    public boolean onMenuItemClick(MenuItem menuItem) {
                        switch (menuItem.getItemId()) {
                            case R.id.xoa:
                                new Controllers(mContext).DeleteFriend(danhsach.get(position));
                                danhsach.remove(position);
                                notifyItemRemoved(position);
                                notifyItemRangeChanged(position, danhsach.size());
                                break;
                            case R.id.sua:
                                final Dialog dialog = new Dialog(mContext);
                                dialog.setContentView(R.layout.dialogrhem);
                                final EditText NameEdit = dialog.findViewById(R.id.Inputname);
                                TextView Save = dialog.findViewById(R.id.save);
                                final Friend f = new Controllers(mContext).getFriend(danhsach.get(position).getId());
                                NameEdit.setText(f.getName());
                                Save.setOnClickListener(new View.OnClickListener() {
                                    @Override
                                    public void onClick(View view) {
                                        f.setName(NameEdit.getText().toString());
                                        new Controllers(mContext).EditFriend(f);
                                        notifyItemRangeChanged(position, danhsach.size());
                                        dialog.dismiss();
                                    }
                                });
                                dialog.show();
                                break;
                        }
                        return false;
                    }
                });
                popupMenu.show();
            }
        });
    }

    @Override
    public int getItemCount() {
        return danhsach.size();
    }

    class FriendViewHolder extends RecyclerView.ViewHolder {
        TextView Name;
        ImageView Menu;

        public FriendViewHolder(View itemView) {
            super(itemView);
            Name = itemView.findViewById(R.id.Name);
            Menu = itemView.findViewById(R.id.menu);
        }
    }
}

Và cuối cùng tại MainActivity ta sẽ xử lý như sau

package com.chamcong.akinosora.sqlite;

import android.app.Dialog;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

import java.util.List;

public class MainActivity extends AppCompatActivity {
    FloatingActionButton Add;
    RecyclerView Danhsach;
    private Controllers controllers;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initControl();
        initData();
        initEvent();
    }

    private void initEvent() {
        Add.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                final Dialog dialog = new Dialog(MainActivity.this);
                dialog.setContentView(R.layout.dialogrhem);

                final EditText NameEdit = dialog.findViewById(R.id.Inputname);
                TextView Save = dialog.findViewById(R.id.save);
                Save.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        if (controllers.AddFriend(new Friend(NameEdit.getText().toString()))) {
                            initData();
                            dialog.dismiss();
                        }
                    }
                });
                dialog.show();
            }
        });
    }

    private void initData() {
        controllers = new Controllers(MainActivity.this);
        List<Friend> friendList = controllers.FriendList();
        Adapter adapter = new Adapter(MainActivity.this, friendList);
        RecyclerView.LayoutManager lm = new GridLayoutManager(MainActivity.this, 1);
        Danhsach.setLayoutManager(lm);
        Danhsach.setItemAnimator(new DefaultItemAnimator());
        Danhsach.setAdapter(adapter);
    }

    private void initControl() {
        Add = findViewById(R.id.add);
        Danhsach = findViewById(R.id.danhsach);
    }
}

Xong bạn hãy thử chạy chương trình trên và xem nó hoạt động ra sao.

Như vậy là tôi đã hướng dẫn các bạn sử dụng SQLite với thư viện green dao trong bài viết tiếp theo cũng là bài cuối của series Android truyền kì tôi sẽ hướng dẫn các bạn kết nối và sử dụng SQL Server trong Android. Cảm ơn các bạn đã theo dõi và xin hẹn gặp lại trong bài cuối cùng.