<pre id="z8nfa"></pre>

<acronym id="z8nfa"><strong id="z8nfa"></strong></acronym><pre id="z8nfa"></pre>
<track id="z8nfa"></track>
  • <acronym id="z8nfa"><strong id="z8nfa"><listing id="z8nfa"></listing></strong></acronym>
  • 
    
    <p id="z8nfa"></p>
      鍍金池/ 教程/ 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;
        }
      }
      无码丰满熟妇一区二区蜜臀Av
      <pre id="z8nfa"></pre>

      <acronym id="z8nfa"><strong id="z8nfa"></strong></acronym><pre id="z8nfa"></pre>
      <track id="z8nfa"></track>
    1. <acronym id="z8nfa"><strong id="z8nfa"><listing id="z8nfa"></listing></strong></acronym>
    2. 
      
      <p id="z8nfa"></p>