ActiveAndroid – Tạo và thao tác database trong Android trong vòng 1 nốt nhạc
Chào các bạn, rất lâu rồi mình mới trở lại viết Blog hướng dẫn về Android. Lần trước mình đã có viết 5 bài về database trong android. Thực sự đó là một loạt bài rất tâm huyết của mình, tuy nhiên sau nhiều lần làm việc với database, mình nhận ra cách sử dụng thông thường như vậy thật là quá vất vả với 1 bảng, chứ chưa nói đến database có nhiều bảng. Vì vậy căn bệnh lười phát sinh và nghĩ rằng liệu có một thứ gì đó hoặc một cách nào đó mà chỉ cần “1 nốt nhạc” cũng tạo được một database phức tạp. Và mình đã tìm ra nó – ActiveAndroid.
Trang chủ của ActiveAndroid ở đây: http://www.activeandroid.com/
Tuy nhiên mình chỉ đọc trên github của họ thôi, các bạn có thể xem tại đây: https://github.com/pardom/ActiveAndroid
Trong bài này, mình sẽ hướng dẫn các bạn làm một ứng dụng FriendList (lưu tên bạn bè) đơn giản xây dựng database với ActiveAndroid trên Android Studio 2.0
Nội dung
1. Cấu hình build.gradle
Chúng ta cấu hình như sau:
apply plugin: 'com.android.application' android { compileSdkVersion 23 buildToolsVersion "23.0.2" defaultConfig { applicationId "com.nguyenvanquan7826.friendlist" minSdkVersion 14 targetSdkVersion 23 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } // for activeandroid repositories { mavenCentral() maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:design:23.3.0' compile 'com.android.support:cardview-v7:23.3.0' compile 'com.android.support:recyclerview-v7:23.3.0' // for activeandroid compile 'com.michaelpardo:activeandroid:3.1.0-SNAPSHOT' }
Trong đó chú ý những dòng để load thư viện activeandroid
repositories { mavenCentral() maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } } compile 'com.michaelpardo:activeandroid:3.1.0-SNAPSHOT'
2. Cấu hình manifest
Trong thẻ application của AndroidManifest.xml các bạn thêm các thuộc tính sau:
<application android:name="com.activeandroid.app.Application" ... <meta-data android:name="AA_DB_NAME" android:value="friendlist.db" /> <meta-data android:name="AA_DB_VERSION" android:value="1" /> <meta-data android:name="AA_MODELS" android:value="com.nguyenvanquan7826.friendlist.Friend" /> ... </application>
Trong này các bạn chú ý:
- AA_DB_NAME là từ khóa nhận biết tên database (friendlist.db)
-
AA_DB_VERSION là từ khóa nhận biết phiên bản database (hiện tại là phiên bản 1), sau này các bạn nâng cấp database chỉ cần sửa tại đây thôi
-
AA_MODELS là từ khóa nhận biết các bảng trong database. Các bảng này chính là các class của chúng ta (có kèm package), lát nữa mình sẽ nói rõ hơn. Bình thường chúng ta không cần thẻ meta-data của AA_MODELS, tuy nhiên để quá trình load cấu trúc database nhanh hơn và nếu muốn cho Android 6 chạy được các bạn hãy cho vào. Trong trường hợp có nhiều bảng, các bạn ghi cách nhau bởi dấu phẩy như sau:
com.nguyenvanquan7826.friendlist.Friend, com.nguyenvanquan7826.friendlist.Lover -
android:name=”com.activeandroid.app.Application” đây là dòng khai báo cho ứng dụng biết chúng ta sử dụng Application của activeandroid. Nếu các bạn đang sử dụng một Application của một thư viện khác thì có thể dùng Application đó kế thừa com.activeandroid.app.Application. Hoặc nếu bạn không muốn kế thừa từ com.activeandroid.app.Application thì có thể custom file Application hiện tại của bạn như sau:
public class MyApplication extends SomeLibraryApplication { @Override public void onCreate() { super.onCreate(); Configuration dbConfiguration = new Configuration.Builder(this).setDatabaseName("xxx.db").create(); ActiveAndroid.initialize(dbConfiguration); } }
3. Thiết kế giao diện
Định nghĩa color trong file res/values/colors.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="colorPrimary">#3F51B5</color> <color name="colorPrimaryDark">#303F9F</color> <color name="colorAccent">#FF4081</color> <color name="white">#FFFFFF</color> <color name="black">#000000</color> <color name="background_activity">#F5F5F5</color> <color name="transparent">#00000000</color> </resources>
Định nghĩa các chuỗi trong file res/values/strings.xml
<resources> <string name="app_name">FriendList</string> <string name="action_settings">Settings</string> <string name="name">Name</string> <string name="phone">Phone</string> <string name="add">Add</string> <string name="update">Update</string> <string name="edit">Edit</string> <string name="delete">Delete</string> <string name="delete_success">Delete success</string> <string name="delete_fail">Delete fail</string> <string name="save_success">Save success</string> <string name="save_fail">Save fail</string> <string name="update_success">Update success</string> <string name="update_fail">Update fail</string> <string name="please_enter_name">Please enter name</string> <string name="please_enter_phone">Please enter phone</string> </resources>
Định nghĩa layout chính. Layout chính của chúng ta gồm 2 file (Android Studio tự phân ra cho chúng ta khi tạo Project). Nếu các bạn không thích thì hoàn toàn có thể gộp thành 1 file.
res/layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:context="com.nguyenvanquan7826.friendlist.MainActivity"> <android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/AppTheme.AppBarOverlay"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/AppTheme.PopupOverlay" /> </android.support.design.widget.AppBarLayout> <include layout="@layout/content_main" /> </android.support.design.widget.CoordinatorLayout>
res/layout/content_main.xml là file chứa nội dung chính của giao diện
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:context="com.nguyenvanquan7826.friendlist.MainActivity" tools:showIn="@layout/activity_main"> <android.support.design.widget.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <EditText android:id="@+id/editName" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/name" android:singleLine="true" /> </android.support.design.widget.TextInputLayout> <android.support.design.widget.TextInputLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <EditText android:id="@+id/editPhone" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="@string/phone" android:inputType="phone" android:singleLine="true" /> </android.support.design.widget.TextInputLayout> <Button android:id="@+id/btnAdd" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="@string/add" /> <android.support.v7.widget.RecyclerView android:id="@+id/rv" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>
res/layout/item_friend.xml là file giao diện của 1 item trong danh sách
<?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:card_view="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="4dp" android:background="@color/white" android:foreground="?android:attr/selectableItemBackground" card_view:cardCornerRadius="2dp"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="4dp"> <ImageView android:id="@+id/icFriend" android:layout_width="48dp" android:layout_height="48dp" android:layout_centerVertical="true" android:layout_marginRight="4dp" android:src="@drawable/ic_friend" /> <TextView android:id="@+id/tvName" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@+id/icFriend" android:text="@string/name" android:textSize="18sp" /> <TextView android:id="@+id/tvPhone" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/tvName" android:layout_toRightOf="@+id/icFriend" android:text="@string/phone" /> <ImageView android:id="@+id/btnMore" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:src="@drawable/ic_more" /> </RelativeLayout> </android.support.v7.widget.CardView>
4. Tạo lớp dữ liệu – class Friend
Việc tạo class Friend này rất quan trọng, nó không những là class để tạo các đối tượng Friend mà còn là bảng Friend của chúng ta trong database.
Chúng ta tạo class như sau:
package com.nguyenvanquan7826.friendlist; import com.activeandroid.Model; import com.activeandroid.annotation.Column; import com.activeandroid.annotation.Table; @Table(name = "tbFriend") public class Friend extends Model { public static final String NAME = "name"; public static final String PHONE = "phone"; @Column(name = NAME) private String name; @Column(name = PHONE) private String phone; public String getName() { return name; } public Friend setName(String name) { this.name = name; return this; } public String getPhone() { return phone; } public Friend setPhone(String phone) { this.phone = phone; return this; } }
Trong class này các bạn chú ý:
- class Friend kế thừa từ class Model của com.activeandroid, chúng ta cần kế thừa nó để có thể tạo bảng dữ liệu và dùng các câu lệnh truy vấn cho class Friend này.
-
@Table(name = “tbFriend”) định nghĩa tên bảng là tbFriend trong database. Lệnh này viết ngay trên tên của class các bạn muốn nó là bảng.
-
@Column(name = PHONE) định nghĩa column phone trong bảng tbFriend
5. Tạo adapter
Trong phần này chúng ta cần tạo ra 1 adapter sao cho mỗi item đều có 1 nút menu (nút 3 chấm). Nút này để hiển thị 1 menu (edit, delete) khi click vào. Để thực hiện được điều này chúng ta cần tạo 1 PopupMenu từ file menu.
res/menu/menu_item_friend.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" tools:context="com.nguyenvanquan7826.friendlist.MainActivity"> <item android:id="@+id/menu_edit" android:orderInCategory="100" android:title="@string/edit" app:showAsAction="never" /> <item android:id="@+id/menu_delete" android:orderInCategory="100" android:title="@string/delete" app:showAsAction="never" /> </menu>
Tiếp đến để bắt sự kiện cho menu có thể edit và delete được chúng ta cần tạo 1 interface để truyền thông tin về cho MainActivity xử lý.
AdapterFriend.java
package com.nguyenvanquan7826.friendlist; import android.content.Context; import android.support.v7.widget.PopupMenu; 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.TextView; import java.util.List; public class AdapterFriend extends RecyclerView.Adapter<AdapterFriend.RecyclerViewHolder> { private List<Friend> list; private Context context; public AdapterFriend(Context context, List<Friend> list) { this.context = context; this.list = list; } @Override public int getItemCount() { return list.size(); } @Override public RecyclerViewHolder onCreateViewHolder(ViewGroup viewGroup, int position) { LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext()); View itemView = inflater.inflate(R.layout.item_friend, viewGroup, false); return new RecyclerViewHolder(itemView); } @Override public void onBindViewHolder(RecyclerViewHolder viewHolder, int position) { Friend friend = list.get(position); viewHolder.tvName.setText(friend.getName()); viewHolder.tvPhone.setText(friend.getPhone()); } public class RecyclerViewHolder extends RecyclerView.ViewHolder { public TextView tvName; public TextView tvPhone; // for show menu edit and delete private PopupMenu popupMenu; public RecyclerViewHolder(View itemView) { super(itemView); tvName = (TextView) itemView.findViewById(R.id.tvName); tvPhone = (TextView) itemView.findViewById(R.id.tvPhone); itemView.findViewById(R.id.btnMore).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { popupMenu.show(); } }); setPopup(itemView); } /* * when show popup menu, we can click edit or delete menu item. * so we need create a interface to sent position for main activity process * */ private void setPopup(View view) { popupMenu = new PopupMenu(context, view); popupMenu.getMenuInflater().inflate(R.menu.menu_item_friend, popupMenu.getMenu()); popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { public boolean onMenuItemClick(MenuItem item) { switch (item.getItemId()) { case R.id.menu_edit: if (listener != null) { listener.edit(getAdapterPosition()); } break; case R.id.menu_delete: if (listener != null) { listener.del(getAdapterPosition()); } break; } return true; } }); } } public interface AdapterFriendListener { void del(int position); void edit(int position); } private AdapterFriendListener listener; public AdapterFriend setListener(AdapterFriendListener listener) { this.listener = listener; return this; } }
6. Viết xử lý trong MainActivity
Trong MainActivity chúng ta có 3 công việc chính cần xử lý gồm Thêm, Sửa, Xóa. Việc thêm và sửa thì gần giống nhau, nếu thêm chúng ta tạo mới, nếu sửa chúng ta xem xét vị trí cần sửa qua 1 biến positionEdit.
MainActivity.java
package com.nguyenvanquan7826.friendlist; import android.content.Context; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.text.TextUtils; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import com.activeandroid.query.Select; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class MainActivity extends AppCompatActivity implements AdapterFriend.AdapterFriendListener { private Context context; private EditText editName; private EditText editPhone; private Button btnAdd; private AdapterFriend adapter; private ArrayList<Friend> list; /* * index of item need edit * if positionEdit = -1 then we not need edit item, so when click btnAdd we insert into database * if positionEdit >= 0 then we need eidt item, so when click btnAdd we update item inti database * */ private int positionEdit = -1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); context = this; setContentView(R.layout.activity_main); connectView(); reloadData(); } private void connectView() { Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); RecyclerView recyclerView = (RecyclerView) findViewById(R.id.rv); recyclerView.setHasFixedSize(false); LinearLayoutManager layoutManager = new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false); recyclerView.setLayoutManager(layoutManager); adapter = new AdapterFriend(context, list = new ArrayList<>()); adapter.setListener(this); recyclerView.setAdapter(adapter); editName = (EditText) findViewById(R.id.editName); editPhone = (EditText) findViewById(R.id.editPhone); btnAdd = (Button) findViewById(R.id.btnAdd); btnAdd.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { add(); } }); } private void add() { String name = editName.getText().toString().trim(); String phone = editPhone.getText().toString().trim(); if (TextUtils.isEmpty(name)) { editName.requestFocus(); Toast.makeText(context, R.string.please_enter_name, Toast.LENGTH_SHORT).show(); return; } if (TextUtils.isEmpty(phone)) { editPhone.requestFocus(); Toast.makeText(context, R.string.please_enter_phone, Toast.LENGTH_SHORT).show(); return; } Friend friend; // we not need edit if (positionEdit < 0) { friend = new Friend(); } else { // we need edit friend = list.get(positionEdit); } friend.setName(name).setPhone(phone).save(); reloadData(); editName.setText(""); editPhone.setText(""); btnAdd.setText(R.string.add); editName.requestFocus(); Toast.makeText(context, R.string.save_success, Toast.LENGTH_SHORT).show(); } @Override public void del(int position) { Friend.delete(Friend.class, list.get(position).getId()); reloadData(); Toast.makeText(context, R.string.delete_success, Toast.LENGTH_SHORT).show(); } @Override public void edit(int position) { positionEdit = position; editName.setText(list.get(position).getName()); editPhone.setText(list.get(position).getPhone()); btnAdd.setText(R.string.update); editName.requestFocus(); } private void reloadData() { List<Friend> ls = new Select().from(Friend.class).execute(); list.clear(); list.addAll(ls); Collections.reverse(list); adapter.notifyDataSetChanged(); } }
Ở code trên các bạn chú ý:
- Để lưu lại hoặc insert 1 bản ghi (1 object) chúng ta chỉ cần gọi phương thức save()
-
Để lấy ra một danh sách các bản ghi chúng ta dùng new Select().from(Friend.class).execute()
-
Để xóa một bản ghi ta dùng phương thức delete.
Trên đây là những hướng dẫn hết sức cơ bản của mình để sử dụng ActiveAndroid thao tác với database trong vòng “một nốt nhạc”. Để có thể hiểu thêm và thực hiện tốt nhiều điều khác các bạn hãy xem wiki của họ
Các bạn có thể download Project FriendList tại đây
Bài viết được thực hiện trong loạt bài hướng dẫn Database trong Android bởi nguyenvanquan7826
Chúc các bạn vui vẻ.
friend.setName(name).setPhone(phone).save();
Có gì sai ở đây rồi anh ạ.
Sai thế nào em?
trong hàm set đã return this rồi mà bạn
Anh ơi nếu muốn dùng ImageSlide trong pageview mà lại lấy ảnh trong SQLite ra chứ ko phải từ drawable thì làm thế nào vậy a
lưu link ảnh vào sqlite thôi, hoặc lưu tên ảnh, sau đó dựa vào tên ảnh lấy drawable ra.
Tôi muốn học từ xa để làm một app đơn giản trên Android
SĐT & Zalo của tôi 0909142790