Parse SDK:里面到底有什么寶貝?

jopen 9年前發布 | 7K 次閱讀 Parse SDK

Parse SDK 已經是,也是一直以來手機在 Parse 開發方面很重要的一部分。作為移動 Parse 的開發者,你應該已經從公共 API 處獲得了 Parse 的 SDK,但今天我們開源了我們的 SDK,這樣你最終有機會能夠看一下其內部是如何運作的。

在這篇文章中,我們將分解我們在構建 Parse SDK 過程中的一些最具挑戰性的方面——構建異步的API,解耦架構已經實現 API 的一致性。在接下來的幾周里,我們將發表一系列的博客文章來深入介紹我們 SDK 的方方面面。

異步 API

一些 Parse SDK 中的重要功能包括網絡通信,數據存儲,以及返回數據給開發者用于更新其 UI。所有這些都必須在異步中進行,分離于主線程并行。知道了這些你應該不會驚訝于我們的 SDK 中最重要的部分居然是如何做異步編程。去年,我們發布了 Tasks,作為 Bolts 的一部分,這是一個基于約定的拼裝起來的庫,其簡化了并行性與并發性。我們提到這個是因為我們在內部使用其來解決一些并發問題,但你現在可以看它的擴展部分。

我們所有內部的 API 幾乎都是基于任務的。我們用其來簡化異步操作的串行執行,比如在服務器上保持一個 ParseObjects 的依賴鏈,同時簡化并行異步操作,比如保持非關聯 ParseObjects 的分支結構。 這已經強大到我們能夠將這兩個拼接到單個異步操作中了。

/*
  Saves a collection of objects in serial batches of leaf nodes.
 */public Task<Void> deepSaveAsync(List<ParseObject> objects) {
    if (hasCycle(objects)) {
        return Task.forError(new RuntimeException(“Unable to save a ParseObject with a relation to a cycle”));
    }
    Task<Void> task = Task.forResult(null);

    List<ParseObject> remaining = new ArrayList<>(objects);     while (remaining.size() > 0) {         List<ParseObject> batch = collectLeafNodes(objects);         remaining.removeAll(batch);

        // Execute each batch operation serially, awaiting until         // the previous has completed.         task = task.onSuccessTask((t) -> {         return saveAllAsync(batch);         });     }     return task;}/*   Saves batches of objects in parallel.  */public Task<Void> saveAllAsync(List<ParseObject> objects) {     if (objects.size() > MAX_BATCH_SIZE) {         // The collection of objects is too big for a single batch,         // so partition the collection and execute each batch         // in parallel.         List<List<ParseObject>> partitioned = Lists.partition(objects, MAX_BATCH_SIZE);         List<Task<Void>> tasks = new ArrayList<>();         for (List<ParseObject> partition : partitioned) {             tasks.add(saveAllAsync(partition);         }         return Task.whenAll(tasks);     }

    return executeBatchCommand(objects);}// * Abridged, for clarity</pre>

通過 Tasks 編寫異步 API 是一件輕而易舉的事情,并且我們非常建議您深入了解 Bolts 框架:Android, iOS/OS X 以及我們的SDKs:AndroidiOS/OS X

解耦架構和 API 的一致性

盡可能的延續 Parse SDK 的簡單易用的傳統是我們最優先的選擇。但是,這樣做很難既添加新的功能,還要讓我們的 SDK 更加穩定而不去改變傳統。此外,由于我們代碼級的增長,為了給我們的開發者發布最穩定的版本,我們需要確保我們的代碼可測試。

為了解決所有的這些問題,我們采取了解耦架構模塊,包括我們的公開的API對象實例,對象狀態,控制者和REST協議。每一塊都被封裝了,是為了確保關注分離和允許我們添加新功能的不同實現而不用修改太多的代碼。這是所有模塊如何在一起工作的示例圖


Parse SDK:里面到底有什么寶貝?
我們得解耦架構模塊

對象實例

對象實例是允許我們保持一個易用的和不變的 API 的片段,對于 ParseObject 來說是包涵屬性的 set,get 方法和保存,獲取和刪除方法的 API 表面層,只要我們保持這樣的完整性,我們可以在底層重構和添加新的功能而沒有任何破壞性的改變。

狀態

狀態涉及對象的內部狀態的組合,對 ParseObject 來說,狀態是指當前自身在服務器上的表示和在本地運行的變化的集合,也指在本地的狀態的當前表示的緩存.

這些狀態實例也定義了在對象實例和控制層交互里的接口。對象實例傳遞它的狀態給控制器,控制器返回一個新的狀態,然后對象實例用這個新的狀態更新自身。


控制器

控制器定義了可在每個 Parse 類型上執行的所有行為:ParseObject 可以被保存、獲取與刪除,ParseQuery 可以被查找與計數,ParseFile 可以被保存與獲取。

基礎控制器將序列化或反序列化對象狀態至公共的 REST 格式并且傳送所有的請求給內部邏輯網絡。 這就防止我們因為實現不必要的序列化和反序列化,而使得實例與狀態實現得更加復雜,同時提供了更好測試的代碼插入。

我們也設計了控制器的可擴展性來使除了 Parse 通信的其它功能能被添加。其中的實例就是局部數據存儲。對于這個新特性,我們可以創建另一個 ParseQueryController 的實現,而不是通過 Parse 在網絡上通信。這就需要這些對象在本地設備上。

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!