+1

[Parse]Bước cơ bản làm việc với Parse

Theo phương thức truyền thống thì khi lập trình viên mobile khi tạo ra 1 ứng dụng mà cần liên quan đến dữ liệu thì sẽ cần phải kèm theo một web developer để tạo 1 backend để có thể kết nối đến cơ sơ dữ liệu cũng như làm việc trên nó. Như vậy các lập trình viên di động sẽ cần phải đợi chờ backend và viết ra những service phục vụ cho công việc yêu cầu. Nếu cứ theo mô hình như vậy khi làm gì cũng phải phụ thuộc vào web develop và khi cần chỉnh sửa gì thì chỉ có đợi backend và đôi khi việc backend trả giá trị như thế nào thì chỉ biết như vậy. Điều này khiến cho các lập trình viên mobile khó linh động và luôn phải chờ đợi. Điều này giờ đã được giải quyết bằng cách các lập trình viên mobile sẽ làm việc trực tiếp qua 1 serice trung gian chuyên xử lý dự liệu là Parse. Trong bài viết này tôi xin hướng dẫn các bạn 1 cách cơ bản làm quen với việc sử dụng Parse cho việc lập trình cho mobile (Android) và Backend (Php).

Trước khi đi vào chi tiết tôi xin giới thiệu qua cho các bạn Parse là gì và hỗ trợ gì cho chúng ta. Bạn có thể vào trực tiếp trang chủ của Parse để có thể tìm hiểu cũng như đăng ký cho mình 1 tài khoản hoàn toàn miễn phí. Khi vào trang chủ của Parse chúng ta có thể thấy Parse cung cấp cho chúng ta 3 dịch vụ chính đó là:

  1. Xử lý dữ liệu: Sẽ cung cấp cho ứng dụng của bạn lưu trữ dữ liệu, làm việc dễ dàng với cơ sở dữ liệu đồng thời có thể dễ dàng trao đổi dữ liệu từ server đến Parse.
  2. Push notification: Đây là 1 dịch vụ rất tiện lợi cho các nhà phát triển mobile vì Parse cung cấp sẵn việc Push notification một cách tiện lợi và vô cùng đơn giản (Tôi sẽ nói rõ hơn khi hướng dẫn làm việc với Android).
  3. Thống kê: Đây là dịch vụ để nhà phát triển nắm bắt được sự phát triển của ứng dụng mình làm ra để có những phương án phát triển tiếp theo.

Một điều đáng nói nữa là Parse cung cấp cho lập trình viên bộ thư viện đầy đủ cho gần như toàn bộ các ngôn ngữ lập trình cho Mobile (iOs, Android, Windows Phone, Unity, Xamarin, ..), cho web hay ứng dụng desktop (OsX, Windows, Php, Unity,..). Thực sự mọi người lập trình viên đều có thể làm việc với Parse vì được cung cấp tài liệu hướng dẫn đầy đủ cho từng ngôn ngữ lập trình tại đây.

Để bắt tay vào làm quen với Parse tôi sẽ đưa ra 1 yêu cầu khá đơn giản đó là sẽ tạo ra 1 Object là Blog gồm các trường là name - author - content. Công việc yêu cầu phía backend (Php) thì cần quản trị được các Blog này và khi thêm mới sẽ gửi 1 thông báo về các client về Blog mới được thêm này. Còn về phía Client (Android App) sẽ hiển thị các Blog và hiển thị thông báo và click vào đó thì sẽ ra list các Blog gồm cả Blog mới được thêm.

Tạo app mới từ Parse

Sau khi đăng ký mới 1 tài khoản chúng ta đã bắt đầu có thể sử dụng Parse cho công việc của mình, đầu tiên ta cần tạo 1 app mới. Sau khi App mới được tạo ra thì tại màn hình quản lý App ta vào phần Setting rồi vào phần Keys.

Tại đây App sẽ sinh ra các Key cho mục đích làm việc của lập trình. Ví dụ như Backend Php sẽ cần đến Application Id, REST API KeyMaster Key, Android thì cần Application IDClinet Key

Backend

Để cài đặt và sử dụng Parse cho Php ta cần phải cài Composer trước sau đó tạo 1 file là composer.json có nội dung như sau:

{
    "require": {
       "parse/php-sdk" : "1.1.*"
    }
}

Sau đó download Parse bằng lệnh composer install . Sau khi chạy xong thì ta sẽ có thư viện Parse trong folder Vendor. Và ở đây để làm việc với Parse, tôi tạo thêm 1 file có tên là parse.php trong folder vendor vừa sinh ra. Nội dung file đó như sau

