Lưu trữ và truy vấn người dùng, các đối tượng dữ liệu và các tệp trong đám mây
cho các ứng dụng Android của bạn
Khám phá những ưu điểm về lưu trữ dữ liệu của ứng dụng di động trong một đám
mây riêng thông qua bài giới thiệu về Parse SDK (Bộ công cụ dùng cho nhà phát
triển phần mềm của Parse) này, phiên bản dành cho Android. Chuyên gia di động
C. Enrique Ortiz giới thiệu các lớp API của Parse để lưu trữ và xử lý người dùng,
các đối tượng dữ liệu và các tệp trong đám mây cho các ứng dụng di động của bạn.
34 trang |
Chia sẻ: lylyngoc | Lượt xem: 1660 | Lượt tải: 1
Bạn đang xem trước 20 trang tài liệu Các dịch vụ đám mây của Parse dành cho Android, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
Các dịch vụ đám mây của
Parse dành cho Android
Lưu trữ và truy vấn người dùng, các đối tượng dữ liệu và các tệp trong đám mây
cho các ứng dụng Android của bạn
Khám phá những ưu điểm về lưu trữ dữ liệu của ứng dụng di động trong một đám
mây riêng thông qua bài giới thiệu về Parse SDK (Bộ công cụ dùng cho nhà phát
triển phần mềm của Parse) này, phiên bản dành cho Android. Chuyên gia di động
C. Enrique Ortiz giới thiệu các lớp API của Parse để lưu trữ và xử lý người dùng,
các đối tượng dữ liệu và các tệp trong đám mây cho các ứng dụng di động của bạn.
Bộ công cụ cho nhà phát triển phần mềm di động của Parse (Parse mobile SDK)
cung cấp các API và các dịch vụ đám mây dành cho các ứng dụng iOS, Android và
Windows®. Parse SDK còn cung cấp một JavaScript và các API REST. Khi sử
dụng Parse API, bạn có thể chạy các ứng dụng di động của mình trên đám mây một
cách nhanh chóng và hao tốn ít hiệu năng. Một ứng dụng di động được tích hợp
với Parse API có thể dễ dàng lưu trữ các đối tượng và các tệp dữ liệu trên Parse
cloud, gửi và lắng nghe các tin nhắn push (ND.: tin nhắn push (push notification)
cho phép một ứng dụng thông báo cho bạn các tin nhắn hoặc sự kiện mới mà
không cần phải mở ứng dụng ra), quản lý người dùng, xử lý dữ liệu vị trí địa lý và
sử dụng các nền tảng truyền thông xã hội như Twitter và Facebook. Đối với các
ứng dụng di động cần mở rộng quy mô, Parse SDK cung cấp tất cả tính co giãn của
một nền tảng đám mây.
Bài này giới thiệu các lớp Parse API cốt lõi cho người dùng, các đối tượng dữ liệu
và các tệp của Parse. Bạn sẽ tìm hiểu cách làm việc với các danh sách kiểm soát
truy cập (ACL), cách thực hiện các thao tác CRUD trên các đối tượng dữ liệu, cách
lưu trữ và lấy ra các tệp trong Parse cloud. Các ví dụ được xây dựng trên Parse
SDK cho Android
Bảng điều khiển Parse
Bảng điều khiển Parse hỗ trợ các nhà phát triển trong việc quản lý các ứng dụng.
Bảng điều khiển cung cấp các số liệu thống kê về cách sử dụng chung và cách sử
dụng ứng dụng-đặc trưng cho các API, các tệp và các tin nhắn push. Các khóa và
các giá trị thiết lập ứng dụng được quản lý thông qua bảng điều khiển. Bảng điều
khiển này cũng cung cấp một trình duyệt dữ liệu để cho phép các nhà phát triển
duyệt và thậm chí chỉnh sửa các đối tượng Parse đã lưu. Trình duyệt dữ liệu rất có
ích cho việc gỡ lỗi. Hình 1 là một ảnh chụp màn hình của bảng điều khiển Parse:
Hình 1. Bảng điều khiển Parse
Các ứng dụng được xác thực thông qua một Application ID (mã định danh ứng
dụng) và một Client ID (mã định danh khách hàng). Để có được các ID ứng dụng
và ID khách hàng của mình, bạn phải đăng ký ứng dụng của mình qua bảng điều
khiển Parse. Bạn sẽ sử dụng các khóa này khi khởi tạo thư viện Parse trên ứng
dụng của mình.
Các đối tượng dữ liệu Parse
Trong Parse, dữ liệu được biểu diễn bằng cách sử dụng ParseObject, một đối tượng
chứa các cặp name-value (tên-giá trị). ParseObject có thể lưu trữ bất kỳ dữ liệu nào
tương thích với JSON, như trong Liệt kê 1 1:
Liệt kê 1. Một ví dụ về ParseObject
ParseObject myParseObject = new ParseObject("MyObject"); // Class Name
myParseObject.put("name", "C. Enrique Ortiz");
myParseObject.put("twitterHandle", "eortiz");
myParseObject.put("followers", 123456);
Khi được tạo ra, ParseObject được cấp một classname. Classname trong Liệt kê 1
là "MyObject". Các classname giống như các tên bảng trong một cơ sở dữ liệu
quan hệ và các đối tượng Parse trong cùng lớp giống như các hàng trong một bảng.
ParseObject trưng ra các phương thức tương tự như các phương thức được cung
cấp trong một lớp Map của Java, chẳng hạn như put, get và remove, cộng với một
số phương thức khác đặc trưng cho ParseObject.
Các khóa tên (name keys) của ParseObject phải là chữ số; theo quy định, sử dụng
cách viết hoa chữ cái đầu tiên của các từ cho các khóa tên. Các giá trị có thể là bất
kỳ kiểu dữ liệu nào có thể được lưu trữ trong JSON; có nghĩa là, các số, các chuỗi,
các kiểu dữ liệu logic, các mảng, JSONObject.NULL, các JSONObject và các
JSONArray. Các kiểu dữ liệu khác được ParseObject hỗ trợ là các mảng Date và
byte[] của Java. Một ParseObject cũng có thể bao gồm nhiều ParseObject.
Liệt kê 2 cho thấy một số kiểu dữ liệu giá trị của ParseObject được hỗ trợ:
Liệt kê 2. ParseObject: Một số kiểu dữ liệu giá trị được hỗ trợ
// Byte Array
byte[] byteArray = {1, 2, 3, 4, 5};
// A date
Date d = new Date(); // java.util.Date
// A number
int number = 21;
// A String
String name = "Enrique";
// A JSONArray - any mix of JSONObjects, JSONArrays, Strings, Booleans,
// Integers, Longs, Doubles, null or NULL.
JSONArray jArray = new JSONArray();
jArray.put(number);
jArray.put(name);
// A JSONObject
JSONObject jObject = new JSONObject();
try {
jObject.put("number", number);
jObject.put("name", name);
} catch (JSONException e) {
e.printStackTrace();
}
// A ParseObject
ParseObject pObject = new ParseObject("MyObject"); // Class name
pObject.put("myByteArray", byteArray);
pObject.put("myDate", d);
pObject.put("myString", name);
pObject.put("myNumber", number);
pObject.put("myJsonArray", jArray);
pObject.put("myJsonObject", jObject);
pObject.put("myNull", JSONObject.NULL);
Mã trong Liệt kê 2 tạo ra một ParseObject được lưu trữ như một đối tượng trong
đám mây Parse. Sau đó nhiều MyObject của cùng lớp được lưu như các hàng của
các đối tượng dữ liệu ParseObject để có thể lưu, truy vấn, cập nhật và xóa các đối
tượng dữ liệu đó khỏi thiết bị lưu trữ đám mây của Parse. Thậm chí còn có thể lưu
dữ liệu khi ứng dụng không nối mạng — thư viện Parse chỉ cần lưu dữ liệu cục bộ
cho đến khi một kết nối mạng được thiết lập lại.
Sửa đổi một ParseObject
Nếu bạn đã quen với việc phát triển ứng dụng di động, thì bạn biết rằng các hoạt
động lâu dài như các hoạt động mạng nên được chạy ngầm, trên một luồng làm
việc (worker thread) và không phải trên luồng giao diện người dùng của hệ thống
chính. Điều này sẽ giữ cho luồng của hệ thống chính không chặn và ảnh hưởng đến
sự đáp ứng của giao diện người dùng của bạn. Phần sau của bài này, tôi sẽ chỉ cho
bạn cách Parse tạo điều kiện thuận lợi cho hoạt động trong nền để lưu, xóa và tìm
ra các đối tượng. Bây giờ, hãy xem xét phương thức remove() đồng bộ sau đây
được sử dụng để loại bỏ một khóa khỏi đối tượng Parse:
pObject.remove("myNumber"); // remove the field/key "myNumber" from pObject
Sau khi loại bỏ hoặc thêm vào các trường hay cập nhật một trường hiện tại, bạn có
thể lưu (hoặc cập nhật) đối tượng dữ liệu trên đám mây bằng cách gọi một trong
các phương thức save...() của ParseObject, mà tôi thảo luận sau trong bài này.
Những người dùng, các vai trò và các ACL của Parse
Trước khi tôi giới thiệu cho bạn cách thực hiện các hoạt động CRUD trên một đối
tượng Parse, bạn nên biết một số thông tin về người dùng, các vai trò và các ACL
(Danh sách kiểm soát truy cập) của Parse. Tất cả ba điều này đều là các khái niệm
và các phương tiện rất quan trọng để bảo vệ các đối tượng dữ liệu ứng dụng của
bạn.
Parse users (những người dùng Parse)
Một lớp có tên là ParseUser đại diện cho một người dùng và cung cấp chức năng
tài khoản-người dùng cho các ứng dụng Parse. Mỗi ứng dụng Parse có những
người dùng Parse liên kết với nó. Một lớp ParseUser là một ParseObject nhưng có
các thuộc tính bổ sung là username, password và email. Bạn có thể thêm vào bất
kỳ giá trị dữ liệu bổ sung nào mà bạn thấy phù hợp.
Những người dùng có thể đăng ký trở thành Parse users trong ứng dụng của bạn,
như trong Liệt kê 3:
Liệt kê 3. ParseUser — đăng ký
ParseUser user = new ParseUser();
user.setUsername("eortiz");
user.setPassword("123456");
user.setEmail("eortiz@nospam.com");
user.put("userType", "Author"); // add another field
// Call the asynchronous background method to sign up
user.signUpInBackground(new SignUpCallback() {
public void done(ParseException e) {
if (e == null) {
// Successful. Allow access to app.
} else {
// Failed....
}
}
});
Trường username và email phải là duy nhất. Nếu một trường username hoặc email
đã được sử dụng rồi, thì cuộc gọi đăng ký sẽ thất bại. Bạn nên có một cơ chế để
thông báo cho người dùng biết khi có một trong hai trường thất bại, cũng như một
quá trình để thử lại.
Sau khi đăng ký, người dùng có thể đăng nhập vào ứng dụng của bạn, như trong
Liệt kê 4:
Liệt kê 4. ParseUser — đăng nhập
ParseUser.logInInBackground("eortiz", "123456", new LogInCallback() {
public void done(ParseUser user, ParseException e) {
if (user != null) {
// Successful. Allow access to app.
} else {
// Failed
}
}
});
Bạn có thể cập nhật thông tin người dùng bằng cách gọi ParseUser.save(). Tuy
nhiên, hãy nhớ rằng chỉ chủ sở hữu của ParseUser mới có thể sửa đổi nội dung của
nó; còn những người khác chỉ có thể xem mà không thể chỉnh sửa.
Parse lưu trữ trong bộ nhớ đệm người dùng hiện đã đăng nhập. Bạn có thể truy vấn
người dùng hiện tại bằng cách gọi ParseUser.currentUser(). Phương thức
currentUser cho phép bạn nhanh chóng truy cập thông tin người dùng hiện tại, do
đó bạn chỉ cần nhắc lại các thông tin đăng nhập nếu phiên làm việc của người dùng
hiện tại không hoạt động. Liệt kê 5 cho thấy cách lấy ra thông tin người dùng hiện
tại trong Parse:
Liệt kê 5. ParseUser — nhận được thông tin người dùng hiện tại
ParseUser currentUser = ParseUser.getCurrentUser();
if (currentUser != null) {
// current user is valid
} else {
// current user not valid, ask for credentials
}
Thiết lập lại một người dùng hiện tại
Bạn có thể thiết lập lại một người dùng hiện tại trong Parse bằng cách gọi
ParseUser.logOut(), như trong Liệt kê 6:
Liệt kê 6. ParseUser — thiết lập lại người dùng hiện tại (đăng xuất)
ParseUser.logOut(); // static method
Các Parse ACL
Một ACL là một danh sách các giấy phép truy cập (hoặc các quyền điều khiển truy
cập) gắn liền với một đối tượng dữ liệu. Lớp ParseACL cho phép bạn định nghĩa
các giấy phép cho một ParseObject cụ thể. Với các ACL, bạn có thể định nghĩa
quyền truy cập công khai vào các đối tượng dữ liệu ứng dụng của mình và bạn có
thể hạn chế quyền truy cập cho những người dùng hoặc các nhóm những người
dùng (thông qua các vai trò) cụ thể. Liệt kê 7 trình bày việc sử dụng các Parse
ACL (ACL của Parse):
Liệt kê 7. Sử dụng lớp ParseACL để có các giấy phép truy cập
// Define a Parse user
ParseUser user = new ParseUser();
user.setUsername(username);
:
:
// Define a read/write ACL
ParseACL rwACL = new ParseACL();
rwACL.setReadAccess(user, true); // allow user to do reads
rwACL.setWriteAccess(user, true); // allow user to do writes
:
:
// Define a Parse object and its ACL
ParseObject gameObject = new ParseObject("Game");
gameObject.setACL(rwACL); // allow user do read/writes on gameObject
gameObject.saveInBackground(); // save the ACL'ed object to the cloud
:
:
// You can define a public ACL that gives public access to the object
ParseACL publicACL = new ParseACL();
publicACL.setPublicReadAccess(true);
publicACL.setPublicWriteAccess(true);
gameObject.setACL(publicACL); // allow public read/writes
gameObject.saveInBackground(); // save the ACL'ed object to the cloud
Bạn cũng có thể định nghĩa một ACL mặc định cho tất cả các đối tượng mới được
tạo ra. Trong Liệt kê 8 tôi đã thiết lập ACL mặc định là công khai cho các lần đọc
và viết, như publicACL đã định nghĩa trong Liệt kê 7.
Liệt kê 8. Thiết lập ACL mặc định
// Set a default ACL for all newly created objects as public access
ParseACL.setDefaultACL(publicACL, true);
Mặc dù không trình bày ở đây, nhưng chúng ta vẫn có thể sử dụng lớp ParseRole
để cấp các giấy phép truy cập cho các nhóm những người dùng.
Tiếp theo, chúng ta sẽ xem xét cách lưu và lấy ra các đối tượng dữ liệu Parse từ
Parse cloud.
Các đối tượng dữ liệu Parse trên đám mây
Một khi bạn đã tạo ra và điền vào một ParseObject, bạn có thể lưu nó trên Parse
cloud. Việc lưu các đối tượng dữ liệu trên Parse cloud thực sự là một trong những
điều đơn giản nhất để làm với Parse; Parse hoàn toàn che giấu đi sự phức tạp
thường liên quan đến việc biểu diễn dữ liệu, sắp xếp dữ liệu (marshaling), truyền
thông mạng và vận chuyển và v.v. Bạn sẽ cần sử dụng các phương thức của trình
trợ giúp để ánh xạ cá thể đối tượng dữ liệu của mình vào một ParseObject và
ngược lại và bạn sẽ cần quyết định xem bạn có muốn gửi hoạt động lưu trữ của
Parse trên luồng riêng của mình không hoặc có sử dụng lưu trữ theo phương thức
nền không.
Hãy coi chừng chặn luồng hệ thống!
Hãy nhớ lại rằng trong các ứng dụng di động, không nên thực hiện các hoạt động
kéo dài như hoạt động mạng, hoạt động tệp hoặc các tính toán dài dòng trên luồng
hệ thống chính. Thay vào đó, hãy thực hiện các hoạt động đó trong một luồng công
việc riêng biệt. Việc chặn luồng hệ thống sẽ ảnh hưởng tiêu cực đến đáp ứng giao
diện người dùng của ứng dụng, có khả năng dẫn đến ứng dụng của bạn bị buộc
phải đóng lại.
ParseObject cung cấp hai loại trong số các phương thức lưu trữ: save() và
saveInBackground(). saveInBackground() (lưu trữ trong nền) là phương thức lưu
trữ nên dùng do nó chạy hoạt động lưu trữ trên luồng công việc riêng của nó. Nếu
bạn chọn sử dụng phương thức save() (lưu) đồng bộ, hãy hiểu rõ rằng việc gọi
phương thức này trên luồng công việc của riêng nó để ngăn giao diện người dùng
không chặn luồng hệ thống là trách nhiệm của bạn.
Liệt kê 9 cho thấy mã để lưu một đối tượng dữ liệu Parse trong nền:
Liệt kê 9. Lưu ParseObject trong nền
// ParseObject
ParseObject pObject = new ParseObject("ExampleObject");
pObject.put("myNumber", number);
pObject.put("myString", name);
pObject.saveInBackground(); // asynchronous, no callback
Còn Liệt kê 10 cho thấy mã dùng để lưu một đối tượng dữ liệu Parse trong nền với
một cuộc gọi lại:
Liệt kê 10. Lưu trong nền với cuộc gọi lại
pObject.saveInBackground(new SaveCallback () {
@Override
public void done(ParseException ex) {
if (ex == null) {
isSaved = true;
} else {
// Failed
isSaved = false;
}
}
});
Các biến thể của phương thức save...() bao gồm:
saveAllinBackground() lưu một ParseObject có hoặc không có một cuộc gọi
lại.
saveAll(List objects) lưu một danh sách các ParseObject.
saveAllinBackground(List objects) lưu một danh sách các
ParseObject trong nền.
saveEventually() cho phép bạn lưu một đối tượng dữ liệu vào máy chủ tại
một thời điểm nào đó trong tương lai; sử dụng phương thức này nếu Parse
cloud hiện tại không thể truy cập được.
Khi một ParseObject đã được lưu thành công trên Đám mây, nó được gán cho một
mã định danh đối tượng (Object-ID) duy nhất. Object-ID này là rất quan trọng vì
chỉ có nó mới nhận ra được cá thể ParseObject đó. Bạn sẽ sử dụng Object-ID, ví
dụ, để xác định xem đối tượng đã được lưu thành công trên đám mây chưa, để lấy
ra và làm mới một cá thể đối tượng Parse đã cho và để xóa một ParseObject cụ thể.
Lấy ra các đối tượng dữ liệu từ đám mây
Phần này xem xét các phương thức để truy vấn và lấy ra các đối tượng dữ liệu đã
lưu trên Parse cloud. Bạn có thể truy vấn một ParseObject đơn lẻ theo object-ID
hoặc bạn có thể truy vấn một hoặc nhiều đối tượng Parse bằng cách sử dụng các
thuộc tính. Nếu bạn đã có một ParseObject rồi, bạn có thể làm mới hoặc đồng bộ
hóa các nội dung của nó bằng cách tìm nạp các giá trị mới nhất từ máy chủ. Chúng
tôi sẽ xem xét tất cả các tùy chọn này trong các đoạn mã sau đây.
Tìm nạp các ParseObject
Để tìm nạp một đối tượng dữ liệu từ đám mây Parse, hãy sử dụng phương thức của
ParseObject là fetch() (tìm nạp) hoặc fetchInBackground() (tìm nạp trong nền),
được hiển thị trong Liệt kê 11:
Liệt kê 11. Tìm nạp (vô điều kiện)
// ParseObject
ParseObject pObject = new ParseObject("ExampleObject");
:
:
// Fetch the parse object unconditionally
try {
pObject.fetch();
} catch (ParseException e) {
e.printStackTrace();
}
// Fetch the parse object unconditionally, with Callback
pObject.fetchInBackground(new GetCallback() {
@Override
public void done(ParseObject obj, ParseException ex) {
if (ex == null) {
// Success
} else {
// Failed
}
}
});
Bạn cũng có thể tìm nạp chỉ khi cần; ví dụ, khi tìm nạp một đối tượng Parse có các
đối tượng Parse liên quan, như trong Liệt kê 12:
Liệt kê 12. Tìm nạp khi cần
ParseObject po = new ParseObject("ExampleObject");
:
ParseObject po2 = po.getParseObject("key");
// Fetch only if needed
try {
po2.fetchIfNeeded();
} catch (ParseException e) {
e.printStackTrace();
}
Một lựa chọn khác là thực hiện một hoạt động tìm nạp nếu cần trong nền và với
một cuộc gọi lại. Về việc này, bạn nên sử dụng phương thức đối tượng Parse là
fetchIfNeededInBackground(GetCallback callback).
Trong một số trường hợp, bạn sẽ cần tìm nạp một bộ sưu tập của các đối tượng
Parse cùng một lúc, vô điều kiện hoặc chỉ khi cần. ParseObject cung cấp một tập
hợp các phương thức tĩnh để làm việc này; mỗi phương thức tĩnh nhận đầu vào là
một danh sách các đối tượng Parse và sau đó trả về một danh sách các đối tượng
Parse:
fetchAll(List objects)
fetchAllIfNeeded(List objects)
fetchAllIfNeededInBackground(List objects, FindCallback
callback)
fetchAllInBackground(List objects, FindCallback callback)
Truy vấn các đối tượng dữ liệu trên đám mây
Giờ đây, hy vọng bạn đã thấy rằng Parse API rất toàn diện — nhưng hãy chờ xem,
bởi vì còn có nhiều điều hay ho hơn nữa! Ngoài việc tìm nạp các đối tượng dữ liệu,
Parse cũng cho phép bạn truy vấn các đối tượng dữ liệu bằng cách sử dụng object-
ID hoặc các thuộc tính. Để truy vấn một đối tượng dữ liệu từ đám mây Parse, hãy
sử dụng lớp ParseQuery. Bạn có thể sử dụng lớp ParseQuery cho cả hai các truy
vấn dữ liệu cơ bản và các truy vấn dữ liệu phức tạp, thu nhận lại một đối tượng đã
cho hoặc một List (Danh sách) các đối tượng phù hợp.
Liệt kê 13 cho thấy cách lấy ra một đối tượng Parse cụ thể từ máy chủ trong một
luồng nền, dựa vào một object-ID:
Liệt kê 13. Sử dụng lớp ParseQuery để lấy ra một ParseObject đã cho
String myID = "12345";
ParseQuery query = new ParseQuery("Players");
query.getInBackground(myID, new GetCallback() {
@Override
public void done(ParseObject object, ParseException e) {
if (object != null) {
// Get object
} else {
// Not found
}
}
});
Lưu ý query.getInBackground() không sử dụng bộ nhớ đệm ParseQuery.
Liệt kê 14 cho thấy một truy vấn để lấy ra tất cả các đối tượng dữ liệu của lớp:
Players. (Không cung cấp sự ràng buộc nào).
Liệt kê 14. Sử dụng lớp ParseQuery cho tất cả các ParseObject của một lớp đã cho
ParseQuery query = new ParseQuery("Players");
query.findInBackground(new FindCallback() {
@Override
public void done(List players, ParseException e) {
if (players != null) {
// Get list of players
} else {
// No players
}
}
});
ITrong Liệt kê 15, tôi đã sử dụng một sự ràng buộc truy vấn để lấy ra một hoặc
nhiều đối tượng Parse phù hợp; trong trường hợp này ParseObject là Players đang
hoạt động (active):
Liệt kê 15. Sử dụng lớp ParseQuery để lấy ra các ParseObject phù hợp
ParseQuery query = new ParseQuery("Players");
query.whereEqualTo("status", "active");
query.findInBackground(new FindCallback() {
@Override
public void done(List players, ParseException e) {
if (players != null) {
// Success - players contain active players
} else {
// Failed
}
}
});
Lớp ParseQuery cũng cung cấp một phương thức để nhận được tổng số đếm của
các đối tượng phù hợp mà không cần lấy ra chính các đối tượng đó, điều này rất có
ích. Liệt kê 16 cho thấy cách nhận được tổng số đếm của players đang hoạt động:
Liệt kê 16. Sử dụng lớp ParseQuery để đếm các ParseObject phù hợp
ParseQuery query = new ParseQuery("Players");
qu