fbpx
Hàng triệu nội dung hữu ích dành riêng cho bạn đã sẵn sàng. Tìm hiểu thêm
Tran Duy Thanh Level 4

Phát triển ứng dụng cơ sở dữ liệu thời gian thực với Firebase-phần 3

Tran Duy Thanh   15 min read

Bài 1 các bạn đã biết cách kết nối và truy vấn Realtime Database Firebase, Bài 2 biết cách thêm mới dữ liệu vào Firbase. Trong bài này Tui sẽ hướng dẫn các bạn cách chỉnh sửa và xóa dữ liệu khỏi Realtime Database Firebase.

Tiếp tục mở lại Project ở bài 2, Ta bổ sung thêm 3 chức năng: Lấy chi tiết Cập nhật và xóa.

Ta tạo một màn hình mới tên là CapNhatContactActivity, bằng cách bấm chuột phải vào package/ chọn New / Chọn Activity/ chọn Empty Activity:

Sau khi chọn Empty Activity, ta nhập tên CapNhatContactActivity:

sau khi nhập xong, nhấn FINISH để tạo màn hình Cập nhật, thiết kế giao diện màn hình này như hình dưới đây:

Mục đích của màn hình này là:

– Truy vấn chi tiết 1 Contact trên Firebase dựa vào Contact ID được chọn trên ListView ở màn hình chính

– Cho phép Cập nhật

– Cho phép Xóa

XML Layout của màn hình này như sau:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".CapNhatContactActivity">
    <TextView
        android:id="@+id/textView0"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Nhập Contact Id:"
        android:textSize="25sp" />
    <EditText
        android:id="@+id/edtContactId"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:hint="Contact Id ở đây"
        android:inputType="textPersonName"
        android:textSize="25sp" />
    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Nhập Ten:"
        android:textSize="25sp" />
    <EditText
        android:id="@+id/edtTen"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:hint="Tên ở đây"
        android:inputType="textPersonName"
        android:textSize="25sp" />
    <TextView
        android:id="@+id/textView2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Nhập Email:"
        android:textSize="25sp" />
    <EditText
        android:id="@+id/edtEmail"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:hint="Email ở đây"
        android:inputType="textEmailAddress"
        android:textSize="25sp" />
    <TextView
        android:id="@+id/textView3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Nhập Phone:"
        android:textSize="25sp" />
    <EditText
        android:id="@+id/edtPhone"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="Phone ở đây"
        android:inputType="phone"
        android:textSize="25sp" />
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="horizontal">
        <Button
            android:id="@+id/btnChinhSua"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Cập Nhật"
            android:textSize="25sp" />
        <Button
            android:id="@+id/btnXoa"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Xóa"
            android:textSize="25sp" />
    </LinearLayout>
</LinearLayout>

Tiến hành bổ sung sự kiện cho ListView ở màn hình MainActivity:

1
2
3
4
5
6
7
8
9
10
lvContact.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        String data=adapter.getItem(position);
        String key=data.split("\n")[0];
        Intent intent=new Intent(MainActivity.this,CapNhatContactActivity.class);
        intent.putExtra("KEY",key);
        startActivity(intent);
    }
});

Vì ở màn hình chính Tui hiển thị mỗi dòng là các thông số Contact Id, Phone, Email, Name được nối nhau bằng ký tự xuống dòng \n. Nên ở đây khi có được dòng đang chọn, Tui dùng hàm split để tách ra, phần tử đầu tiên là Contact ID nên lấy index là [0]

Contact ID này sẽ được gửi qua màn hình CapNhatContactActivity, Tui đặt tên nó là KEY. Bên màn hình Cập nhật sẽ dựa vào KEY này để lấy thông tin chi tiết từ Firebase cũng như dùng cho cập nhật, xóa (Các bạn đừng thắc mắc là tại sao không truyền hết qua luôn để không phải mất công truy suất lại). Ở đây Tui có 2 lý do:

  • Lý do 1: Tui muốn hướng dẫn các bạn cách lấy thông tin chi tiết từ Firebase khi có Key
  • Lý do 2: Trong thực tế dữ liệu có rất nhiều thuộc tính, trong màn hình danh sách không phải tải hết về, mà chỉ tải một số thông tin quan trọng, do đó trong màn hình chí tiết ta mới tải hết về dựa vào Key