<?php
require "autoload.php";
//Load toàn bộ thư viện và các hàm của Parse
use Parse\ParseObject;
use Parse\ParseQuery;
use Parse\ParseACL;
use Parse\ParsePush;
use Parse\ParseUser;
use Parse\ParseInstallation;
use Parse\ParseException;
use Parse\ParseAnalytics;
use Parse\ParseFile;
use Parse\ParseCloud;
use Parse\ParseClient;

class Parse
{
  //Để chạy được Parse thì cần 3 thông số được nhập ở dưới đây là app_id, rest_id và master_id
  private $_app_id = '';
  private $_rest_key = '';
  private $_master_key = '';
  private $_object_name = '';

  //Khởi tạo class với tên của Object, tên Object có thể để trống
  public function __construct($sObject = '')
  {
      $this->_object_name = $sObject;
      $this->init();
  }
  //Hàm khởi tạo Parse
  public function init()
  {
      ParseClient::initialize($this->_app_id, $this->_rest_key, $this->_master_key);
  }
  /**
  Hàm gửi push notification đến mọi máy di động có sử dụng đến Parse
  $sMessage: Là nội dung thông báo gửi đến các máy client.
  Parse có cung cấp cho người dùng gửi push notification đến những người dùng chọn lọc và có 2 cách chọn lọc là Chanel và Advance Targeting.
  Ở đây là dùng cách Advancer Targetting với việc gửi cho tất cả các máy
  */
  public function sendPushNotification($sMessage)
  {
      $data = array("alert" => $sMessage);
      $this->init();
      $query = ParseInstallation::query();
      ParsePush::send(array(
        "where" => $query,
        "data" => $data
      ));
  }
  /**
  Hàm thêm dữ liệu vào object, dữ liệu truyền vào là các mảng với key là filed và value là giá trị còn đưa vào
  Hàm trả về id của object do Parse sinh ra
  */
  public function add($aVals = [])
  {
      $oObject = new ParseObject($this->_object_name);
      foreach ($aVals as $sField => $val) {
          $oObject->set($sField, $val);
      }
      try {
          $oObject->save();
          return $oObject->getObjectId();
      } catch (ParseException $ex) {
          return false;
      }
  }

  /**
    Hàm lấy tất cả dữ liệu của 1 Object
  */
  public function getList()
  {
      $query = new ParseQuery($this->_object_name);
      $results = $query->find();
      return $results;
  }
  /**
    Hàm lấy toàn bộ thông tin của 1 Item vừa vào Id của Parse đã cung cấp lúc thêm mới
    Hàm trả về là 1 Object
  */
  public function getItemById($sObjectId)
  {
      $query =  new ParseQuery($this->_object_name);
      return $query->get($sObjectId);
  }
  /**
    Hàm cập nhật dữ liệu vào object, dữ liệu truyền vào là các mảng với key là filed và value là giá trị còn đưa vào
    Hàm trả về item với thông tin mới cập nhật
  */
  public function update($aVals, $sObjectId)
  {
      if ($oObject = $this->getItemById($sObjectId)) {
          foreach ($aVals as $sField => $val) {
              $oObject->set($sField, $val);
          }
          $oObject->save();
      }
      return $oObject->fetch();
  }
  /**
    Xóa 1 item từ database với id của Parse
  */
  public function delete($sObjectId)
  {
      if ($oObject = $this->getItemById($sObjectId)) {
          $oObject->destroy();
      }
      return true;
  }
}

Giờ khi cần làm việc với Parse ta chỉ cần thêm dòng require "vendor/parse.php";. Theo yêu cầu của đề bài đưa ra thì chúng ta sẽ cần 2 trang là màn hình danh sách các Blog và xóa từng Blog và màn hình thứ 2 cho việc thêm mới, sửa xóa Blog. Tương ứng với 2 trang này tôi tạo ra 2 file index.phpadd.php.

File index.php

Trang này sẽ thực hiện 2 chức năng là hiển thị toàn bộ Blog đã được thêm và, với mỗi Blog sẽ có 2 đường link để sửa và xóa từng Blog, và thêm 1 đường link để thêm mới Blog. Để xóa 1 Blog thì sẽ cần gửi đến link của file này với biến là delete có giá trị là id của Blog này lấy từ dữ liệu trả về từ Parse và sau khi xóa xong thì hiển thị danh sách mới. Tương tự link để update Blog này sẽ sang file app.php với id là Id của Blog này.

