Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Siavash

100 views

Published on

TehLUG presentation about rxjava and flux

IVAN MORGILLO©

Published in: Engineering
  • Be the first to comment

  • Be the first to like this

Siavash

  1. 1. Data flow Observer pattern Push vs Pull Reactive Programming
  2. 2. Data flow: How it look like
  3. 3. Observer Pattern Notifications Automation Cause-Effect
  4. 4. Rx Observer Pattern Observable Observer Subscription Subject
  5. 5. Rx Observer Pattern Observable Observer Subscription Subject onNext() onError() onCompleted()
  6. 6. Rx Observer Pattern Observable emits Observer Time item1 onNext(item1) Uses item1 item2 item3 onNext(item2) onNext(item3) Uses item2 Uses item3
  7. 7. Please, show some Android • Standard Android app • A bit of Material Design • A RecyclerView • A list of installed apps
  8. 8. Create an Observable private Observable<AppInfo> getApps() {
 return Observable.create(subscriber -> {
 List<AppInfoRich> apps = getList();
 
 for (AppInfoRich appInfo : apps) {
 if (subscriber.isUnsubscribed()) {
 return;
 } Bitmap icon = Utils.drawableToBitmap(appInfo.getIcon());
 String name = appInfo.getName();
 String iconPath = mFilesDir + "/" + name;
 Utils.storeBitmap(App.instance, icon, name);
 subscriber.onNext( new AppInfo(name, iconPath, appInfo.getLastUpdateTime()));
 }
 if (!subscriber.isUnsubscribed()) {
 subscriber.onCompleted();
 }
 });
 }
  9. 9. Create an Observable private Observable<AppInfo> getApps() {
 return Observable.create(subscriber -> {
 List<AppInfoRich> apps = getList();
 
 for (AppInfoRich appInfo : apps) {
 if (subscriber.isUnsubscribed()) {
 return;
 } Bitmap icon = Utils.drawableToBitmap(appInfo.getIcon());
 String name = appInfo.getName();
 String iconPath = mFilesDir + "/" + name;
 Utils.storeBitmap(App.instance, icon, name);
 subscriber.onNext( new AppInfo(name, iconPath, appInfo.getLastUpdateTime()));
 }
 if (!subscriber.isUnsubscribed()) {
 subscriber.onCompleted();
 }
 });
 }
  10. 10. Create an Observable private Observable<AppInfo> getApps() {
 return Observable.create(subscriber -> {
 List<AppInfoRich> apps = getList();
 
 for (AppInfoRich appInfo : apps) {
 if (subscriber.isUnsubscribed()) {
 return;
 } Bitmap icon = Utils.drawableToBitmap(appInfo.getIcon());
 String name = appInfo.getName();
 String iconPath = mFilesDir + "/" + name;
 Utils.storeBitmap(App.instance, icon, name);
 AppInfo app = new AppInfo(name, iconPath, appInfo.getLastUpdateTime()) subscriber.onNext(app);
 }
 if (!subscriber.isUnsubscribed()) {
 subscriber.onCompleted();
 }
 });
 }
  11. 11. Create an Observable private Observable<AppInfo> getApps() {
 return Observable.create(subscriber -> {
 List<AppInfoRich> apps = getList();
 
 for (AppInfoRich appInfo : apps) {
 if (subscriber.isUnsubscribed()) {
 return;
 } Bitmap icon = Utils.drawableToBitmap(appInfo.getIcon());
 String name = appInfo.getName();
 String iconPath = mFilesDir + "/" + name;
 Utils.storeBitmap(App.instance, icon, name); AppInfo app = new AppInfo(name, iconPath, appInfo.getLastUpdateTime()) subscriber.onNext(app);
 }
 if (!subscriber.isUnsubscribed()) {
 subscriber.onCompleted();
 }
 });
 }
  12. 12. Create an Observable private Observable<AppInfo> getApps() {
 return Observable.create(subscriber -> {
 List<AppInfoRich> apps = getList();
 
 for (AppInfoRich appInfo : apps) {
 if (subscriber.isUnsubscribed()) {
 return;
 } Bitmap icon = Utils.drawableToBitmap(appInfo.getIcon());
 String name = appInfo.getName();
 String iconPath = mFilesDir + "/" + name;
 Utils.storeBitmap(App.instance, icon, name); AppInfo app = new AppInfo(name, iconPath, appInfo.getLastUpdateTime()) subscriber.onNext(app);
 }
 if (!subscriber.isUnsubscribed()) {
 subscriber.onCompleted();
 }
 });
 }
  13. 13. Without RetroLambda private Observable<AppInfo> getApps() {
 
 return Observable.create( new Observable.OnSubscribe<AppInfo>(){
 
 @Override
 public void call(Subscriber<? super AppInfo> subscriber) {
 List<AppInfoRich> apps = getList();
 
 
 for (AppInfoRich appInfo : apps) {
 if (subscriber.isUnsubscribed()) {
 return;
 }
 Bitmap icon = Utils.drawableToBitmap(appInfo.getIcon());
 
 String name = appInfo.getName();
 String iconPath = mFilesDir + "/" + name;
 
 Utils.storeBitmap(App.instance, icon, name);
 AppInfo app = new AppInfo(name, iconPath, appInfo.getLastUpdateTime())
 subscriber.onNext(app);
 }
 
 if (!subscriber.isUnsubscribed()) {
 subscriber.onCompleted();
 }
 
 }
 })
 }
  14. 14. .create() an Observable
  15. 15. Observable.from() List<AppInfo> appsList = [...] Observable.from(appsList) .subscribe(...) I already have a list
  16. 16. Observable.just() AppInfo appOne = appsList.get(0); AppInfo appTwo = appsList.get(1); AppInfo appThree = appsList.get(2); Observable.just(appOne, appTwo, appThree) .subscribe(...) What about just three elements?
  17. 17. From old code to Rx public boolean doSomething() { // do something slow, then return true; } public Observable<Boolean> rxDoSomething() { return Observable.defer(() -> Observable.just(doSomething())); } rxDoSomething().subscribe(...);
  18. 18. recyclerView.setLayoutManager(new LinearLayoutManager(view.getContext())); adapter = new ApplicationAdapter(new ArrayList<>(), R.layout.applications_list_item); recyclerView.setAdapter(adapter); swipeRefreshLayout.setColorSchemeColors(mResources.getColor(R.color.myPrimaryColor)); swipeRefreshLayout.setProgressViewOffset(false, 0, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 24, [...]); swipeRefreshLayout.setEnabled(false); swipeRefreshLayout.setRefreshing(true); recyclerView.setVisibility(View.GONE); Observable.from(apps).subscribe(observer); Subscribe and react
  19. 19. Observer<AppInfo> observer = new Observer<AppInfo>() { @Override public void onNext(AppInfo appInfo) { addedApps.add(appInfo); adapter.addApplication(addedApps.size() - 1, appInfo); } @Override public void onCompleted() { showCompleteSequenceToast(); stopProgressBar(); } @Override public void onError(Throwable e) { showErrorToast(); stopProgressBar(); } }; Subscribe and react
  20. 20. Observer<AppInfo> observer = new Observer<AppInfo>() { @Override public void onNext(AppInfo appInfo) { addedApps.add(appInfo); adapter.addApplication(addedApps.size() - 1, appInfo); } @Override public void onCompleted() { showCompleteSequenceToast(); stopProgressBar(); } @Override public void onError(Throwable e) { showErrorToast(); stopProgressBar(); } }; Subscribe and react
  21. 21. Observer<AppInfo> observer = new Observer<AppInfo>() { @Override public void onNext(AppInfo appInfo) { addedApps.add(appInfo); adapter.addApplication(addedApps.size() - 1, appInfo); } @Override public void onCompleted() { showCompleteSequenceToast(); stopProgressBar(); } @Override public void onError(Throwable e) { showErrorToast(); stopProgressBar(); } }; Subscribe and react
  22. 22. I'm not buying it!! Show more!!!! Subscribe and react
  23. 23. .subscribe(observer); Observer<AppInfo> observer = new Observer<AppInfo>() { @Override public void onCompleted() { [...] } @Override public void onError(Throwable e) { [...] } @Override public void onNext(AppInfo appInfo) { [...] } }; .filter((appInfo) -> appInfo.getName().startsWith("C")) incomingApps() Filtering
  24. 24. .subscribe(observer); Observer<AppInfo> observer = new Observer<AppInfo>() { @Override public void onCompleted() { [...] } @Override public void onError(Throwable e) { [...] } @Override public void onNext(AppInfo appInfo) { [...] } }; incomingApps() Filtering .filter((appInfo) -> appInfo.getName().startsWith("C"))
  25. 25. incomingApps() .subscribe(observer); .take(3) First 3
  26. 26. incomingApps() .takeLast(3) .subscribe(observer); This is The End
  27. 27. incomingApps() .subscribe(observer); .take(3) .repeat(3) .distinct() I hate duplicates!
  28. 28. currentTemperature() .subscribe(observer); .distinctUntilChanged() -25... -25... -25... -25...
  29. 29. currentTemperature() .subscribe(observer); .sample(5, TimeUnit.MINUTES) -25........ -26........ .distinctUntilChanged()
  30. 30. currentTemperature() .subscribe(observer); -25........ -26........ .throttleFirst(5, TimeUnit.MINUTES)
  31. 31. incomingApps() .subscribe(observer);.map((AppInfo appInfo) -> { appInfo.setName( appInfo.getName().toLowerCase()); return appInfo; }) Transforming
  32. 32. FlatMap ConcatMap Cast Buffer .buffer(3) .cast(Long.class) Transforming
  33. 33. List rev = Lists.reverse(apps); Observable<AppInfo> apps = Observable.from(apps); Observable<AppInfo> rApps = Observable.from(rev); Observable .merge(apps, rApps) .subscribe(observer); Combining
  34. 34. Observable<AppInfo> apps = Observable.from(list); Observable<Long> tictoc = Observable.interval(1, TimeUnit.SECONDS); private AppInfo updateTitle(AppInfo appInfo, Long time) { appInfo.setName(time + " " + appInfo.getName()); return appInfo; } Observable .zip(apps, tictoc, updateTitle) .subscribe(observer) Combining
  35. 35. private Observable<List<AppInfo>> getAppsList() { return Observable.create(subscriber -> { List<AppInfo> apps = new ArrayList<>(); SharedPreferences sharedPref = getActivity().getPreferences(Context.MODE_PRIVATE); Type appInfoType = new TypeToken<List<AppInfo>>() {}.getType(); String serializedApps = sharedPref.getString("APPS", ""); if (!"".equals(serializedApps)) { apps = new Gson().fromJson(serializedApps, appInfoType); } subscriber.onNext(apps); subscriber.onCompleted(); }); } Defeating Android MainThread issue
  36. 36. Defeating Android MainThread issue
 public void onCreate() {
 if (DEVELOPER_MODE) {
 StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
 .detectDiskReads()
 .detectDiskWrites()
 .detectNetwork() // or .detectAll() for all detectable problems
 .penaltyLog()
 .build());
 StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
 .detectLeakedSqlLiteObjects()
 .detectLeakedClosableObjects()
 .penaltyLog()
 .penaltyDeath()
 .build());
 }
 super.onCreate();
 }
  37. 37. D/StrictMode: StrictMode policy violation; ~duration=253 ms: android.os.StrictMode$StrictModeDiskReadViolation: policy=31violation=2 at android.os.StrictMode$AndroidBlockGuardPolicy.onReadFromDisk( StrictMode.java:1135) getAppsList() .subscribeOn(Schedulers.io()) .subscribe(observer) Defeating Android MainThread issue
  38. 38. Only the original thread that created a view hierarchy can touch its views Defeating Android MainThread issue D/StrictMode: StrictMode policy violation; ~duration=253 ms: android.os.StrictMode$StrictModeDiskReadViolation: policy=31violation=2 at android.os.StrictMode$AndroidBlockGuardPolicy.onReadFromDisk( StrictMode.java:1135) getAppsList() .subscribeOn(Schedulers.io()) .subscribe(observer)
  39. 39. D/StrictMode: StrictMode policy violation; ~duration=253 ms: android.os.StrictMode$StrictModeDiskReadViolation: policy=31violation=2 at android.os.StrictMode$AndroidBlockGuardPolicy.onReadFromDisk(StrictMode.java:1135) getAppsList() .subscribeOn(Schedulers.io()) .subscribe(new Observer<List<AppInfo>>() {...} Only the original thread that created a view hierarchy can touch its views. getAppsList() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(jonSnow); Defeating Android MainThread issue
  40. 40. private Observable<AppInfo> getApps(List<AppInfo> apps) { return Observable.create(subscriber -> { // let's waste some time for (double i = 0; i < 1000000000; i++) { double y = i * i; } for (AppInfo app : apps) { subscriber.onNext(app); } subscriber.onCompleted(); }); } Defeating Android MainThread issue
  41. 41. I/Choreographer: Skipped 598 frames! The application may be doing too much work on its main thread. Defeating Android MainThread issue
  42. 42. getObservableApps(apps) .subscribeOn(Schedulers.computation()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(jonShow) Schedule all the things!! ✓Schedulers.immediate() ✓Schedulers.trampoline() ✓Schedulers.newThread()
  43. 43. TYPE AsyncSubject BehaviorSubject PublishSubject ReplaySubject Subjects
  44. 44. Hot Observable Cold Observable
  45. 45. Question About RxJava?
  46. 46. Flux Actions Stores
  47. 47. View Presenter / Controller View Presenter / Controller SERVER Data Layer
  48. 48. View Store Action Dispatcher EventObserver Action Dispatcher Event
  49. 49. public class ActionObject {
 private final ArrayMap<String, Object> data;
 private final String type;
 
 public ActionObject(String type, ArrayMap<String,Object> actions) {
 this.type = type;
 this.data = new ArrayMap<>();
 for (Map.Entry<String,Object> item :
 actions.entrySet() ) {
 data.put(item.getKey(),item.getValue());
 }
 }
 
 public String getType() {
 return type;
 }
 
 public Object get(String connectionState) {
 return data.get(connectionState);
 }
 }
  50. 50. public class ConnectionStateAction {
 
 public static void setConnectionState(@ConnectionStateStore.ConnectionState String state){
 ArrayMap<String, Object> list = new ArrayMap<>();
 Pair<String, String> item = new Pair<>(Keys.CONNECTION_STATE, state);
 list.put(item.first,item.second);
 ActionObject actionObject = new ActionObject(Actions.CONNECTION_STATE,list);
 EventBus.getDefault().post(actionObject);
 }
 }
  51. 51. public class ConnectionStateStore {
 
 public static final String DISCONNECT = "DISCONNECT";
 public static final String CONNECTED = "CONNECTED";
 public static final String CONNECTING = "CONNECTING";
 
 private String connectionState = DISCONNECT;
 
 private static ConnectionStateStore mInstance;
 
 BehaviorSubject<String> mObservable;
 
 public static ConnectionStateStore getSingleton(){
 if (mInstance == null)
 mInstance = new ConnectionStateStore();
 
 return mInstance;
 }
 
 private ConnectionStateStore() {
 mObservable = BehaviorSubject.create();
 mObservable.onNext(connectionState);
 }
  52. 52. 
 public Observable<String> getConnectionObservable() {
 return mObservable.distinctUntilChanged();
 }
 
 
 @StringDef({DISCONNECT, CONNECTED, CONNECTING})
 public @interface ConnectionState {
 }
 
 private void setConnectionState(@ConnectionState String connectionState) {
 this.connectionState = connectionState;
 mObservable.onNext(connectionState);
 }
 @Subscribe(threadMode = ThreadMode.BACKGROUND)
 public void onAction(ActionObject action) {
 switch (action.getType()) {
 case Actions.CONNECTION_STATE:
 String state = (String) action.get(Keys.CONNECTION_STATE);
 setConnectionState(state);
 break;
 }
 }
  53. 53. @_siavasha Question? useful links: http://rxmarbles.com/ http://reactivex.io/documentation/ https://github.com/skimarxall/RxFlux

×