OK, giờ quay lại màn hình CapNhatContactActivity, coding để lấy chi tiết Contact:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package com.communityuni.realtimedatabasefirebase;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import java.util.HashMap;
public class CapNhatContactActivity extends AppCompatActivity {
    EditText edtId,edtTen,edtPhone,edtEmail;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_cap_nhat_contact);
        addControls();
        getContactDetail();
    }
    private void getContactDetail() {
        Intent intent=getIntent();
        final String key=intent.getStringExtra("KEY");
        FirebaseDatabase database = FirebaseDatabase.getInstance();
        //Kết nối tới node có tên là contacts (node này do ta định nghĩa trong CSDL Firebase)
        DatabaseReference myRef = database.getReference("contacts");
        //truy suất và lắng nghe sự thay đổi dữ liệu
        //chỉ truy suất node được chọn trên ListView myRef.child(key)
        //addListenerForSingleValueEvent để lấy dữ liệu đơn
        myRef.child(key).addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                try {
                    //nó trả về 1 DataSnapShot, mà giá trị đơn nên gọi getValue trả về 1 HashMap
                    HashMap<String,Object> hashMap= (HashMap<String, Object>) dataSnapshot.getValue();
                    //HashMap này sẽ có kích  thước bằng số Node con bên trong node truy vấn
                    //mỗi phần tử có key là name được định nghĩa trong cấu trúc Json của Firebase
                    edtId.setText(key);
                    edtTen.setText(hashMap.get("name").toString());
                    edtEmail.setText(hashMap.get("email").toString());
                    edtPhone.setText(hashMap.get("phone").toString());
                }
                 catch (Exception ex)
                {
                    Log.e("LOI_JSON",ex.toString());
                }
            }
            @Override
            public void onCancelled(DatabaseError databaseError) {
                Log.w("LOI_CHITIET", "loadPost:onCancelled", databaseError.toException());
            }
        });
    }
    private void addControls() {
        edtId=findViewById(R.id.edtContactId);
        edtTen=findViewById(R.id.edtTen);
        edtPhone=findViewById(R.id.edtPhone);
        edtEmail=findViewById(R.id.edtEmail);
    }
}

Lưu ý trong sự kiện lấy chi tiết, Tui dùng addListenerForSingleValueEvent, nó khác với lấy danh sách Contact trong MainActivity nha (addValueEventListener).

Chạy lên ta có kết quả:

Khi chọn 1 Contact, ví dụ như Putin–> nó sẽ mò lên Realtime Database Firebase để lấy chi tiết  và trả về cho màn hình CapNhatContactActivity.

Tiếp tục bổ sung 2 sự kiện (dùng onClick XML) Cập nhật và Xóa cho màn hình Cập Nhật:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<Button
    android:id="@+id/btnChinhSua"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:onClick="xuLySua"
    android:text="Cập Nhật"
    android:textSize="25sp" />
<Button
    android:id="@+id/btnXoa"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:onClick="xuLyXoa"
    android:text="Xóa"
    android:textSize="25sp" />

Coding cho 2 sự kiện này trong màn hình CapNhatContactActivity như sau:

Sự kiện sửa:

1
2
3
4
5
6
7
8
9
10
11
12
13
public void xuLySua(View view) {
    String key=edtId.getText().toString();
    String phone=edtPhone.getText().toString();
    String name=edtTen.getText().toString();
    String email=edtEmail.getText().toString();
    FirebaseDatabase database = FirebaseDatabase.getInstance();
    //Kết nối tới node có tên là contacts (node này do ta định nghĩa trong CSDL Firebase)
    DatabaseReference myRef = database.getReference("contacts");
    myRef.child(key).child("phone").setValue(phone);
    myRef.child(key).child("email").setValue(email);
    myRef.child(key).child("name").setValue(name);
    finish();
}

Ở trên biến key là ContactId, ta sửa giá trị các node bên trong của nó lần lượt có: Phone, email, name:

myRef.child(key).child(“phone”) -> truy suất tới node phone

myRef.child(key).child(“phone”).setValue(phone)–> đổi mới giá trị cho node phone.

Sự kiện Xóa:

1
2
3
4
5
6
7
8
public void xuLyXoa(View view) {
    String key=edtId.getText().toString();
    FirebaseDatabase database = FirebaseDatabase.getInstance();
    //Kết nối tới node có tên là contacts (node này do ta định nghĩa trong CSDL Firebase)
    DatabaseReference myRef = database.getReference("contacts");
    myRef.child(key).removeValue();
    finish();
}

Ta dùng hàm removeValue() để xóa, hoặc setValue(null) nha. Còn muốn cập nhập/ xóa nhiều thì dùng hàm updateChildren, truyền vào là 1 HashMap.