Tại đây ta có thể mỗi Item mà Parse trả về đều ở dạng Object và muốn lấy các trường trong đấy ta dùng đến hàm get(tên trường), tuy nhiên có 3 hàm đặc biệt riêng của Parse đó là

  • Hàm getObjectId() là để lấy id của Item.
  • Hàm getUpdatedAt() lấy thời điểm cập nhật gần nhất.
  • Hàm getCreatedAt() lấy thời gian tạo ra Item.
<?php
//Load parse class
require "vendor/parse.php";

//Khởi tạo Object Blog
$oBlogs = new Parse('Blog');

//Kiểm tra xem có truyền biến delete hay không và lưu giá trị này vào biến $iDeleteId
if (isset($_GET['delete']) && $iDeleteId = $_GET['delete']) {
  //Xóa Blog khỏi database
  $oBlogs->delete($iDeleteId);
  //Quay lại trang index.php
  header('location: index.php');
}
$aBlogs = $oBlogs->getList();
?>
<!DOCTYPE html>
<html>
  <head>
    <title>Parse sample</title>
  </head>
  <body>
    <h1>Parse Sample - Viblo</h1>
    <ul>
        <?php foreach($aBlogs as $aBlog) { ?>
            <li>
                <?php
                echo $aBlog->get('name');?>
                <a href="add.php?id=<?php echo $aBlog->getObjectId() ?>">Edit</a>
                <a href="?delete=<?php echo $aBlog->getObjectId() ?>">Delete</a>
            </li>
         <?php } ?>
    </ul>
    <a href="add.php">Add</a>
  </body>
</html>

File add.php

Trang này thực hiện chức năng thêm mới và sửa một Blog. Sự khác nhau giữa thêm mới và sửa là khi gửi đi sẽ có thêm biến Id trên đường dẫn gửi đến file này. Và sau khi thêm mới thành công sẽ thêm 1 push notification với nội dung thông báo có 1 Blog mới và có tên của Blog. Và sau khi thực hiện thì chuyển về trang index.php

<?php
require "vendor/parse.php";
//Load class Parse
$oBlog = new Parse('Blog');

// Kiểm tra xem có biến Id gửi đến không.
if (isset($_GET['id']) && $iId = $_GET['id']) {
    //Lấy thông tin của 1 Blog theo Id gửi đến
    $aBlog = $oBlog->getItemById($iId);
}

//Kiểm tra xem có phải gửi có gửi dữ liệu từ Form lên không?
if ($aVals = $_POST) {
    //Kiểm tra xem có phải đang chỉnh sửa
    if (isset($iId)) {
        //Cập nhật BLog
        $oBlog->update($aVals, $aVals['id']);
    } else {
        //Thêm mới BLog
        $oBlog->add($aVals);
        //Gửi pushs notification
        $oBlog->sendPushNotification('Parse have new blog "' . $aVals['name'] . '"');
    }
    //Chuyển về trang index.php
    header('location: index.php');
}

?>
<!DOCTYPE html>
<html>
  <head>
      <title>Parse sample</title>
  </head>
  <body>
      <h1>Parse Sample - Viblo</h1>
      <form method="POST">
          <table>
              <tr>
                  <td>Name :</td>
                  <td>
                      <input name="name" value="<?php if (isset($aBlog)) echo $aBlog->name;?>">
                      <?php if (isset($aBlog)) { ?>
                          <input type="hidden" name="id" value="<?php echo $aBlog->getObjectId(); ?>">
                      <?php } ?>
                  </td>
              </tr>
              <tr>
                  <td>Author :</td>
                  <td><input name="author"value="<?php if (isset($aBlog)) echo $aBlog->author;?>"></td>
              </tr>
              <tr>
                  <td>Content :</td>
                  <td><input name="content"value="<?php if (isset($aBlog)) echo $aBlog->content;?>"></td>
              </tr>
              <tr>
                  <td colspan="2">
                      <input type="submit" value="Submit">
                  </td>
              </tr>
          </table>
      </form>
  </body>
</html>

Client

Trong bài này, chúng ta sẽ viết app cho Android sử dụng Android Studio với SDK version 19 tương đương với Android 4.4. Để sử dụng thư viện của Parse thì cần thêm vào file guild.gradle đoạn code sau:

    compile 'com.parse.bolts:bolts-android:1.+'
    compile 'com.parse:parse-android:1.+'

Sau khi thêm dòng đó thì để kết nối được đến Parse thì bạn cần chạy đoạn code này:

  Parse.initialize(this, "{app_id}", "{client_id}");
  ParseInstallation.getCurrentInstallation().saveInBackground();

