Slide 1

Slide 1 text

INTRODUCTION TO AGERA HIROSHI KUROKAWA (FABLIC, INC.) SHIBUYA.APK #7, MAY 9TH, 2016

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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.>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)); }

Slide 10

Slide 10 text

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.>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

Slide 11

Slide 11 text

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.>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

Slide 12

Slide 12 text

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.>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

Slide 13

Slide 13 text

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.>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

Slide 14

Slide 14 text

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.>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

Slide 15

Slide 15 text

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.>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

Slide 16

Slide 16 text

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.>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

Slide 17

Slide 17 text

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.>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

Slide 18

Slide 18 text

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.>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)); }.

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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); }

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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); }..

Slide 24

Slide 24 text

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() { ... }..

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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()

Slide 27

Slide 27 text

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() {}));

Slide 28

Slide 28 text

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() { @Override public void success(Result result) { }. @Override public void failure(TwitterException exception) { }. }));

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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() { @Override public void success(Result searchResult) { }. @Override public void failure(TwitterException exception) { }. }));

Slide 31

Slide 31 text

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() { @Override public void success(Result searchResult) { result = Result.success(searchResult.data.tweets); dispatchUpdate(); }. @Override public void failure(TwitterException exception) { result = Result.failure(exception); dispatchUpdate(); }. })); }..

Slide 32

Slide 32 text

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() { …. })); }..

Slide 33

Slide 33 text

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() { …. })); }. @NonNull @Override public Result> get() { return result; }.

Slide 34

Slide 34 text

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() { …. })); }. @NonNull @Override public Result> get() { return result; }. @Override protected void observableActivated() { update(); }. CALLED WHEN THE FIRST UPDATABLE IS ADDED

Slide 35

Slide 35 text

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() { …. })); }. @NonNull @Override public Result> get() { return result; }. @Override protected void observableActivated() { update(); }.

Slide 36

Slide 36 text

SHIBUYA.APK #7 (2016-05-09) ONE STEP FURTHER - CALLBACK API class TweetsSearchRepository extends BaseObservable implements Repository>>, Updatable { @Override public void update() { final TwitterApiClient client = Twitter.getApiClient(session); client.getSearchService().tweets("#shibuyaapk", new GuestCallback<>(new Callback() { …. })); }. @NonNull @Override public Result> get() { return result; }. @Override protected void observableActivated() { update(); }. } KEEP THE THREADING CONTRACT BETWEEN OBSERVABLE AND UPDATABLE

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

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

Slide 40

Slide 40 text

SHIBUYA.APK #7 (2016-05-09) ONE MORE STEP - REPOSITORY CHAIN // Repository to store the entire list final Repository>> tweetsRepository = Repositories.repositoryWithInitialValue(Result.>absent()) .observe(tweetsSearchRepository) .onUpdatesPerLoop() .thenMergeIn(tweetsSearchRepository, (current, searchResult) -> { if (current.isAbsent() || current.failed()) { return searchResult; }. final List 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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

SHIBUYA.APK #7 (2016-05-09) ONE MORE STEP - REPOSITORY CHAIN // Repository to store the entire list final Repository>> tweetsRepository = Repositories.repositoryWithInitialValue(Result.>absent()) .observe(tweetsSearchRepository) .onUpdatesPerLoop() .thenMergeIn(tweetsSearchRepository, (current, searchResult) -> { if (current.isAbsent() || current.failed()) { return searchResult; }. final List 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);

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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()

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

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)