Cuối cùng ta có coding đầy đủ của màn hình CapNhatContactActivity như sau:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package com.communityuni.realtimedatabasefirebase;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import java.util.HashMap;
public class CapNhatContactActivity extends AppCompatActivity {
    EditText edtId,edtTen,edtPhone,edtEmail;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_cap_nhat_contact);
        addControls();
        getContactDetail();
    }
    private void getContactDetail() {
        Intent intent=getIntent();
        final String key=intent.getStringExtra("KEY");
        FirebaseDatabase database = FirebaseDatabase.getInstance();
        //Kết nối tới node có tên là contacts (node này do ta định nghĩa trong CSDL Firebase)
        DatabaseReference myRef = database.getReference("contacts");
        //truy suất và lắng nghe sự thay đổi dữ liệu
        //chỉ truy suất node được chọn trên ListView myRef.child(key)
        //addListenerForSingleValueEvent để lấy dữ liệu đơn
        myRef.child(key).addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                try {
                    //nó trả về 1 DataSnapShot, mà giá trị đơn nên gọi getValue trả về 1 HashMap
                    HashMap<String,Object> hashMap= (HashMap<String, Object>) dataSnapshot.getValue();
                    //HashMap này sẽ có kích  thước bằng số Node con bên trong node truy vấn
                    //mỗi phần tử có key là name được định nghĩa trong cấu trúc Json của Firebase
                    edtId.setText(key);
                    edtTen.setText(hashMap.get("name").toString());
                    edtEmail.setText(hashMap.get("email").toString());
                    edtPhone.setText(hashMap.get("phone").toString());
                }
                 catch (Exception ex)
                {
                    Log.e("LOI_JSON",ex.toString());
                }
            }
            @Override
            public void onCancelled(DatabaseError databaseError) {
                Log.w("LOI_CHITIET", "loadPost:onCancelled", databaseError.toException());
            }
        });
    }
    private void addControls() {
        edtId=findViewById(R.id.edtContactId);
        edtTen=findViewById(R.id.edtTen);
        edtPhone=findViewById(R.id.edtPhone);
        edtEmail=findViewById(R.id.edtEmail);
    }
    public void xuLySua(View view) {
        String key=edtId.getText().toString();
        String phone=edtPhone.getText().toString();
        String name=edtTen.getText().toString();
        String email=edtEmail.getText().toString();
        FirebaseDatabase database = FirebaseDatabase.getInstance();
        //Kết nối tới node có tên là contacts (node này do ta định nghĩa trong CSDL Firebase)
        DatabaseReference myRef = database.getReference("contacts");
        myRef.child(key).child("phone").setValue(phone);
        myRef.child(key).child("email").setValue(email);
        myRef.child(key).child("name").setValue(name);
        finish();
    }
    public void xuLyXoa(View view) {
        String key=edtId.getText().toString();
        FirebaseDatabase database = FirebaseDatabase.getInstance();
        //Kết nối tới node có tên là contacts (node này do ta định nghĩa trong CSDL Firebase)
        DatabaseReference myRef = database.getReference("contacts");
        myRef.child(key).removeValue();
        finish();
    }
}

Chạy phần mềm lên, giả sử chọn Contact có tên là Tám:

Ta bấm cập nhật, dữ liệu sẽ được update luôn trên Firebase Server, và bất kỳ client nào đang sài phần mềm này cũng thấy sự thay đổi đó.

Giả sử bạn nhấn nút Xóa, trên Firebase sẽ đánh dấu mà đỏ báo cho ta chuẩn bị xóa-> và xóa thành công:

Như vậy Tui đã hướng dẫn xong cách: lấy chi tiết, cập nhật và xóa, các bạn thực hành lại nha.

Đây là source code của phần này: Tải code ở đây

Bài sau Tui sẽ hướng dẫn phần nâng cao: dùng java model class, cũng như lắng nghe kết quả thực hiện, transaction… các bạn chú ý theo dõi.

Chào mừng trở lại.

Đăng nhập sẽ giúp cá nhân hoá nội dung trang chủ của bạn, theo dõi các chủ đề yêu thích và tương tác với các bài viết bạn yêu thích.


Chào mừng trở lại.

Đăng nhập sẽ giúp cá nhân hoá nội dung trang chủ của bạn, theo dõi các chủ đề yêu thích và tương tác với các bài viết bạn yêu thích.


Chào mừng tham gia.

Đăng nhập sẽ giúp cá nhân hoá nội dung trang chủ của bạn, theo dõi các chủ đề yêu thích và tương tác với các bài viết bạn yêu thích.


Nhấp vào “Đăng ký” để chấp nhận Điều khoản dịch vụ và chính sách bảo mật của Toppick.