Skip to content

Observables 과 updatables

Youngchan edited this page Apr 22, 2016 · 12 revisions

이전 페이지에서 언급했듯이 observable은 event source 나타내고 updatable은 이벤트들을 관찰합니다. updatable은 Observable.addUpdatable(Updatable)을 사용하여 등록하고 Observable.removeUpdatable(Updatable)을 사용하여 등록해제 합니다. 이벤트는 Updatable.update()를 호출하는 형태로 updatable에게 전달 됩니다. Activity에서는 이와 같이 Observable에서 이벤트를 관찰 할 수 있습니다:

    public class MyUpdatableActivity extends Activity implements Updatable {
      private Observable observable;
      
      @Override
      protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        observable = new MyObservable();
      }
      
      @Override
      public void update() {
        // Act on the event
      }
      
      @Override
      protected void onResume() {
        super.onResume();
        observable.addUpdatable(this);
        update();
      }
      
      @Override
      protected void onPause() {
        super.onPause();
        observable.removeUpdatable(this);
      }
    }

Updatable 등록과 등록해지는 반드시 같이 쓰여야 합니다. 한번 이상 observable에 동일한 updatable을 추가하거나 등록 되기 전에 observable에서 updatable을 제거 하거나 이미 등록해지 된 상태에서 제거 할 경우 위반입니다.

라이프사이클 활성화 그리고 event 체인

observable은 관찰됨(observed)으로써 _활성화(active)_됩니다.(적어도 하나의 등록된 updatable을 가지고 있음), 그리고 관찰하지 않음으로써 _비활성화(inactive)_됩니다.(등록된 updatables이 없음). 다른 각도에서 말하면, 비활성화(inactive)상태의 observable을 등록하는 것을 _활성화activate_라고 합니다. 그리고 observable을 등록해지하는 것을 _비활성화(deactivate)_라고 합니다.

An observable may observe other observables further “upstream” (in the sense of an event propagation path) and translates their events into its own events. A common example is a repository whose data depends on the data supplied by other repositories. For the correct wiring, such an intermediate observable normally keeps strong references to the upstream observables, but will typically only register its internal updatable to the upstream when it itself is active, and deregister the updatable when it is deactivated. This means that the strong references in the downstream direction only exist for registered updatables. It also means that the most downstream updatables (those not managed by these intermediate observables) ultimately control the activation and deactivation of all observables in an event chain.

UI 라이프사이클

The event chain feature is most useful for building reactive architecture with awareness of the UI lifecycle. Let a UI element be an Activity, a Fragment, or a View therein, and its active lifecycle be defined by any Android lifecycle event pair that is sensible for the specific case, such as from onStart to onStop, from onResume to onPause, from onAttachedToWindow to onDetachedFromWindow and so on. Let this UI element be or own an updatable that updates the UI using the data supplied by a repository. The repository in turn uses other event sources and data sources (not necessarily repositories) to calculate its data.

At the beginning of the UI element’s lifecycle, the aforementioned updatable is registered to, and therefore activates, the repository. This will connect the event chain and activate all relevant data processing flows, keeping the data and the UI up to date.

At the end of the UI element’s lifecycle, the updatable is deregistered from the same repository, which, assuming no other updatables are still keeping any observable active, will lead to a cascading teardown of the event chain. If the UI element is to never become active again (due to e.g. the activity being destroyed), because there are no downstream references when the system is inactive, the UI element is free to be garbage collected, making it easy to prevent activity leaks.

쓰레딩

Agera advocates explicit threading, and uses Loopers (available in abundance, such as the app’s main Looper and the Looper for an IntentService’s worker thread) to help define the following threading contracts.

For internal activation lifecycle handling, each observable has a lifetime association with a worker Looper, the Looper for the thread from which the observable instance was instantiated. The observable is activated and deactivated from this worker Looper. If the observable observes other observables on activation, its internal updatable will be registered onto those upstream observables from this worker Looper thread.

An updatable must be registered onto an observable from a Looper thread, which does not need to be the same thread running the observable’s worker Looper. The observable will use the same Looper thread to dispatch the Updatable.update() calls to this updatable.

An updatable can be deregistered from any thread, but to prevent a race condition where the event is dispatched to the updatable after it is deregistered due to the Looper’s internal handling, it is recommended to deregister the updatable from the same Looper thread from which the registration took place.

The coder is responsible for keeping a Looper active as long as there are observables or registered updatables depending on it. Exceptions and memory leaks caused by dead Loopers are the coder’s liability. In practice, however, there is seldom genuine need to use any Looper other than the main Looper, which will always be active.