Và đoạn code này chúng ta cần đưa vào file Application của Android vì Plugin Parse chỉ cần được load 1 lần duy nhất. Và để load duy nhất 1 lần chúng ta cần tạo 1 file và extends đến class Application của Android và trong file AndroidManifest.xml khai báo thêm tên file class đó. Cụ thể ta sẽ tạo 1 file là ParseApplication.java với nội dung như sau:

package com.example.framgianguyenquanghuy.parsesample;

import android.app.Application;

import com.parse.Parse;
import com.parse.ParseInstallation;

/**
* Created by FRAMGIA\nguyen.quang.huy on 26/11/2015.
*/
public class ParseApplication extends Application {
  @Override
  public void onCreate() {
      super.onCreate();
      Parse.initialize(this, "{app_id}", "{client_id}");
      ParseInstallation.getCurrentInstallation().saveInBackground();
  }
}

File AndroidManifest.xml

Đây là file thiết lập các cấu hình cho app. Như đã nói ở trên thì ta cần phải khai báo thêm một thuộc tính để chỉ load Plugin Parse một lần khi chạy app, ta cần thêm thuộc tính name trong thẻ application. Và cũng để chạy được chức năng push notification thì theo tài liệu này thì ta cần làm các bước sau: Thêm đoạn dưới đây trong thẻ application:

<service android:name="com.parse.PushService" />
<receiver android:name="com.parse.ParsePushBroadcastReceiver"
    android:exported="false">
  <intent-filter>
    <action android:name="com.parse.push.intent.RECEIVE" />
    <action android:name="com.parse.push.intent.DELETE" />
    <action android:name="com.parse.push.intent.OPEN" />
    </intent-filter>
</receiver>
<receiver android:name="com.parse.GcmBroadcastReceiver"
    android:permission="com.google.android.c2dm.permission.SEND">
  <intent-filter>
    <action android:name="com.google.android.c2dm.intent.RECEIVE" />
    <action android:name="com.google.android.c2dm.intent.REGISTRATION" />

    <category android:name="com.parse.starter" />
  </intent-filter>
</receiver>

và thay đổi thuộc tính android:name trong thẻ category bằng tên của app. Tức là thay tên của app vào đoaạn <category android:name="com.parse.starter" />.

Để chạy được push notification cho app thì cũng cần phải thêm bên ngoài thẻ application như sau:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

<permission android:protectionLevel="signature"
    android:name="com.parse.starter.permission.C2D_MESSAGE" />
<uses-permission android:name="com.parse.starter.permission.C2D_MESSAGE" />

và cũng thay đổi thuộc tính android:name cho 2 thẻ dưới thành tên của app. Như vậy nội dung của file AndroidManifest.xml sẽ như sau:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.framgianguyenquanghuy.parsesample" >
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />

    <permission android:protectionLevel="signature"
        android:name="com.example.framgianguyenquanghuy.parsesample.permission.C2D_MESSAGE" />
    <uses-permission android:name="com.example.framgianguyenquanghuy.parsesample.permission.C2D_MESSAGE" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        android:name=".ParseApplication">

        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service android:name="com.parse.PushService" />
        <receiver android:name="com.parse.ParsePushBroadcastReceiver"
            android:exported="false">
            <intent-filter>
                <action android:name="com.parse.push.intent.RECEIVE" />
                <action android:name="com.parse.push.intent.DELETE" />
                <action android:name="com.parse.push.intent.OPEN" />
            </intent-filter>
        </receiver>
        <receiver android:name="com.parse.GcmBroadcastReceiver"
            android:permission="com.google.android.c2dm.permission.SEND">
            <intent-filter>
                <action android:name="com.google.android.c2dm.intent.RECEIVE" />
                <action android:name="com.google.android.c2dm.intent.REGISTRATION" />

                <category android:name="com.example.framgianguyenquanghuy.parsesample" />
            </intent-filter>
        </receiver>
    </application>
</manifest>

Sau khi khai báo xong chúng ta có thể thử test push notification tại trang web quản lý app của Parse.

File Blog.java

Để làm việc với Blog ta cần khai báo 1 class để lưu trữ các thuộc tính của Blog đó. Nội dung file Blog như sau

package com.example.framgianguyenquanghuy.parsesample;

/**
 * Created by FRAMGIA\nguyen.quang.huy on 26/11/2015.
 */
public class Blog {
    public Blog(String _name, String _author, String _content) {
        this._name = _name;
        this._author = _author;
        this._content = _content;
    }
    public String _name;

    public String get_name() {
        return _name;
    }

    public void set_name(String _name) {
        this._name = _name;
    }

    public String _author;

    public String get_author() {
        return _author;
    }

    public void set_author(String _author) {
        this._author = _author;
    }

