Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Introduction to Agera

Introduction to Agera

Introduction to a library, agera, provided by Google. https://github.com/google/agera

Reference:
- GitHub Wiki
https://github.com/google/agera/wiki
- Advanced RxJava: Google Agera vs. ReactiveX
http://akarnokd.blogspot.jp/2016/04/google-agera-vs-reactivex.html
- dex.fm - 1.5: Agera
https://dexfm.tumblr.com/post/143911768293/15-agera
- Sample code used in this talk
https://github.com/hkurokawa/AgeraSample

Hiroshi Kurokawa

May 09, 2016
Tweet

More Decks by Hiroshi Kurokawa

Other Decks in Technology

Transcript

  1. SHIBUYA.APK #7 (2016-05-09) AGENDA ▸ Brief introduction of Agera ▸

    Simple usage ▸ Advanced usage: dealing with an existing callback API ▸ Advanced usage: repository chain
  2. SHIBUYA.APK #7 (2016-05-09) WHAT’S AGERA ▸ Published by Google ▸

    A flavour of 0-arguments reactive programming ▸ Push event, pull data ▸ For consumption by Android application components https://github.com/google/agera
  3. SHIBUYA.APK #7 (2016-05-09) REFERENCE ▸ GitHub Wiki ▸ https://github.com/google/agera/wiki ▸

    Advanced RxJava: Google Agera vs. ReactiveX ▸ http://akarnokd.blogspot.jp/2016/04/google-agera-vs- reactivex.html ▸ dex.fm - 1.5: Agera ▸ https://dexfm.tumblr.com/post/143911768293/15-agera ▸ Sample code used in this talk ▸ https://github.com/hkurokawa/AgeraSample
  4. SHIBUYA.APK #7 (2016-05-09) BASIC CONCEPT ▸ Observable ▸ Event source

    (do not carry any data) ▸ Updatable ▸ Observes an Observable
  5. SHIBUYA.APK #7 (2016-05-09) BASIC CONCEPT ▸ Observable ▸ Event source

    (do not carry any data) ▸ Updatable ▸ Observes an Observable ▸ Supplier ▸ Provides data
  6. SHIBUYA.APK #7 (2016-05-09) BASIC CONCEPT ▸ Observable ▸ Event source

    (do not carry any data) ▸ Updatable ▸ Observes an Observable ▸ Supplier ▸ Provides data ▸ Repository ▸ Both Observable and Supplier
  7. SHIBUYA.APK #7 (2016-05-09) SIMPLE USAGE public class MainActivity extends AppCompatActivity

    implements Updatable { ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... // OnRefresh observable final OnRefreshObservable refreshObservable = new OnRefreshObservable(); swipeRefreshLayout.setOnRefreshListener(refreshObservable); // Tweets supplier and repository final TweetsSupplier tweetsSupplier = new TweetsSupplier(); tweetsRepository = Repositories .repositoryWithInitialValue(Result.<List<Tweet>>absent()) .observe(refreshObservable) .onUpdatesPerLoop() .goTo(networkExecutor) .thenGetFrom(tweetsSupplier) .compile(); listAdapter = RepositoryAdapter.repositoryAdapter() .add(tweetsRepository, new TweetPresenter()) .build(); final RecyclerView list = binding.list; list.setAdapter(listAdapter); list.setLayoutManager(new LinearLayoutManager(this)); }
  8. SHIBUYA.APK #7 (2016-05-09) SIMPLE USAGE public class MainActivity extends AppCompatActivity

    implements Updatable { ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... // OnRefresh observable final OnRefreshObservable refreshObservable = new OnRefreshObservable(); swipeRefreshLayout.setOnRefreshListener(refreshObservable); // Tweets supplier and repository final TweetsSupplier tweetsSupplier = new TweetsSupplier(); tweetsRepository = Repositories .repositoryWithInitialValue(Result.<List<Tweet>>absent()) .observe(refreshObservable) .onUpdatesPerLoop() .goTo(networkExecutor) .thenGetFrom(tweetsSupplier) .compile(); listAdapter = RepositoryAdapter.repositoryAdapter() .add(tweetsRepository, new TweetPresenter()) .build(); final RecyclerView list = binding.list; list.setAdapter(listAdapter); list.setLayoutManager(new LinearLayoutManager(this)); } SETUP AN OBSERVABLE TRIGGERED
 WHEN REFRESHED
  9. SHIBUYA.APK #7 (2016-05-09) SIMPLE USAGE public class MainActivity extends AppCompatActivity

    implements Updatable { ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... // OnRefresh observable final OnRefreshObservable refreshObservable = new OnRefreshObservable(); swipeRefreshLayout.setOnRefreshListener(refreshObservable); // Tweets supplier and repository final TweetsSupplier tweetsSupplier = new TweetsSupplier(); tweetsRepository = Repositories .repositoryWithInitialValue(Result.<List<Tweet>>absent()) .observe(refreshObservable) .onUpdatesPerLoop() .goTo(networkExecutor) .thenGetFrom(tweetsSupplier) .compile(); listAdapter = RepositoryAdapter.repositoryAdapter() .add(tweetsRepository, new TweetPresenter()) .build(); final RecyclerView list = binding.list; list.setAdapter(listAdapter); list.setLayoutManager(new LinearLayoutManager(this)); } SETUP A REPOSITORY TO FETCH TWEETS
  10. SHIBUYA.APK #7 (2016-05-09) SIMPLE USAGE public class MainActivity extends AppCompatActivity

    implements Updatable { ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... // OnRefresh observable final OnRefreshObservable refreshObservable = new OnRefreshObservable(); swipeRefreshLayout.setOnRefreshListener(refreshObservable); // Tweets supplier and repository final TweetsSupplier tweetsSupplier = new TweetsSupplier(); tweetsRepository = Repositories .repositoryWithInitialValue(Result.<List<Tweet>>absent()) .observe(refreshObservable) .onUpdatesPerLoop() .goTo(networkExecutor) .thenGetFrom(tweetsSupplier) .compile(); listAdapter = RepositoryAdapter.repositoryAdapter() .add(tweetsRepository, new TweetPresenter()) .build(); final RecyclerView list = binding.list; list.setAdapter(listAdapter); list.setLayoutManager(new LinearLayoutManager(this)); } START WITH ABSENT
  11. SHIBUYA.APK #7 (2016-05-09) SIMPLE USAGE public class MainActivity extends AppCompatActivity

    implements Updatable { ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... // OnRefresh observable final OnRefreshObservable refreshObservable = new OnRefreshObservable(); swipeRefreshLayout.setOnRefreshListener(refreshObservable); // Tweets supplier and repository final TweetsSupplier tweetsSupplier = new TweetsSupplier(); tweetsRepository = Repositories .repositoryWithInitialValue(Result.<List<Tweet>>absent()) .observe(refreshObservable) .onUpdatesPerLoop() .goTo(networkExecutor) .thenGetFrom(tweetsSupplier) .compile(); listAdapter = RepositoryAdapter.repositoryAdapter() .add(tweetsRepository, new TweetPresenter()) .build(); final RecyclerView list = binding.list; list.setAdapter(listAdapter); list.setLayoutManager(new LinearLayoutManager(this)); } OBSERVE ONREFRESH,
 HANDLING A CONSECUTIVE EVENTS
 AS AN EVENT
  12. SHIBUYA.APK #7 (2016-05-09) SIMPLE USAGE public class MainActivity extends AppCompatActivity

    implements Updatable { ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... // OnRefresh observable final OnRefreshObservable refreshObservable = new OnRefreshObservable(); swipeRefreshLayout.setOnRefreshListener(refreshObservable); // Tweets supplier and repository final TweetsSupplier tweetsSupplier = new TweetsSupplier(); tweetsRepository = Repositories .repositoryWithInitialValue(Result.<List<Tweet>>absent()) .observe(refreshObservable) .onUpdatesPerLoop() .goTo(networkExecutor) .thenGetFrom(tweetsSupplier) .compile(); listAdapter = RepositoryAdapter.repositoryAdapter() .add(tweetsRepository, new TweetPresenter()) .build(); final RecyclerView list = binding.list; list.setAdapter(listAdapter); list.setLayoutManager(new LinearLayoutManager(this)); } RETRIEVES TWEETS ON ANOTHER THREAD
  13. SHIBUYA.APK #7 (2016-05-09) SIMPLE USAGE public class MainActivity extends AppCompatActivity

    implements Updatable { ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... // OnRefresh observable final OnRefreshObservable refreshObservable = new OnRefreshObservable(); swipeRefreshLayout.setOnRefreshListener(refreshObservable); // Tweets supplier and repository final TweetsSupplier tweetsSupplier = new TweetsSupplier(); tweetsRepository = Repositories .repositoryWithInitialValue(Result.<List<Tweet>>absent()) .observe(refreshObservable) .onUpdatesPerLoop() .goTo(networkExecutor) .thenGetFrom(tweetsSupplier) .compile(); listAdapter = RepositoryAdapter.repositoryAdapter() .add(tweetsRepository, new TweetPresenter()) .build(); final RecyclerView list = binding.list; list.setAdapter(listAdapter); list.setLayoutManager(new LinearLayoutManager(this)); } BUILD A REPOSITORY
  14. SHIBUYA.APK #7 (2016-05-09) SIMPLE USAGE public class MainActivity extends AppCompatActivity

    implements Updatable { ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... // OnRefresh observable final OnRefreshObservable refreshObservable = new OnRefreshObservable(); swipeRefreshLayout.setOnRefreshListener(refreshObservable); // Tweets supplier and repository final TweetsSupplier tweetsSupplier = new TweetsSupplier(); tweetsRepository = Repositories .repositoryWithInitialValue(Result.<List<Tweet>>absent()) .observe(refreshObservable) .onUpdatesPerLoop() .goTo(networkExecutor) .thenGetFrom(tweetsSupplier) .compile(); listAdapter = RepositoryAdapter.repositoryAdapter() .add(tweetsRepository, new TweetPresenter()) .build(); final RecyclerView list = binding.list; list.setAdapter(listAdapter); list.setLayoutManager(new LinearLayoutManager(this)); } CREATE A RECYCLERVIEW ADAPTER
 RECEIVING TWEETS
  15. SHIBUYA.APK #7 (2016-05-09) SIMPLE USAGE public class MainActivity extends AppCompatActivity

    implements Updatable { ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... // OnRefresh observable final OnRefreshObservable refreshObservable = new OnRefreshObservable(); swipeRefreshLayout.setOnRefreshListener(refreshObservable); // Tweets supplier and repository final TweetsSupplier tweetsSupplier = new TweetsSupplier(); tweetsRepository = Repositories .repositoryWithInitialValue(Result.<List<Tweet>>absent()) .observe(refreshObservable) .onUpdatesPerLoop() .goTo(networkExecutor) .thenGetFrom(tweetsSupplier) .compile(); listAdapter = RepositoryAdapter.repositoryAdapter() .add(tweetsRepository, new TweetPresenter()) .build(); final RecyclerView list = binding.list; list.setAdapter(listAdapter); list.setLayoutManager(new LinearLayoutManager(this)); } SET THE ADAPTER
  16. SHIBUYA.APK #7 (2016-05-09) SIMPLE USAGE public class MainActivity extends AppCompatActivity

    implements Updatable { ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... // OnRefresh observable final OnRefreshObservable refreshObservable = new OnRefreshObservable(); swipeRefreshLayout.setOnRefreshListener(refreshObservable); // Tweets supplier and repository final TweetsSupplier tweetsSupplier = new TweetsSupplier(); tweetsRepository = Repositories .repositoryWithInitialValue(Result.<List<Tweet>>absent()) .observe(refreshObservable) .onUpdatesPerLoop() .goTo(networkExecutor) .thenGetFrom(tweetsSupplier) .compile(); listAdapter = RepositoryAdapter.repositoryAdapter() .add(tweetsRepository, new TweetPresenter()) .build(); final RecyclerView list = binding.list; list.setAdapter(listAdapter); list.setLayoutManager(new LinearLayoutManager(this)); }.
  17. SHIBUYA.APK #7 (2016-05-09) SIMPLE USAGE public class MainActivity extends AppCompatActivity

    implements Updatable { ... @Override protected void onCreate(Bundle savedInstanceState) { ... }.
  18. SHIBUYA.APK #7 (2016-05-09) SIMPLE USAGE public class MainActivity extends AppCompatActivity

    implements Updatable { ... @Override protected void onCreate(Bundle savedInstanceState) { ... }. @Override protected void onResume() { super.onResume(); // Start loading listAdapter.startObserving(); swipeRefreshLayout.post(this::update); // Start listening to the update tweetsRepository.addUpdatable(this); } @Override protected void onPause() { super.onPause(); listAdapter.stopObserving(); // Stop listening to the update tweetsRepository.removeUpdatable(this); }
  19. SHIBUYA.APK #7 (2016-05-09) SIMPLE USAGE public class MainActivity extends AppCompatActivity

    implements Updatable { ... @Override protected void onCreate(Bundle savedInstanceState) { ... } @Override protected void onResume() { super.onResume(); // Start loading listAdapter.startObserving(); swipeRefreshLayout.post(this::update); // Start listening to the update tweetsRepository.addUpdatable(this); } @Override protected void onPause() { super.onPause(); listAdapter.stopObserving(); // Stop listening to the update tweetsRepository.removeUpdatable(this); } START OBSERVING, SHOW REFRESHING PROGRESS BAR
  20. SHIBUYA.APK #7 (2016-05-09) SIMPLE USAGE public class MainActivity extends AppCompatActivity

    implements Updatable { ... @Override protected void onCreate(Bundle savedInstanceState) { ... } @Override protected void onResume() { super.onResume(); // Start loading listAdapter.startObserving(); swipeRefreshLayout.post(this::update); // Start listening to the update tweetsRepository.addUpdatable(this); } @Override protected void onPause() { super.onPause(); listAdapter.stopObserving(); // Stop listening to the update tweetsRepository.removeUpdatable(this); } STOP OBSERVING
  21. SHIBUYA.APK #7 (2016-05-09) SIMPLE USAGE public class MainActivity extends AppCompatActivity

    implements Updatable { ... @Override protected void onCreate(Bundle savedInstanceState) { ... }. @Override protected void onResume() { super.onResume(); // Start loading listAdapter.startObserving(); swipeRefreshLayout.post(this::update); // Start listening to the update tweetsRepository.addUpdatable(this); }. @Override protected void onPause() { super.onPause(); listAdapter.stopObserving(); // Stop listening to the update tweetsRepository.removeUpdatable(this); }..
  22. SHIBUYA.APK #7 (2016-05-09) SIMPLE USAGE public class MainActivity extends AppCompatActivity

    implements Updatable { ... @Override protected void onCreate(Bundle savedInstanceState) { ... }. @Override protected void onResume() { ... }. @Override protected void onPause() { ... }..
  23. SHIBUYA.APK #7 (2016-05-09) SIMPLE USAGE public class MainActivity extends AppCompatActivity

    implements Updatable { ... @Override protected void onCreate(Bundle savedInstanceState) { ... }. @Override protected void onResume() { ... }. @Override protected void onPause() { ... }.. @Override public void update() { if (tweetsSearchRepository.get().isAbsent()) { swipeRefreshLayout.setRefreshing(true); } else if (tweetsSearchRepository.get().failed()) { Toast.makeText(this, R.string.error, Toast.LENGTH_SHORT).show(); swipeRefreshLayout.setRefreshing(false); } else { swipeRefreshLayout.setRefreshing(false); } } SHOW REFRESHING PROGRESS BAR WHILE UPDATING
  24. SHIBUYA.APK #7 (2016-05-09) LESSONS LEARNED #1 ▸ It’s NOT that

    simple! ▸ Trigger (OnRefreshObservable) doesn’t provide any data ▸ The thread to execute the supplier can be controlled with goTo() method ▸ CompiledRepository is useful but the methods are order-sensitive ▸ ex. getFrom() vs. thenGetFrom() ▸ Support for RecyclerView or other Android stuff is great ▸ Call addUpdatable() and removeUpdatable() in onResume() and onPause()
  25. SHIBUYA.APK #7 (2016-05-09) ONE STEP FURTHER - CALLBACK API ▸

    Dealing with a callback API final TwitterApiClient client = Twitter.getApiClient(session); client.getSearchService().tweets("#shibuyaapk", new GuestCallback<>(new Callback<Search>() {}));
  26. SHIBUYA.APK #7 (2016-05-09) ONE STEP FURTHER - CALLBACK API ▸

    Dealing with a callback API final TwitterApiClient client = Twitter.getApiClient(session); client.getSearchService().tweets("#shibuyaapk", new GuestCallback<>(new Callback<Search>() { @Override public void success(Result<Search> result) { }. @Override public void failure(TwitterException exception) { }. }));
  27. SHIBUYA.APK #7 (2016-05-09) ONE STEP FURTHER - CALLBACK API ▸

    Dealing with a callback API ▸ Wrap with a Repository
  28. SHIBUYA.APK #7 (2016-05-09) ONE STEP FURTHER - CALLBACK API final

    TwitterApiClient client = Twitter.getApiClient(session); client.getSearchService().tweets("#shibuyaapk", new GuestCallback<>(new Callback<Search>() { @Override public void success(Result<Search> searchResult) { }. @Override public void failure(TwitterException exception) { }. }));
  29. SHIBUYA.APK #7 (2016-05-09) ONE STEP FURTHER - CALLBACK API @Override.

    public void update() { final TwitterApiClient client = Twitter.getApiClient(session); client.getSearchService().tweets("#shibuyaapk", new GuestCallback<>(new Callback<Search>() { @Override public void success(Result<Search> searchResult) { result = Result.success(searchResult.data.tweets); dispatchUpdate(); }. @Override public void failure(TwitterException exception) { result = Result.failure(exception); dispatchUpdate(); }. })); }..
  30. SHIBUYA.APK #7 (2016-05-09) ONE STEP FURTHER - CALLBACK API @Override.

    public void update() { final TwitterApiClient client = Twitter.getApiClient(session); client.getSearchService().tweets("#shibuyaapk", new GuestCallback<>(new Callback<Search>() { …. })); }..
  31. SHIBUYA.APK #7 (2016-05-09) ONE STEP FURTHER - CALLBACK API @Override

    public void update() { final TwitterApiClient client = Twitter.getApiClient(session); client.getSearchService().tweets("#shibuyaapk", new GuestCallback<>(new Callback<Search>() { …. })); }. @NonNull @Override public Result<List<Tweet>> get() { return result; }.
  32. SHIBUYA.APK #7 (2016-05-09) ONE STEP FURTHER - CALLBACK API @Override

    public void update() { final TwitterApiClient client = Twitter.getApiClient(session); client.getSearchService().tweets("#shibuyaapk", new GuestCallback<>(new Callback<Search>() { …. })); }. @NonNull @Override public Result<List<Tweet>> get() { return result; }. @Override protected void observableActivated() { update(); }. CALLED WHEN THE FIRST UPDATABLE IS ADDED
  33. SHIBUYA.APK #7 (2016-05-09) ONE STEP FURTHER - CALLBACK API @Override

    public void update() { final TwitterApiClient client = Twitter.getApiClient(session); client.getSearchService().tweets("#shibuyaapk", new GuestCallback<>(new Callback<Search>() { …. })); }. @NonNull @Override public Result<List<Tweet>> get() { return result; }. @Override protected void observableActivated() { update(); }.
  34. SHIBUYA.APK #7 (2016-05-09) ONE STEP FURTHER - CALLBACK API class

    TweetsSearchRepository extends BaseObservable implements Repository<Result<List<Tweet>>>, Updatable { @Override public void update() { final TwitterApiClient client = Twitter.getApiClient(session); client.getSearchService().tweets("#shibuyaapk", new GuestCallback<>(new Callback<Search>() { …. })); }. @NonNull @Override public Result<List<Tweet>> get() { return result; }. @Override protected void observableActivated() { update(); }. } KEEP THE THREADING CONTRACT BETWEEN OBSERVABLE AND UPDATABLE
  35. SHIBUYA.APK #7 (2016-05-09) LESSONS LEARNED #2 ▸ If you have

    to deal with an existing callback API, wrap the API with Repository ▸ Inherit BaseObservable if possible ▸ Do not forget to override observableActivated() ▸ Make sure your repository is as simple as possible
  36. SHIBUYA.APK #7 (2016-05-09) ONE MORE STEP - REPOSITORY CHAIN ▸

    Load the next page when scrolling down to the bottom of the list ▸ OnBottomObservable ▸ Fire an event when the bottom of the list is visible ▸ TweetsRequestSupplier ▸ Provide the maxId query ▸ OnBottomObservable triggers the search and the retrieved tweets are appended to the current list
  37. SHIBUYA.APK #7 (2016-05-09) ONE MORE STEP - REPOSITORY CHAIN //

    Repository to store the entire list final Repository<Result<List<Tweet>>> tweetsRepository = Repositories.repositoryWithInitialValue(Result.<List<Tweet>>absent()) .observe(tweetsSearchRepository) .onUpdatesPerLoop() .thenMergeIn(tweetsSearchRepository, (current, searchResult) -> { if (current.isAbsent() || current.failed()) { return searchResult; }. final List<Tweet> ls = new ArrayList<>(current.get()); if (searchResult.succeeded()) { ls.addAll(searchResult.get()); }. return Result.success(ls); }) .compile();
  38. SHIBUYA.APK #7 (2016-05-09) ONE MORE STEP - REPOSITORY CHAIN //

    Repository to store the entire list final Repository<Result<List<Tweet>>> tweetsRepository = Repositories.repositoryWithInitialValue(Result.<List<Tweet>>absent()) .observe(tweetsSearchRepository) .onUpdatesPerLoop() .thenMergeIn(tweetsSearchRepository, (current, searchResult) -> { if (current.isAbsent() || current.failed()) { return searchResult; }. final List<Tweet> ls = new ArrayList<>(current.get()); if (searchResult.succeeded()) { ls.addAll(searchResult.get()); }. return Result.success(ls); }) .compile(); MERGE THE RETRIEVED TWEETS INTO THE CURRENT LIST
  39. SHIBUYA.APK #7 (2016-05-09) ONE MORE STEP - REPOSITORY CHAIN //

    Repository to store the entire list final Repository<Result<List<Tweet>>> tweetsRepository = Repositories.repositoryWithInitialValue(Result.<List<Tweet>>absent()) .observe(tweetsSearchRepository) .onUpdatesPerLoop() .thenMergeIn(tweetsSearchRepository, (current, searchResult) -> { if (current.isAbsent() || current.failed()) { return searchResult; }. final List<Tweet> ls = new ArrayList<>(current.get()); if (searchResult.succeeded()) { ls.addAll(searchResult.get()); }. return Result.success(ls); }) .compile();
  40. SHIBUYA.APK #7 (2016-05-09) ONE MORE STEP - REPOSITORY CHAIN //

    Repository to store the entire list final Repository<Result<List<Tweet>>> tweetsRepository = Repositories.repositoryWithInitialValue(Result.<List<Tweet>>absent()) .observe(tweetsSearchRepository) .onUpdatesPerLoop() .thenMergeIn(tweetsSearchRepository, (current, searchResult) -> { if (current.isAbsent() || current.failed()) { return searchResult; }. final List<Tweet> ls = new ArrayList<>(current.get()); if (searchResult.succeeded()) { ls.addAll(searchResult.get()); }. return Result.success(ls); }) .compile(); listAdapter = RepositoryAdapter.repositoryAdapter() .add(tweetsRepository, new TweetPresenter()) .build(); list.setAdapter(listAdapter);
  41. SHIBUYA.APK #7 (2016-05-09) ONE MORE STEP - REPOSITORY CHAIN @Override

    protected void onResume() { super.onResume(); // Start loading listAdapter.startObserving(); swipeRefreshLayout.post(this::update); // Start listening to the update refreshObservable.addUpdatable(tweetsSearchRepository); refreshObservable.addUpdatable(searchRequest); onBottomObservable.addUpdatable(tweetsSearchRepository); tweetsSearchRepository.addUpdatable(this); } @Override protected void onPause() { super.onPause(); // Stop listening to the update refreshObservable.removeUpdatable(tweetsSearchRepository); refreshObservable.removeUpdatable(searchRequest); onBottomObservable.removeUpdatable(tweetsSearchRepository); tweetsSearchRepository.removeUpdatable(this); listAdapter.stopObserving(); } MANY REGISTRATIONS/UNREGISTRATIONS
  42. SHIBUYA.APK #7 (2016-05-09) LESSONS LEARNED #4 ▸ You can chain

    repositories to compose a flow ▸ The Updatables have to be added/removed at onResume()/ onPuase()
  43. SHIBUYA.APK #7 (2016-05-09) COMPARE AGERA TO RXJAVA (JUST AN IMPRESSION)

    ▸ 0-arguments reactive programming ▸ Not so bad in Android app usage ▸ Non-rich operators ▸ No combineLatest() or zipWith() operator ▸ You can use Functions to do map, filter, etc. ▸ Handling of the subscriptions seems not so smart
  44. SHIBUYA.APK #7 (2016-05-09) CONCLUSION ▸ Pros ▸ Very focusing on

    Android app usage (e.g. RecyclerViewAdapter, SqlDatabaseFunctions, HttpFunctions) ▸ Maybe easy and effective for a simple requirement ▸ Cons ▸ Needs some time for developer to get used to the APIs ▸ Operators are not rich (for now) ▸ Can be complicated for a complicated requirement (that’s the way of our life)