<wbr id="jl7f7"></wbr>

        <i id="jl7f7"></i>
          <acronym id="jl7f7"></acronym>

          <s id="jl7f7"></s>

          <ins id="jl7f7"></ins><button id="jl7f7"><strong id="jl7f7"></strong></button>
          鍍金池/ 教程/ Android/ Compiled repositories
          Custom observables
          Compiled functions
          Reactive programming
          Reservoirs and parallelism
          Incrementally Agerifying legacy code
          Observables and updatables
          Compiled repositories
          Repositories

          Compiled repositories

          復雜的repository可以用單個(gè)Java表達式編譯出來(lái)。
          Java表達式由下面幾部分構成,順序如下:

          // 聲明RepositoryCompiler,并初始化,返回REventSource實(shí)例;
          1. `Repositories.repositoryWithInitialValue(...)`;
          // 指定事件源(Observable),可以多個(gè),返回RFrequency實(shí)例;
          2. Event sources - `.observe(...)`;
          // 設置通知頻率(比如click頻率限制),返回RFlow實(shí)例;
          3. Frequency of reaction - `.onUpdatesPer(...)` or `.onUpdatesPerLoop()`;
          // 設置數據源(Supplier),返回RFlow或RTermination實(shí)例;
          4. Data processing flow - `.getFrom(...)`, `.mergeIn(...)`, `.transform(...)`, etc.;
          // 其他配置,返回RConfig;
          5. Miscellaneous configurations - `.notifyIf(...)`, `.onDeactivation(...)`, etc.;
          // 編譯成Repository實(shí)例。
          6. `.compile()`.

          當compiled repository運行時(shí), 先將指定當事件源注冊?xún)炔康膗pdatable,同時(shí)啟動(dòng)數據處理流程來(lái)計算為首次準備的值。 當從事件源收到事件的時(shí)候,這個(gè)數據處理流程會(huì )再次啟動(dòng)來(lái)更新值以響應。

          在第一次計算結果完成之前,repository將使用初始值(repositoryWithInitialValue()方法設置的初始值)作為數據。 當數據一旦有更新時(shí),repository的觀(guān)察者們都會(huì )收到通知。當不活動(dòng)時(shí),事件源將注銷(xiāo)內部的updatable,數據處理流程不再運行,所以數據會(huì )變成舊的。重新活動(dòng)后,數據會(huì )重新保持最新的。

          The different stages of this expression are represented by the “compiler state interfaces” nested in RepositoryCompilerStates, 表達式的不同階段都返回RepositoryCompilerStates中內嵌的接口(compiler state interfaces)對象,這樣可以每個(gè)階段只暴露合適的方法, 引導開(kāi)發(fā)者完成正確的表達式(使用IDE自動(dòng)完成時(shí))。

          這些方法的完整文檔可以在這些接口中找到;特別的部分:

          • 事件源和響應頻率: RFrequencyREventSource
          • 數據處理流程: RFlowRSyncFlow
          • 其它配置: RConfig

          repository編譯表達式不能從中間斷開(kāi),企圖將中間結果存到本地變量或者強制轉換(cast)為另一個(gè)接口,這些方法都不支持。

          編譯repository會(huì )導致一些開(kāi)銷(xiāo), 但之后的操作相當輕量級。repository最適合與高級組件的生命周期進(jìn)行綁定,例如Activity、可重用的視圖或者一個(gè)為整個(gè)應用服務(wù)的全局單例。

          由于編譯的開(kāi)銷(xiāo),編譯repository確實(shí)如此(還是會(huì )在運行時(shí)發(fā)生編譯情況)。

          When, where, what

          compiled repository表達式清晰的說(shuō)明了什么時(shí)候(when)響應事件, 在什么線(xiàn)程(where)上響應事件, 提供什么數據(what)。 compiled repository指定的事件源和發(fā)生頻率,這兩個(gè)就是repository什么時(shí)候(when)響應事件的概念。

          數據處理流程指定原數據(依賴(lài))和計算出repository的數據,這就是repository提供什么數據(what)的概念。

          由于內部使用了updatable, 必須在有Looper線(xiàn)程上被注冊到事件源, compiled repository關(guān)聯(lián) worker Looper (下一篇詳細介紹 Asynchronous programming)。

          數據處理過(guò)程中,指令可以轉交給Java執行器執行,這些明確的線(xiàn)程結構就是repository(where)的概念。

          Data processing flow

          整個(gè)數據處理流程由指令組成,每一個(gè)指令接受一個(gè)輸入值,并為下一條產(chǎn)生一個(gè)輸出值。 第一條指令的輸入值類(lèi)型是repository的數據類(lèi)型,最后一條指令也是輸出相同類(lèi)型的數據。 compiler狀態(tài)接口使用泛型參數有助于保證類(lèi)型安全,輸入參數類(lèi)型逆變性(Contravariance,下一條指令可以接受前一條產(chǎn)生的數據類(lèi)型的父類(lèi)) 和輸出值類(lèi)型協(xié)變性(Covariance,最后一條指令可以產(chǎn)生repository的數據類(lèi)型的子類(lèi))

          // 1. 協(xié)變性 (Covariance): List<ASub> 是一個(gè) List<A>,反之不成立
          
          // 2. 逆變性 (Contravariance): List<A> 是一個(gè) List<ASub>,反之不成立    
          
          // 3. 不變性 (Invariance):List<ASub> 不是一個(gè) List<A>,List<A> 也不是一個(gè) List<ASub>      

          當數據處理流程開(kāi)始運行, 通過(guò)Repository.get()拉取的數據作為第一條指令的輸入值。如果之前還沒(méi)有更新過(guò)數據,拉取的數據可能是初始值或者使用RepositoryConfig.RESET_TO_INITIAL_VALUE重置的值。 這些指令順序的執行轉換輸入值。 數據處理流程通常在運行完_then_指令后結束并產(chǎn)生一個(gè)終值或者使用終止語(yǔ)句(termination clause)(RTermination接口, 詳情在下面“Attempts and Result”中)結束流程并返回一個(gè)值,這種情況下repository數據值會(huì )更新并發(fā)送通知。 使用.thenSkip()指令或者終止語(yǔ)句(termination clause)也可以終止流程,跳過(guò)剩余的流程,這種情況下repository跳過(guò)數據更新、跳過(guò)發(fā)送通知。

          Operators

          為了允許數據處理流程調用客戶(hù)代碼邏輯,Agera定制了下列只帶有一個(gè)方法的接口:

          • Supplier.get(): a 0-input, 1-output operator;
          • Function.apply(TFrom): a 1-input, 1-output operator;
          • Merger.merge(TFirst, TSecond): a 2-input, 1-output operator.

          使用它們的指令是:

          • .getFrom(Supplier) and variants;
          • .transform(Function) and variants;
          • .mergeIn(Supplier, Merger) and variants;
            如下圖所示:

          http://wiki.jikexueyuan.com/project/agera-wiki-cn/images/operators.png" alt="Operators" />

          對于高級功能,數據處理流程提供了非線(xiàn)性操作符(數據從"側邊"流出,或者流程終止),通過(guò)下列接口支持

          • Receiver.accept(T): a 1-input, 0-output operator;
          • Binder.bind(TFirst, TSecond): a 2-input, 0-output operator;
          • Predicate.apply(T): an operator that checks the input value for a yes-or-no answer.

          使用它們的指令是:

          • .sendTo(Receiver) and variants;
          • .bindWith(Supplier, Binder) and variants;
          • .check(Predicate).or… and variants;
            如下圖所示:

          http://wiki.jikexueyuan.com/project/agera-wiki-cn/images/sideoperators.png" alt="Side operators" />

          為了幫助構建模塊化的結構, Repository 實(shí)現了 Supplier接口, MutableRepository 實(shí)現了 SupplierReceiver接口, 在復雜的repository中,它們可以直接當作操作符使用。

          Attempts and Result

          這些函數式接口Supplier, Function and Merger都是不拋任何異常的, 但實(shí)踐中,許多操作可能會(huì )失敗。 為了捕獲異常,Agera 提供了一個(gè)封裝類(lèi) Result,它可以封裝易失敗操作的結果(成功或者失敗)或者_attempt_的結果值。 _attempt_可以作為Supplier, FunctionMerger的實(shí)現,返回Result。

          數據處理流程提供能感知錯誤的指令,這樣就可以在錯誤的情況下終止流程:

          • .attemptGetFrom(Supplier).or…;
          • .attemptTransform(Function).or…;
          • .attemptMergeIn(Supplier, Merger).or…,

          其中 .or… (和.check指令的第二部分相同)是終止語(yǔ)句,使用RTermination狀態(tài)接口實(shí)現, 如前文所述, 可以跳過(guò)更新 (.orSkip()) 或 用計算的新值來(lái)結束數據流程(.orEnd(Function))。

          所有.attempt*指令保證下一條指令只接收成功的結果,使用輸出Result<T>的操作符,輸出一個(gè)能感知錯誤的結果T,而不是Result<T>。

              mRepository = Repositories.repositoryWithInitialValue(Result.<Integer>absent())
                      .observe(mObservable)
                      .onUpdatesPerLoop()
                      // attemptGetFrom 輸出 Result<Integer>
                      .attemptGetFrom(new Supplier<Result<Integer>>() {
                          @NonNull
                          @Override
                          public Result<Integer> get() {
                              return Result.success(100);
                          }
                      })
                      .orSkip()
                      // 輸入 Integer
                      .thenTransform(new Function<Integer, Result<Integer>>() {
                          @NonNull
                          @Override
                          public Result<Integer> apply(@NonNull Integer input) {
                              return Result.success(input);
                          }
                      })
                      .compile();

          相反, 操作符也可以是恢復操作, 這意味著(zhù)它需要Result作為輸入, 或者是一個(gè)_attempt recovery_操作符,這意味著(zhù)它輸入和輸出都是Result。 要把這樣的操作符放在數據處理流程中, 前面的指令必須不是感知錯誤的(就算使用.attempt*操作符),所以恢復操作符可以接受成功和失敗的結果(Result類(lèi)型)。

          Asynchronous programming

          repository必須在有Looper的線(xiàn)程編譯(通常是主線(xiàn)程),這個(gè)Looper成為repository的[[worker looper|Observables-and-updatables#threading]], 所有這些過(guò)程都運行在這個(gè)Looper的線(xiàn)程上:

          • 注冊和注銷(xiāo) updatable;
          • 觀(guān)察、處理和事件源更新頻率限制;
          • 啟動(dòng)數據處理流程。

          數據處理流程不要求在Looper線(xiàn)程上完全同步執行。專(zhuān)門(mén)的指令 .goTo(Executor).goLazy() 會(huì )開(kāi)啟異步執行。 它們不改變輸入值;它們在運行時(shí)控制流程的持續:.goTo(Executor) 將剩下的執行指令發(fā)送到該Executor, 而 .goLazy() 暫停執行,直到需要新的數據的時(shí)候調用 Repository.get() 將繼續執行剩下的執行。

          .goTo(Executor)指令之后, 線(xiàn)程將釋放用于處理其他事件,repository可能同時(shí)發(fā)生被設為不活動(dòng)狀態(tài)和有更新事件。 在后面這種情況下,數據處理流程會(huì )重新運行,為了減少競爭條件,不用啟動(dòng)一個(gè)并行線(xiàn)程,會(huì )運行在同一個(gè)線(xiàn)程中。 repository在不活動(dòng)和并發(fā)更新是,可以取消正在執行的任務(wù)(ps:就是goTo()上執行的命令),這樣可以減少資源浪費(repository不活動(dòng)的情況下), 也可以更快的重新運行(并發(fā)更新的情況下,ps:因為只關(guān)心最新的數據嘛)。取消流程可以抑制更新repository數據和更新通知。 取消任務(wù)可以通過(guò).onDeactivation(int) and .onConcurrentUpdate(int) 方法來(lái)設置, 定義在RConfig狀態(tài)接口中。

          .goLazy()指令之后, 注冊的觀(guān)察者在任何情況下都會(huì )收到更新通知,但是是否真的更新數據取決于剩余的指令。 調用Repository.get()后會(huì )恢復同步執行,因為這個(gè)方法必須返回值,所有的取消都會(huì )忽略。 此外,如果Repository.get()調用之前,repository收到了更新通知,立即重啟流程,暫停狀態(tài)和保存的中間結果都會(huì )丟掉,剩余的指令也不會(huì )再運行。

          調用Repository.get()后恢復指令執行到達.goLazy()之前,repository會(huì )返回之前的數據。.goLazy()可以跳過(guò)不必要的計算, 有策略地使用可以提高程序性能。

          上一篇:Custom observables下一篇:Compiled functions
          日韩性做爰免费a片aa片,天天躁恨恨躁夜躁2020,精品久久综合1区2区3区激情,精产国品一二三产品麻豆

          <wbr id="jl7f7"></wbr>

                <i id="jl7f7"></i>
                  <acronym id="jl7f7"></acronym>

                  <s id="jl7f7"></s>

                  <ins id="jl7f7"></ins><button id="jl7f7"><strong id="jl7f7"></strong></button>