Table of Contents for
Reactive Android Programming

Version ebook / Retour

Cover image for bash Cookbook, 2nd Edition Reactive Android Programming by Tadas Subonis Published by Packt Publishing, 2017
  1. Reactive Android Programming
  2. Title Page
  3. Copyright
  4. Credits
  5. About the Author
  6. About the Reviewers
  7. www.PacktPub.com
  8. Customer Feedback
  9. Table of Contents
  10. Preface
  11. What this book covers
  12. What you need for this book
  13. Who this book is for
  14. Conventions
  15. Reader feedback
  16. Customer support
  17. Downloading the example code
  18. Errata
  19. Piracy
  20. Questions
  21. Building your First “Hello World” RxJava Application
  22. Creating the application
  23. Dependencies
  24. Core dependencies
  25. UI dependencies
  26. Very first user interface
  27. Adding RecyclerView
  28. Stock data Value objects
  29. Using Retrolambda
  30. Setup
  31. Usage
  32. Updating the existing code
  33. Summary
  34. Understanding the Basics of RxJava
  35. Observables
  36. Hot and Cold Observables
  37. Disposables
  38. Schedulers
  39. Scheduling examples
  40. Investigating the flow of an Observable
  41. Flowable
  42. Dropping items
  43. Preserve latest item
  44. Buffering
  45. Completable, Single, and Maybe types
  46. Completable
  47. Single
  48. Maybe
  49. Summary
  50. Learning to use Retrofit by Fetching Financial Data
  51. Setting up Retrofit
  52. Making HTTP requests
  53. Service interface
  54. Service factory
  55. Creating service
  56. Transforming request data
  57. Parsing JSON
  58. Querying data
  59. Transforming JSON value objects
  60. Unwrapping nested objects
  61. Unwrapping lists
  62. Converting objects
  63. Displaying data on the UI
  64. Regular updates
  65. Handling multiple records on the UI
  66. Summary
  67. Integrating RxJava 1.0 with RxJava 2.0
  68. Differences between the versions
  69. Dependencies and package name
  70. Functional interfaces
  71. Flowable
  72. Gluing different RxJava versions
  73. Setup
  74. Converting RxJava 1.0 Observables
  75. Converting to Flowables
  76. Summary
  77. Writing Data to SQLite and Schedulers
  78. Schedulers
  79. Types of Schedulers
  80. Single
  81. Trampoline
  82. NewThread
  83. IO
  84. Computation
  85. Executor Scheduler
  86. Android Scheduler
  87. Using Schedulers
  88. subscribeOn
  89. observeOn
  90. Rules of thumb
  91. Achieving parallelism
  92. Structuring code for parallelism
  93. Writing data with StorIO
  94. Setting up StorIO
  95. Configuring StorIO
  96. Preparing constants
  97. Creating write resolvers
  98. Creating StorIOSQLite interface
  99. Data persistence flow
  100. Summary
  101. Error Handling and SQLite Data Reading
  102. Exception handling in RxJava
  103. Using subscribe()
  104. Using onExceptionResumeNext()
  105. Using doOnError()
  106. Other error processing methods
  107. onErrorResumeNext()
  108. onErrorReturn
  109. onErrorReturnItem
  110. Showing errors in Android UI
  111. Empty State Screen
  112. Toast notification
  113. Centralized error logging
  114. Central handler
  115. Using RxJava plugins
  116. Reading SQLite data with StorIO
  117. Get resolver
  118. Reading cursor columns
  119. Converting data
  120. Creating the StockUpdate object
  121. Configuring Type Mapping
  122. Offline fallback for StockUpdate entries
  123. StorIO database query
  124. Creating the StorIO Observable
  125. The final onExceptionResumeNext() block
  126. Informing the user about the failure
  127. Missing delete resolver
  128. Summary
  129. Integrating RxJava with Activity Lifecycle
  130. Android Activity Lifecycle
  131. Lifecycle review
  132. Fragment lifecycles
  133. Setting up an activity
  134. Things to know about onCreate() calls
  135. Resource leaks
  136. Memory leaks
  137. Memory leak example
  138. Leaking with Observables
  139. Lost background tasks example
  140. Paying special attention to onCreate()
  141. Cleaning up Subscriptions
  142. Using Disposable
  143. Using CompositeDisposable
  144. Utilizing the RxLifecycle library
  145. Setting up the library
  146. Binding to Activity Lifecycle
  147. Binding to Activity without subclassing
  148. Binding to the Fragment lifecycle
  149. Binding to views
  150. Updating the data fetching flow
  151. Summary
  152. Writing Custom Observables
  153. How to create custom Observables
  154. Integrating with standard Java API
  155. Integrating with Emitter API
  156. Cleaning up
  157. Reading tweets for stocks reactively
  158. Setup
  159. Getting access to Twitter
  160. Custom Observable for Twitter
  161. Configuring Twitter
  162. Listening to status updates
  163. Emitting status updates into Observable
  164. Showing tweets in the UI
  165. Integrating Twitter status updates into the Flow
  166. Updating Value Objects
  167. StockUpdate adjustments
  168. StorIO adjustments
  169. Updating layouts
  170. Other improvements
  171. Summary
  172. Advanced Observable Flows Explained
  173. Unwrapping Observables
  174. Transforming values with Map
  175. FlatMap Observables
  176. More FlatMap variations
  177. SwitchMap
  178. Passing values
  179. Tuples
  180. JavaTuples
  181. Custom classes
  182. Updated flow
  183. Combining items
  184. Zip
  185. Combine latest
  186. Concatenating streams
  187. Concat
  188. Merge
  189. Filtering
  190. Cleaning stock adapter
  191. Advanced filtering with distinct calls
  192. Example of GroupBy
  193. Filtering tweets
  194. Summary
  195. Higher Level Abstractions
  196. Extracting code into methods
  197. Making conditions explicit
  198. Extracting consumers
  199. Using method references
  200. Extracting FlatMap
  201. Creating Factory Methods
  202. Financial stock quote Observable
  203. Tweet retrieval Observable
  204. Offline flow Observable
  205. Resulting flow
  206. Using Transformations
  207. Regular code extractions
  208. A Place where things start getting ugly
  209. Simplifying code with Transformations
  210. Extracting item persistence code
  211. Creating transformer classes
  212. File-based caching example
  213. Using Transformation to track execution time
  214. Using Transformation to debug Observables
  215. Summary
  216. Basics of Subjects and Preference Persistence
  217. Subjects
  218. PublishSubject
  219. Multiple sources
  220. BehaviorSubject
  221. ReplaySubject
  222. AsyncSubject
  223. Using subjects in the application
  224. Using RxPreferences
  225. Setup
  226. Examples with RxPreferences
  227. Subjects for Settings
  228. Connecting subjects to Settings
  229. Creating UI for Settings
  230. Creating Settings activity
  231. Preferences XML
  232. Options menu
  233. Updating flow
  234. Settings for financial stock updates
  235. Settings for monitored tweets
  236. Entire merge block
  237. Fixes for duplicate entries
  238. Summary
  239. Learning to Read Marble Diagrams
  240. Core elements of marble diagrams
  241. Elements of the diagram
  242. RxMarbles tool
  243. Examining operators
  244. Map
  245. FlatMap
  246. onExceptionResumeNext()
  247. GroupBy
  248. SubscribeOn and ObserveOn
  249. BehaviorSubject
  250. Summary