    public String _content;

    public String get_content() {
        return _content;
    }

    public void set_content(String _content) {
        this._content = _content;
    }

}

Các file trình bày XML

Theo đề bài ta đặt ra thì ở app sẽ hiển thị list các Blog và sẽ hiển thị dưới dạng List View. Và trong app này có 3 file ta cần làm đó là activity_main.xml, content_mail.xmlitem.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=".MainActivity">

    <android.support.design.widget.AppBarLayout android:layout_height="wrap_content"
        android:layout_width="match_parent" 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.FloatingActionButton android:id="@+id/fab"
        android:layout_width="wrap_content" android:layout_height="wrap_content"
        android:layout_gravity="bottom|end" android:layout_margin="@dimen/fab_margin"
        android:src="@android:drawable/ic_dialog_email" />

</android.support.design.widget.CoordinatorLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:showIn="@layout/activity_main" tools:context=".MainActivity">

    <ListView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/listBlogs"
        android:layout_alignParentTop="true"
        android:layout_alignParentStart="true" />
</RelativeLayout>

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/blog_item">
    <TextView
        android:id="@+id/name"
        android:layout_width="fill_parent"
        android:layout_height="match_parent" />
    <TextView
        android:id="@+id/author"
        android:layout_width="fill_parent"
        android:layout_height="match_parent" />
    <TextView
        android:id="@+id/content"
        android:layout_width="fill_parent"
        android:layout_height="match_parent" />

</LinearLayout>
File MainActivity.java

Đây là file xử lý dữ liệu giống như lớp Controller. Và ở đây khi gọi đến file này sẽ gọi tất cả Blog ra sau đó điền vào adapter là danh sách các Blog được khai báo trong file Blog.java và hiển thị ra màn hình kết quả.

package com.example.framgianguyenquanghuy.parsesample;

import android.content.Context;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;

import com.parse.ParseQuery;
import com.parse.ParseObject;
import com.parse.FindCallback;
import com.parse.ParseException;
import com.parse.PushService;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ArrayList<Blog> aBlogs = new ArrayList<Blog>();
        final BlogAdapter adapter = new BlogAdapter(this, aBlogs);

        ParseQuery<ParseObject> query = ParseQuery.getQuery("Blog");

        query.findInBackground(new FindCallback<ParseObject>() {
            public void done(List<ParseObject> scoreList, ParseException e) {
                if (e == null) {
                    for (int i = 0; i < scoreList.size(); i++) {
                        ParseObject item = scoreList.get(i);
                        Blog aItem = new Blog(item.getString("name"), item.getString("author"), item.getString("content"));
                        adapter.add(aItem);
                    }

                } else {
                    Log.d("score", "Error: " + e.getMessage());
                }
            }
        });
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        ListView listView = (ListView) findViewById(R.id.listBlogs);
        listView.setAdapter(adapter);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    public class BlogAdapter extends ArrayAdapter<Blog> {
        public BlogAdapter(Context context, ArrayList<Blog> blogs) {
            super(context, 0, blogs);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            // Get the data item for this position
            Blog blog = getItem(position);
            // Check if an existing view is being reused, otherwise inflate the view
            if (convertView == null) {
                convertView = LayoutInflater.from(getContext()).inflate(R.layout.item, parent, false);
            }
            // Lookup view for data population
            TextView tvName = (TextView) convertView.findViewById(R.id.name);
            TextView tvHome = (TextView) convertView.findViewById(R.id.author);
            // Populate the data into the template view using the data object
            tvName.setText(blog.get_name());
            tvHome.setText(blog.get_author());
            // Return the completed view to render on screen
            return convertView;
        }
    }
}

Kết

Trên đây chỉ là 1 bài ứng dụng rất đơn giản về cách làm việc với Parse để cho thấy được cách thức hoạt động ra sao cũng như tiện lợi đem lại. Như vậy ta có thể thấy lập trình viên di động sẽ hoàn toàn chủ động với việc làm việc với dữ liệu mà không phải chờ đợi phía backend. Tuy nhiên có những điều bất lợi khi làm việc với Parse đó là việc cần phải có sự thống nhất về dữ liệu giữa các lập trình viên, vì dữ liệu của Parse là dưới dạng No-Sql nên nếu thiếu sự đồng nhất làm cho gây ra nhiều xáo trộn. Tiếp nữa là do liên kết dến bên thứ 3 do vậy cũng phụ thuộc vào bên Parse nếu có nâng cấp thì app cũng gần như dừng hoạt động. Như vậy, Parse phù hợp cho việc phát triên app mà it làm việc với cơ sở dữ liệu.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí