鍍金池/ 教程/ Android/ Incrementally Agerifying legacy code
                                          Custom observables
                                          Compiled functions
                                          Reactive programming
                                          Reservoirs and parallelism
                                          Incrementally Agerifying legacy code
                                          Observables and updatables
                                          Compiled repositories
                                          Repositories

                                          Incrementally Agerifying legacy code

                                          Agera引入的代碼風格也許適合從零開始的新建app項目。這篇包括一些提示,來幫助想在遺留代碼中使用Agera的開發者,如此往下做。

                                          Upgrading legacy observer pattern

                                          --升級原有觀察者模式

                                          觀察者模式有很多種實現方式,但不是所有的都可以通過簡單的放入遷入到Agera中。下面是一個例子:演示將一個監聽(listenable)類添加到Observable接口的一種方法。

                                          MyListenable類可以增加(addListener)和刪除(removeListener)Listener,作為額外完整的演示,它繼承了SomeBaseClass。

                                          該實例使用UpdateDispatcher來解決Java的單繼承約束,使用一個內部類(Bridge)來做橋接, 保持其完整的原始API,同時也使Agera可見。

                                          public final class MyListenable extends SomeBaseClass implements Observable {
                                          
                                            private final UpdateDispatcher updateDispatcher;
                                          
                                            public MyListenable() {
                                              // Original constructor code here...
                                              updateDispatcher = Observables.updateDispatcher(new Bridge());
                                            }
                                          
                                            // Original class body here... including:
                                            public void addListener(Listener listener) { … }
                                            public void removeListener(Listener listener) { … }
                                          
                                            @Override
                                            public void addUpdatable(Updatable updatable) {
                                              updateDispatcher.addUpdatable(updatable);
                                            }
                                          
                                            @Override
                                            public void removeUpdatable(Updatable updatable) {
                                              updateDispatcher.removeUpdatable(updatable);
                                            }
                                          
                                            private final class Bridge implements ActivationHandler, Listener {
                                              @Override
                                              public void observableActivated(UpdateDispatcher caller) {
                                                addListener(this);
                                              }
                                          
                                              @Override
                                              public void observableDeactivated(UpdateDispatcher caller) {
                                                removeListener(this);
                                              }
                                          
                                              @Override
                                              public void onEvent() { // Listener implementation
                                                updateDispatcher.update();
                                              }
                                            }
                                          }

                                          Exposing synchronous operations as repositories

                                          --揭秘repository的同步操作

                                          Java本質是一種同步語言,如:在Java中最低級別的操作都是同步方法。 當操作可能會花一些時間才能返回(耗時操作),這種方法通常稱為阻塞方法,而且禁止開發者在主線程(UI Thread)調用。

                                          假設app的UI需要從阻塞的方法獲得數據。Agera可以很容易的通過后臺線程完成調用,然后UI可以在主線程中接收數據。首先,這個阻塞操作需要封裝成一個Agera操作,像這樣:

                                          public class NetworkCallingSupplier implements Supplier<Result<ResponseBlob>> {
                                            private final RequestBlob request = …;
                                          
                                            @Override
                                            public Result<ResponseBlob> get() {
                                              try {
                                                 ResponseBlob blob = networkStack.execute(request); // blocking call
                                                 return Result.success(blob);
                                              } catch (Throwable e) {
                                                 return Result.failure(e);
                                              }
                                            }
                                          }
                                          
                                          Supplier<Result<ResponseBlob>> networkCall = new NetworkCallingSupplier();
                                          
                                          Repository<Result<ResponseBlob>> responseRepository =
                                              Repositories.repositoryWithInitialValue(Result.<ResponseBlob>absent())
                                                  .observe() // no event source; works on activation
                                                  .onUpdatesPerLoop() // but this line is still needed to compile
                                                  .goTo(networkingExecutor)
                                                  .thenGetFrom(networkCall)
                                                  .compile();

                                          上面的代碼段假定了,在Repository.compile()之前這個請求是已知且永遠不變的。

                                          這個很容易升級成為一個動態請求,甚至在repository同樣的激活周期期間。

                                          要可以修改請求,簡單的方式是使用MutableRepository。 此外,為了在第一次請求為完成之前就可以提供數據,可以在Result中一個提供初始值:absent()。

                                          MutableRepository這種用法類似于是一個可變的變量(可為null),故命名為requestVariable。

                                          // MutableRepository<RequestBlob> requestVariable =
                                          //     mutableRepository(firstRequest);
                                          // OR:
                                          MutableRepository<Result<RequestBlob>> requestVariable =
                                              mutableRepository(Result.<RequestBlob>absent());

                                          然后, 不是在supplier中封裝阻塞方法,使用function實現動態請求:

                                          public class NetworkCallingFunction
                                              implements Function<RequestBlob, Result<ResponseBlob>> {
                                            @Override
                                            public Result<ResponseBlob> apply(RequestBlob request) {
                                              try {
                                                 ResponseBlob blob = networkStack.execute(request);
                                                 return Result.success(blob);
                                              } catch (Throwable e) {
                                                 return Result.failure(e);
                                              }
                                            }
                                          }
                                          
                                          Function<RequestBlob, Result<ResponseBlob>> networkCallingFunction =
                                              new NetworkCallingFunction();

                                          升級后的repository可以像這樣compiled:

                                          Result<ResponseBlob> noResponse = Result.absent();
                                          Function<Throwable, Result<ResponseBlob>> withNoResponse =
                                              Functions.staticFunction(noResponse);
                                          Repository<Result<ResponseBlob>> responseRepository =
                                              Repositories.repositoryWithInitialValue(noResponse)
                                                  .observe(requestVariable)
                                                  .onUpdatesPerLoop()
                                                  // .getFrom(requestVariable) if it does not supply Result, OR:
                                                  .attemptGetFrom(requestVariable).orEnd(withNoResponse)
                                                  .goTo(networkingExecutor)
                                                  .thenTransform(networkCallingFunction)
                                                  .compile();

                                          這部分代碼段還演示了一點:通過給操作一個特殊的名字,讓repository的編譯表達式更易讀。

                                          Wrapping asynchronous calls in repositories

                                          --repository的異步調用封裝

                                          現在的很多Library都有異步API和內置的線程,但是客戶端不能控制或禁用。

                                          app中有這樣的Library的話,引入Agera將是一個具有挑戰性的工作。 一個直接的辦法就是找到Library中同步選擇的點,采用[[如上段所述|Incrementally-Agerifying-legacy-code#exposing-synchronous-operations-as-repositories]]方法。

                                          另一個方式(反模式):切換后臺線程執行異步調用并等待結果,然后同步拿結果。上面方式不可行時,這一節討論一個合適的解決方法。

                                          異步調用的一個循環模式是請求-響應 結構。下面的示例假定這樣結構:未完成的工作可以被取消,但是不指定回調的線程。

                                          interface AsyncOperator<P, R> {
                                            Cancellable request(P param, Callback<R> callback);
                                          }
                                          
                                          interface Callback<R> {
                                            void onResponse(R response); // Can be called from any thread
                                          }
                                          
                                          interface Cancellable {
                                            void cancel();
                                          }

                                          下面repository例子,使用AsyncOperator提供數據, 完成響應式請求(一個抽象的supplier類)。

                                          這段代碼假定AsyncOperator已經有足夠的緩存,因此重復的請求不會影響性能。

                                          public class AsyncOperatorRepository<P, R> extends BaseObservable
                                              implements Repository<Result<R>>, Callback<R> {
                                          
                                            private final AsyncOperator<P, R> asyncOperator;
                                            private final Supplier<P> paramSupplier;
                                          
                                            private Result<R> result;
                                            private Cancellable cancellable;
                                          
                                            public AsyncOperatorRepository(AsyncOperator<P, R> asyncOperator,
                                                Supplier<P> paramSupplier) {
                                              this.asyncOperator = asyncOperator;
                                              this.paramSupplier = paramSupplier;
                                              this.result = Result.absent();
                                            }
                                          
                                            @Override
                                            protected synchronized void observableActivated() {
                                              cancellable = asyncOperator.request(paramSupplier.get(), this);
                                            }
                                          
                                            @Override
                                            protected synchronized void observableDeactivated() {
                                              if (cancellable != null) {
                                                cancellable.cancel();
                                                cancellable = null;
                                              }
                                            }
                                          
                                            @Override
                                            public synchronized void onResponse(R response) {
                                              cancellable = null;
                                              result = Result.absentIfNull(response);
                                              dispatchUpdate();
                                            }
                                          
                                            @Override
                                            public synchronized Result<R> get() {
                                              return result;
                                            }
                                          }

                                          這個類可以很容易地升級到可以修改請求參數,而這個過程就類似于前面的討論:讓repository提供請求參數,并讓AsyncOperatorRepository觀察請求參數變化。

                                          在激活期間,觀察請求參數的變化,取消任何正在進行的請求,并發出新的請求,如下所示:

                                          public class AsyncOperatorRepository<P, R> extends BaseObservable
                                              implements Repository<Result<R>>, Callback<R>, Updatable {
                                          
                                            private final AsyncOperator<P, R> asyncOperator;
                                            private final Repository<P> paramRepository;
                                          
                                            private Result<R> result;
                                            private Cancellable cancellable;
                                          
                                            public AsyncOperatorRepository(AsyncOperator<P, R> asyncOperator,
                                                Repository<P> paramRepository) {
                                              this.asyncOperator = asyncOperator;
                                              this.paramRepository = paramRepository;
                                              this.result = Result.absent();
                                            }
                                          
                                            @Override
                                            protected void observableActivated() {
                                              paramRepository.addUpdatable(this);
                                              update();
                                            }
                                          
                                            @Override
                                            protected synchronized void observableDeactivated() {
                                              paramRepository.removeUpdatable(this);
                                              cancelOngoingRequestLocked();
                                            }
                                          
                                            @Override
                                            public synchronized void update() {
                                              cancelOngoingRequestLocked();
                                              // Adapt accordingly if paramRepository supplies a Result.
                                              cancellable = asyncOperator.request(paramRepository.get(), this);
                                            }
                                          
                                            private void cancelOngoingRequestLocked() {
                                              if (cancellable != null) {
                                                cancellable.cancel();
                                                cancellable = null;
                                              }
                                            }
                                          
                                            @Override
                                            public synchronized void onResponse(R response) {
                                              cancellable = null;
                                              result = Result.absentIfNull(response);
                                              dispatchUpdate();
                                            }
                                          
                                            // Similar process for fallible requests (typically with an
                                            // onError(Throwable) callback): wrap the failure in a Result and
                                            // dispatchUpdate().
                                          
                                            @Override
                                            public synchronized Result<R> get() {
                                              return result;
                                            }
                                          }
                                          人妻精品动漫h无码中字