Creating StorIOSQLite interface

The final step before we can start using StorIO is to create a StorIOSQLite interface. It will be an object that will tie all our resolvers configuration and will be a central go-to interface for operations with the database.

However, before we can do that, there is one more class that's missing. It's the StorIODbHelper class, and it will extend SQLiteOpenHelperSQLiteOpenHelper is often used to handle the initialization of the database--creating tables, migrating old versions of tables, adding columns and so on. Basically, it ensures that the database is ready for work. We will keep this class very brief:

class StorIODbHelper extends SQLiteOpenHelper {

StorIODbHelper
(@NonNull Context context) {
super(context, "reactivestocks.db", null, 1);
}

@Override
public void onCreate(@NonNull SQLiteDatabase db) {
db.execSQL(StockUpdateTable.createTableQuery());
}

@Override
public void onUpgrade(@NonNull SQLiteDatabase db, int oldVersion,
int newVersion) {
}
}

As we do not care (yet) about database upgrade because we always start with a clean state, we set the onUpgrade method to be empty. In our case, it's just the onCreate method that needs to be filled with the code:

db.execSQL(StockUpdateTable.createTableQuery());

This will create the table for StockUpdate tweet. Consider the following line:

super(context, "reactivestocks.db", null, 1);

It tells the helper that the filename for the database will be reactivestocks.db, and it's at version 1.

After the SQLiteOpenHelper class is created, we can proceed with the creation of the main interface. To keep the code well organized, we will put interface creation code in the StorIOFactory class in packt.reactivestocks.storio with the rest of the classes. The factory method itself will be as illustrated:

private static StorIOSQLite INSTANCE;

public synchronized static
StorIOSQLite get(Context context) {
if (INSTANCE != null) {
return INSTANCE;
}

INSTANCE
= DefaultStorIOSQLite.builder()
.sqliteOpenHelper(new StorIODbHelper(context))
.addTypeMapping(StockUpdate.class, SQLiteTypeMapping.
<StockUpdate>builder()
.putResolver(new StockUpdatePutResolver())
.getResolver(createGetResolver())
.deleteResolver(createDeleteResolver())
.build())
.build();

return
INSTANCE;
}

Let's dissect this piece by piece. Consider the given line:

.sqliteOpenHelper(new StorIODbHelper(context))

It gives StorIO access to the original SQLite database. Also, it will ensure that the tables are created before we start using the database. After that, a mapping configuration follows with this:

.addTypeMapping(StockUpdate.class, ...)

The purpose of this line is to specify the configuration that will handle the StockUpdate class. Take a look at the following lines which are a part of the configuration:

SQLiteTypeMapping.<StockUpdate>builder()
.putResolver(new StockUpdatePutResolver())
.getResolver(createGetResolver())
.deleteResolver(createDeleteResolver())
.build()

The following code specifies a class that will be used to handle write operations and we have just created this class a while ago:

 .putResolver(new StockUpdatePutResolver())

The following call sets the configuration that will specify how the database reads are handled:

.getResolver(createGetResolver())

However, since we will be leaving this for a later section, we will plug in a stub implementation here:

private static GetResolver<StockUpdate> createGetResolver() {
return new DefaultGetResolver<StockUpdate>() {
@NonNull
@Override
public StockUpdate mapFromCursor(@NonNull Cursor cursor) {
return null;
}
};
}

The final line will configure the delete action to correctly delete the record in the database when the entity is deleted in the code:

.deleteResolver(createDeleteResolver())

Again, we will use a stub implementation of the following:

private static DeleteResolver<StockUpdate> createDeleteResolver() {
return new DefaultDeleteResolver<StockUpdate>() {
@NonNull
@Override
protected DeleteQuery mapToDeleteQuery(@NonNull StockUpdate
object) {
return null;
}
};
}

Finally, the mapping configuration is created by calling .build(), and then the DefaultStorIOSQLite implementation is initialized with the same method (but on a different class).