Posting Scraped Tweets to Loklak server from Loklak Wok Android

Loklak Wok Android is a peer harvester that posts collected  messages to the Loklak Server. The suggestions to search tweets are fetched using suggest API endpoint. Using the suggestion queries, tweets are scraped. The scraped tweets are shown in a RecyclerView and simultaneously they are posted to loklak server using push API endpoint. Let’s see how this is implemented. Adding Dependencies to the project This feature heavily uses Retrofit2, Reactive extensions(RxJava2, RxAndroid and Retrofit RxJava adapter) and RetroLambda (for Java lambda support in Android). In app/build.gradle: apply plugin: 'com.android.application' apply plugin: 'me.tatarka.retrolambda' android { ... packagingOptions { exclude 'META-INF/rxjava.properties' } } dependencies { ... compile 'com.google.code.gson:gson:2.8.1' compile 'com.squareup.retrofit2:retrofit:2.3.0' compile 'com.squareup.retrofit2:converter-gson:2.3.0' compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0' compile 'io.reactivex.rxjava2:rxjava:2.0.5' compile 'io.reactivex.rxjava2:rxandroid:2.0.1' }   In build.gradle project level: dependencies { classpath 'com.android.tools.build:gradle:2.3.3' classpath 'me.tatarka:gradle-retrolambda:3.2.0' }   Implementation The suggest and push API endpoint is defined in LoklakApi interface public interface LoklakApi { @GET("/api/suggest.json") Observable<SuggestData> getSuggestions(@Query("q") String query, @Query("count") int count); @POST("/api/push.json") @FormUrlEncoded Observable<Push> pushTweetsToLoklak(@Field("data") String data); }   The POJOs (Plain Old Java Objects) for suggestions and posting tweets are obtained using jsonschema2pojo, Gson uses POJOs to convert JSON to Java objects. The REST client is created by Retrofit2 and is implemented in RestClient class. The Gson converter and RxJava adapter for retrofit is added in the retrofit builder. create method is called to generate the API methods(retrofit implements LoklakApi Interface). public class RestClient { private RestClient() { } private static void createRestClient() { sRetrofit = new Retrofit.Builder() .baseUrl(BASE_URL) // gson converter .addConverterFactory(GsonConverterFactory.create(gson)) // retrofit adapter for rxjava .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .build(); } private static Retrofit getRetrofitInstance() { if (sRetrofit == null) { createRestClient(); } return sRetrofit; } public static <T> T createApi(Class<T> apiInterface) { // create method to generate API methods return getRetrofitInstance().create(apiInterface); } }   The suggestions are fetched by calling getSuggestions after LoklakApi interface is implemented. getSuggestions returns an Observable of type SuggestData, which contains the suggestions in a List. For scraping tweets only a single query needs to be passed to LiquidCore, so flatmap is used to transform the observabe and then fromIterable operator is used to emit single queries as string to LiquidCore which then scrapes tweets, as implemented in fetchSuggestions private Observable<String> fetchSuggestions() { LoklakApi loklakApi = RestClient.createApi(LoklakApi.class); Observable<SuggestData> observable = loklakApi.getSuggestions("", 2); return observable.flatMap(suggestData -> { List<Query> queryList = suggestData.getQueries(); List<String> queries = new ArrayList<>(); for (Query query : queryList) { queries.add(query.getQuery()); } return Observable.fromIterable(queries); }); }   As LiquidCore uses callbacks to create a connection between NodeJS instance and Android, to maintain a flow of observables a custom observable is created using create operator which encapsulates the callbacks inside it. For a detail understanding of how LiquidCore event handling works, please go through the example. The way it is implemented in getScrapedTweets: private Observable<ScrapedData> getScrapedTweets(final String query) { final String LC_TWITTER_URI = "android.resource://org.loklak.android.wok/raw/twitter"; URI uri = URI.create(LC_TWITTER_URI); return Observable.create(emitter -> { // custom observable creation EventListener startEventListener = (service, event, payload) -> { service.emit(LC_QUERY_EVENT, query); service.emit(LC_FETCH_TWEETS_EVENT); }; EventListener getTweetsEventListener = (service, event, payload) -> { ScrapedData scrapedData = mGson.fromJson(payload.toString(), ScrapedData.class);…

Continue ReadingPosting Scraped Tweets to Loklak server from Loklak Wok Android

Implementing Tweet Search Suggestions in Loklak Wok Android

Loklak Wok Android not only is a peer harvester for Loklak Server but it also provides users to search tweets using Loklak’s API endpoints. To provide a better search tweet search experience to the users, the app provides search suggestions using suggest API endpoint. The blog describes how “Search Suggestions” is implemented. Third Party Libraries used to Implement Suggestion Feature Retrofit2: Used for sending network request Gson: Used for serialization, JSON to POJOs (Plain old java objects). RxJava and RxAndroid: Used to implement a clean asynchronous workflow. Retrolambda: Provides support for lambdas in Android. These libraries can be installed by adding the following dependencies in app/build.gradle android { …. // removes rxjava file repetations packagingOptions { exclude 'META-INF/rxjava.properties' } } dependencies { // gson and retrofit2 compile 'com.google.code.gson:gson:2.8.1' compile 'com.squareup.retrofit2:retrofit:2.3.0' compile 'com.squareup.retrofit2:converter-gson:2.3.0' compile 'com.squareup.retrofit2:adapter-rxjava2:2.3.0' // rxjava and rxandroid compile 'io.reactivex.rxjava2:rxjava:2.0.5' compile 'io.reactivex.rxjava2:rxandroid:2.0.1' compile 'com.jakewharton.rxbinding2:rxbinding:2.0.0' }   To add retrolambda // in project's build.gradle dependencies { … classpath 'me.tatarka:gradle-retrolambda:3.2.0' } // in app level build.gradle at the top apply plugin: 'me.tatarka.retrolambda'   Fetching Suggestions Retrofit2 sends a GET request to search API endpoint, the JSON response returned is serialized to Java Objects using the models defined in models.suggest package. The models can be easily generated using JSONSchema2Pojo. The benefit of using Gson is that, the hard work of parsing JSON is easily handled by it. The static method createRestClient creates the retrofit instance to be used for network calls private static void createRestClient() { sRetrofit = new Retrofit.Builder() .baseUrl(BASE_URL) // base url : https://api.loklak.org/api/ .addConverterFactory(GsonConverterFactory.create(gson)) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .build(); }   The suggest endpoint is defined in LoklakApi interface public interface LoklakApi { @GET("/api/suggest.json") Observable<SuggestData> getSuggestions(@Query("q") String query); @GET("/api/suggest.json") Observable<SuggestData> getSuggestions(@Query("q") String query, @Query("count") int count); …. }   Now, the suggestions are obtained using fetchSuggestion method. First, it creates the rest client to send network requests using createApi method (which internally calls creteRestClient implemented above). The suggestion query is obtained from the EditText. Then the RxJava Observable is subscribed in a separate thread which is specially meant for doing IO operations and finally the obtained data is observed i.e. views are inflated in the MainUI thread. private void fetchSuggestion() { LoklakApi loklakApi = RestClient.createApi(LoklakApi.class); // rest client created String query = tweetSearchEditText.getText().toString(); // suggestion query from EditText Observable<SuggestData> suggestionObservable = loklakApi.getSuggestions(query); // observable created Disposable disposable = suggestionObservable .subscribeOn(Schedulers.io()) // subscribed on IO thread .observeOn(AndroidSchedulers.mainThread()) // observed on MainUI thread .subscribe(this::onSuccessfulRequest, this::onFailedRequest); // views are manipulated accordingly mCompositeDisposable.add(disposable); }   If the network request is successful onSuccessfulRequest method is called which updates the data in the RecyclerView. private void onSuccessfulRequest(SuggestData suggestData) { if (suggestData != null) { mSuggestAdapter.setQueries(suggestData.getQueries()); // data updated. } setAfterRefreshingState(); }   If the network request fails then onFailedRequest is called which displays a toast saying “Cannot fetch suggestions, Try Again!”. If requests are sent simultaneously and they fail, the previous message i.e. the previous toast is removed. private void onFailedRequest(Throwable throwable) { Log.e(LOG_TAG, throwable.toString()); if (mToast != null) { // checks if a previous toast is present mToast.cancel();…

Continue ReadingImplementing Tweet Search Suggestions in Loklak Wok Android

Invalidating user login using JWT in Open Event Orga App

User authentication is an essential part of Open Event Orga App (Github Repo), which allows an organizer to log in and perform actions on the event he/she organizes. Backend for the application, Open Event Orga Server sends an authentication token on successful login, and all subsequent privileged API requests must include this token. The token is a JWT (Javascript Web Token) which includes certain information about the user, such as identifier and information about from when will the token be valid, when will it expire and a signature to verify if it was tampered. Parsing the Token Our job was to parse the token to find two fields: Identifier of user Expiry time of the token We stored the token in our shared preference file and loaded it from there for any subsequent requests. But, the token expires after 24 hours and we needed our login model to clear it once it has expired and shown the login activity instead. To do this, we needed to parse the JWT and compare the timestamp stored in the exp field with the current timestamp and determine if the token is expired. The first step in the process was to parse the token, which is essentially a Base 64 encoded JSON string with sections separated by periods. The sections are as follows: Header ( Contains information about algorithm used to encode JWT, etc ) Payload ( The data in JWT - exp. Iar, nbf, identity, etc ) Signature ( Verification signature of JWT ) We were interested in payload and for getting the JSON string from the token, we could have used Android’s Base64 class to decode the token, but we wanted to unit test all the util functions and that is why we opted for a custom Base64 class for only decoding our token. So, first we split the token by the period and decoded each part and stored it in a SparseArrayCompat public static SparseArrayCompat<String> decode(String token) { SparseArrayCompat<String> decoded = new SparseArrayCompat<>(2); String[] split = token.split("\\."); decoded.append(0, getJson(split[0])); decoded.append(1, getJson(split[1])); return decoded; }   The getJson function is primarily decoding the Base64 string private static String getJson(String strEncoded) { byte[] decodedBytes = Base64Utils.decode(strEncoded); return new String(decodedBytes); } The decoded information was stored in this way 0={"alg":"HS256","typ":"JWT"}, 1={"nbf":1495745400,"iat":1495745400,"exp":1495745800,"identity":344} Extracting Information Next, we create a function to get the expiry timestamp from the token. We could use GSON or Jackson for the task, but we did not want to map fields into any object. So we simply used JSONObject class which Android provides. It took 5 ms on average to parse the JSON instead of 150 ms by GSON public static long getExpiry(String token) throws JSONException { SparseArrayCompat<String> decoded = decode(token); // We are using JSONObject instead of GSON as it takes about 5 ms instead of 150 ms taken by GSON return Long.parseLong(new JSONObject(decoded.get(1)).get("exp").toString()); }   Next, we wanted to get the ID of user from token to determine if a new user is logging in or an old one, so…

Continue ReadingInvalidating user login using JWT in Open Event Orga App

Smart Data Loading in Open Event Android Orga App

In any API centric native application like the Open Event organizer app (Github Repo), there is a need to access data through network, cache it for later use in a database, and retrieve data selectively from both sources, network and disk. Most of Android Applications use SQLite (including countless wrapper libraries on top of it) or Realm to manage their database, and Retrofit has become a de facto standard for consuming a REST API. But there is no standard way to manage the bridge between these two for smart data loading. Most applications directly make calls to DB or API service to selectively load their data and display it on the UI, but this breaks fluidity and cohesion between these two data sources. After all, both of these sources manage the same kind of data. Suppose you wanted to load your data from a single source without having to worry from where it is coming, it’d require a smart model or repository which checks which kind of data you want to load, check if it is available in the DB, load it from there if it is. And if it not, call the API service to load the data and also save it in the DB there itself. These smart models are self contained, meaning they handle the loading logic and also handle edge cases and errors and take actions for themselves about storing and retrieving the data. This makes presentation or UI layer free of data aspects of the application and also remove unnecessary handling code unrelated to UI. From the starting of Open Event Android Orga Application planning, we proposed to create an efficient MVP based design with clear separation of concerns. With use of RxJava, we have created a single source repository pattern, which automatically handles connection, reload and database and network management. This blog post will discuss the implementation of the AbstractObservableBuilder class which manages from which source to load the data intelligently Feature Set So, first, let’s discuss what features should our AbstractObservableBuilder class should have: Should take two inputs - disk source and network source Should handle force reload from server Should handle network connection logic Should load from disk observable if data is present Should load from network observable if data is not present is disk observable This constitutes the most basic data operations done on any API based Android application. Now, let’s talk about the implementation Implementation Since our class will be of generic type, we will used variable T to denote it. Firstly, we have 4 declarations globally private IUtilModel utilModel; private boolean reload; private Observable<T> diskObservable; private Observable<T> networkObservable;   UtilModel tells us if the device is connected to internet or not reload tells if the request should bypass database and fetch from network source only diskObservable is the database source of the item to be fetched networkObservable is the network source of the same item Next is a very simple implementation of the builder pattern methods which will be…

Continue ReadingSmart Data Loading in Open Event Android Orga App

Addition of Bookmark Icon in Schedule ViewHolder in Open Event Android App

In the Open Event Android app we only had a list of sessions in the schedule page without  the ability to bookmark the session unless we went into the SessionDetailPage or visited the session list via the tracks page or the locations page. This was obviously very inconvenient. There were several iterations of UI design for the same. Taking cues from the Google I/O 17 App I thought that the addition of the Bookmark Icon in the Schedule ViewHolder would be helpful to the user. In this blog post I will be talking about how this feature was implemented. Layout Implementation for the Bookmark Icon <ImageButton    android:id="@+id/slot_bookmark"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:layout_gravity="end"    android:layout_alignParentEnd="true"    android:layout_alignParentRight="true"    android:layout_alignParentBottom="true"    android:tint="@color/black"    android:background="?attr/selectableItemBackgroundBorderless"    android:contentDescription="@string/session_bookmark_status"    android:padding="@dimen/padding_small"    app:srcCompat="@drawable/ic_bookmark_border_white_24dp" /> The bookmark Icon was modelled as an ImageButton inside the item_schedule.xml file which serves as the layout file for the DayScheduleViewHolder. Bookmark Icon Functionality in DayScheduleAdapter The Bookmark Icon had mainly 3 roles : Add the session to the list of bookmarks (obviously) Generate the notification giving out the bookmarked session details. Generate a Snackbar if the icon was un-clicked which allowed the user to restore the bookmarked status of the session. Update the bookmarks widget. Now we will be seeing how was all this done. Some of this was already done previously in the SessionListAdapter. We just had to modify some of the code to get our desired result.        Session not bookmarked                      Session bookmarked                       First we just set a different icon to highlight the Bookmarked and the un-bookmarked status. This code snippet highlights how this is done. if(session.isBookmarked()) {    slot_bookmark.setImageResource(R.drawable.ic_bookmark_white_24dp); } else { slot_bookmark.setImageResource(R.drawable.ic_bookmark_border_white_24dp); } slot_bookmark.setColorFilter(storedColor,PorterDuff.Mode.SRC_ATOP); We check if the session is bookmarked by calling a function isBookmarked() and choose one of the 2 bookmark icons depending upon the bookmark status. If a session was found out to be bookmarked and the Bookmark Icon was we use the WidgetUpdater.updateWidget() function to remove that particular session from the  Bookmark Widget of the app. During this a  Snackbar is also generated “Bookmark Removed” with an UNDO option which is functional. realmRepo.setBookmark(sessionId, false).subscribe(); slot_bookmark.setImageResource(R.drawable.ic_bookmark_border_white_24dp); if ("MainActivity".equals(context.getClass().getSimpleName())) {    Snackbar.make(slot_content, R.string.removed_bookmark, Snackbar.LENGTH_LONG)            .setAction(R.string.undo, view -> {                realmRepo.setBookmark(sessionId, true).subscribe();                slot_bookmark.setImageResource(R.drawable.ic_bookmark_white_24dp);                WidgetUpdater.updateWidget(context);            }).show(); else {    Snackbar.make(slot_content, R.string.removed_bookmark, Snackbar.LENGTH_SHORT).show(); } If a session wasn’t bookmarked earlier but the Bookmark Icon was clicked we would firstly need to update the bookmark status within our local Realm Database. realmRepo.setBookmark(sessionId, true).subscribe(); We would also create a notification to notify the user. NotificationUtil.createNotification(session, context).subscribe(        () -> Snackbar.make(slot_content,                R.string.added_bookmark,                Snackbar.LENGTH_SHORT)                .show(),        throwable -> Snackbar.make(slot_content,                R.string.error_create_notification,                Snackbar.LENGTH_LONG).show()); The static class Notification Util is responsible for the generation of notifications. The internal working of that class is not necessary right now. What this snippet of code does is that It creates a Snackbar upon…

Continue ReadingAddition of Bookmark Icon in Schedule ViewHolder in Open Event Android App

Implementing Barcode Scanning in Open Event Android Orga App using RxJava

One of the principal goals of Open Event Orga App (Github Repo) is to let the event organizer to scan the barcode identifier of an attendee at the time of entry in the event, in order to quickly check in that attendee. Although there are several scanning APIs available throughout the web for Android Projects, we chose Google Vision API as it handles multitude of formats and orientations automatically with little to no configuration, integrates seamlessly with Android, and is provided by Google itself, ensuring great support in future as well. Currently, the use case of our application is: Scan barcode from the camera feed Detect and show barcode information on screen Iterate through the attendee list to match the detected code with unique attendee identifier Successfully return to the caller with scanned attendee’s information so that a particular action can be taken There are several layers of optimisations done in the Orga Application to make the user interaction fluid and concise. I’ll be sharing a few in this blog post regarding the configuration and handling of bursty data from camera source efficiently. To see the full implementation, you can visit the Github Repository of the project using the link provided above. Configuration The configuration of our project was done through Dagger 2 following the dependency injection pattern, which is not the focus of this post, but it is always recommended that you follow separation of concerns in your project and create a separate module for handling independent works like barcode scanner configuration. Normally, people would create factories with scanner, camera source and processors encapsulated. This enables the caller to have control over when things are initialized. Our configuration provides us two initialised objects, namely, CameraSource and BarcodeDetector @Provides BarcodeDetector providesBarCodeDetector(Context context, Detector.Processor<Barcode> processor) { BarcodeDetector barcodeDetector = new BarcodeDetector.Builder(context) .setBarcodeFormats(Barcode.QR_CODE) .build(); barcodeDetector.setProcessor(processor); return barcodeDetector; } @Provides CameraSource providesCameraSource(Context context, BarcodeDetector barcodeDetector) { return new CameraSource .Builder(context, barcodeDetector) .setRequestedPreviewSize(640, 480) .setRequestedFps(15.0f) .setAutoFocusEnabled(true) .build(); } The fields needed to create the objects are provided as arguments to the provider functions as all the dependencies required to construct these objects. Now focusing on the Detector.Processor requirement of the BarcodeDetector is the classic example on non injectable code. This is because the processor is to be supplied by the activity or any other object which wants to receive the callback with the detected barcode data. This means we could inject it at the time of creation of the Activity or Presenter itself. We could easily overcome by adding a constructor to this dagger module containing the Barcode.Processor at the time of injection, but that would violate our existing 0 configuration based model where we just get the required component from the Application class and inject it. So, we wrapped the the processor into a PublishSubject @Provides @Singleton @Named("barcodeEmitter") PublishSubject<Notification<Barcode>> providesBarcodeEmitter() { return PublishSubject.create(); } @Provides @Singleton Detector.Processor<Barcode> providesProcessor(@Named("barcodeEmitter") PublishSubject<Notification<Barcode>> emitter) { return new Detector.Processor<Barcode>() { @Override public void release() { // No action to be taken } @Override public void receiveDetections(Detector.Detections<Barcode> detections) {…

Continue ReadingImplementing Barcode Scanning in Open Event Android Orga App using RxJava

Testing Asynchronous Code in Open Event Orga App using RxJava

In the last blog post, we saw how to test complex interactions through our apps using stubbed behaviors by Mockito. In this post, I’ll be talking about how to test RxJava components such as Observables. This one will focus on testing complex situations using RxJava as the library itself provides methods to unit test your reactive streams, so that you don’t have to go out of your way to set contraptions like callback captors, and implement your own interfaces as stubs of the original one. The test suite (kind of) provided by RxJava also allows you to test the fate of your stream, like confirming that they got subscribed or an error was thrown; or test an individual emitted item, like its value or with a predicate logic of your own, etc. We have used this heavily in Open Event Orga App (Github Repo) to detect if the app is correctly loading and refreshing resources from the correct source. We also capture certain triggers happening to events like saving of data on reloading so that the database remains in a consistent state. Here, we’ll look at some basic examples and move to some complex ones later. So, let’s start. public class AttendeeRepositoryTest { private AttendeeRepository attendeeRepository; @Before public void setUp() { testDemo = new TestDemo(); } @Test public void shouldReturnAttendeeByName() { // TODO: Implement test } }   This is our basic test class setup with general JUnit settings. We’ll start by writing our tests, the first of which will be to test that we can get an attendee by name. The attendee class is a model class with firstName and lastName. And we will be checking if we get a valid attendee by passing a full name. Note that although we will be talking about the implementation of the code which we are writing tests for, but only in an abstract manner, meaning we won’t be dealing with production code, just the test. So, as we know that Observables provide a stream of data. But here, we are only concerned with one attendee. Technically, we should be using Single, but for generality, we’ll stick with Observables. So, a person from the background of JUnit would be tempted to write this code below. Attendee attendee = attendeeRepository.getByAttendeeName("John Wick") .blockingFirst(); assertEquals("John Wick", attendee.getFirstName() + attendee.getLastName());   So, what this code is doing is blocking the thread till the first attendee is provided in the stream and then checking that the attendee is actually John Wick. While this code works, this is not reactive. With the reactive way of testing, not only you can test more complex logic than this with less verbosity, but it naturally provides ways to test other behaviors of Reactive streams such as subscriptions, errors, completions, etc. We’ll only be covering a few. So, let’s see the reactive version of the above test. attendeeRepository.getByAttendeeName("John Wick") .firstElement() .test() .assertNoErrors() .assertValue(attendee -> "John Wick".equals( attendee.getFirstName() + attendee.getLastName() ));   So clean and complete. Just by calling test() on the returned…

Continue ReadingTesting Asynchronous Code in Open Event Orga App using RxJava

Making Open Event Organizer Android App Reactive

FOSSASIA's Open Event Organizer is an Android Application for Event Management. The core feature it provides is two way attendee check in, directly by searching name in the list of attendees or just by scanning a QR code from ticket. So as attendees of an event can be really large in number like 1000+ or more than that, it should not alter the performance of the App. Just imagine a big event with lot of attendees (lets say 1000+) and if check in feature of the app is slow what will be the mess at entrance where each attendee is waiting for his ticket to be scanned and verified. For example, a check in via QR code scan. A complete process is somewhat like this: QR scanner scans the ticket code and parse it into the ticket identifier string. Identifier string is parsed to get an attendee id from it. Using the attendee id, attendee is searched in the complete attendees list of the event. On match, attendee's check in status is toggled by making required call to the server. On successful toggling the attendee is updated in database accordingly. And check in success message is shown on the screen. From the above tasks 1st and 6th steps only are UI related. Remaining all are just background tasks which can be run on non-UI thread instead of carrying them on the same UI thread which is mainly responsible for all the user interaction with the app. ReactiveX, an API for asynchronous programming enables us to do this. Just for clarification asynchronous programming is not multithreading. It just means the tasks are independent and hence can be executed at same time. This will be another big topic to talk about. Here we have used ReactiveX just for running these tasks in background at the same time UI thread is running. Here is our code of barcode processing: private void processBarcode(String barcode) {   Observable.fromIterable(attendees)       .filter(attendee -> attendee.getOrder() != null)       .filter(attendee -> (attendee.getOrder().getIdentifier() + "-" + attendee.getId()).equals(barcode))       .subscribeOn(Schedulers.computation())       .observeOn(AndroidSchedulers.mainThread())       .subscribe(attendee -> {           // here we get the attendee and           // further processing can be called here           scanQRView.onScannedAttendee(attendee);       });   } In the above code you will see the actual creation of an Observable. Observable class has a method fromIterable which takes list of items and create an Observable which emits these items. So hence we need to search the attendee in the attendees list we have already stored in database. Filter operator filters the items emitted using the function provided. Last two lines are important here which actually sets how our subscriber is going to work. You will need to apply this thread management setting to your observable while working on android. You don't actually have to worry about it. Just remember subscribeOn sets the thread on which actually the background tasks will run and on item emission subscriber handle it on main thread which is set by observeOn method. Subscribe operator provides the function what actually we need to run on main thread…

Continue ReadingMaking Open Event Organizer Android App Reactive

Intro to concurrency and Refactoring Open Event Android using RxJava

Functional reactive programming seems to have taken the whole development world by storm. It’s one of the hottest thing even after 2 years of constant traction in the communities of several programming languages, where different implementations of the specifications defined by Rx or Reactive Extensions have changed the paradigm of programming for many professional and enthusiast developers. RxJava is no exception, not only has it been widely adopted by Android and Java developers unanimously, but also received attention of well known and top developers of both communities. The reason of its success is the fluent API with heavy toolset it provides from the Functional Programming paradigm and its ease and natural ability to handle concurrency on different levels based on the type of operation being performed, i.e., computations, I/O, etc. It basically takes away the several constraints and concurrency related checklists developers had to maintain while working with thread management. So, now, developers can’t make an excuse for using database operations on the Main Thread because offloading it on another thread is hard. So, in this blog post, I will be detailing the process of converting the existing synchronous code of your app into a performant reactive code without breaking the structure of your project, like we did in Open Event Android (Github Repo). Before starting, I have assumed that you know how to add RxJava dependency to your project as it is covered in many other blog posts and the documentation is also very clear. Secondly, you should also add RxAndroid dependency as it contains the Scheduler needed to work on Android’s Main Thread. So, Let’s start. Current State Currently, our code loads the queries from database synchronously on Main Thread using the SQLiteDatabase for an Android application. This is how it looks like - As we can see, we are directly returning the loaded results to the caller. This is called synchronous call, meaning the caller will block till the function is returned, and can’t move further to do anything else. It basically waits for the function to return, which may take hundreds of milliseconds to seconds based on the function it performs. New Android version crash the applications that perform Network interactions on the main thread but no such restriction for disk based operations is there, making it hard to enforce best performance practices. Before RxJava, there were interfaces made for different kinds of objects, passed in as parameters of the db request function, which created a new thread and performed operations and when completed, returned back the results to the main thread using the postOnUiThread method, so that the views could update themselves. The interface implementations passed are called callbacks because they call a particular function that you provide back when the asynchronous operation is completed. Even the calling of callback function is delegated on the implementor and may result in undesired effects. The query done in this fashion is called an asynchronous query because the execution of this takes place in parallel with main thread…

Continue ReadingIntro to concurrency and Refactoring Open Event Android using RxJava