There’s a list of “parties”, and a edit box and button to create a new one. On the “party” page, you can add or remove people.
The data is kept in sqlite, retrieved in a background thread. The threading and logic is managed in presenters, in a rough approximation of MVP. There’s a set of unit tests that individually test the database logic, and presenter coordination.
On Android there are 2 Activity classes that point at two Presenters. On iOS, there are 2 equivalent UIViewController classes that talk to the same presenter classes.
So, MVP architecture with unit tests, running on Android and iOS.
In the com.kgalligan.partyclicker.data package, there’s a sqlite open helper (DatabaseHelper) which manages basic data interaction, an interface for those methods (DataProvider), and data objects used by the orm. There’s also a Runnable for some background processing. That could be rolled into RX, but I wanted to make things more difficult.
In the com.kgalligan.partyclicker.presenter package you’ll find the 2 presenters, but also some related Dagger code, and a CrashReporter interface.
Looking at PartyListPresenter, you’ll see methods that interact with the data model, and an interface, UiInterface, which is implemented by PartyListActivity on Android, and PartyListViewController on iOS. The presenter code can interact with the view by way of UiInterface.
So, for example, to load the list of parties, the activity will call callRefreshPartyList(), which loads the data in a different thread, then calls refreshPartyList() on the UiInterface instance (which is the Activity or ViewController).
The unit tests for the presenters mock the UiInterface and verify that methods you expect to be called actually are. All of the tests happen in one thread. We inject an Observable.Transformer with dagger. In the app, the transformer handles subscribeOn and observeOn. In testing, nothing happens, so all calls to rx are on a single thread.
You’ll also notice we’re injecting DataProvider, which is implemented by sqlite in the live app, but an in-memory hand rolled implementation is available during testing. Unit testing!
Also notice DatabaseHelperTest. We’re testing the actual sqlite db, so we need access to the Android context. We have a special test runner, DopplRobolectricTestRunner, that will delegate to Robolectric when you’re testing in Java, and create an instance of co.touchlab.doppl.testing.TestingContext when running in iOS. Just a note on Robolectric here. We’re only using it for the Android context. None of the other functionality is implemented on the iOS side. Future implementations will either create this context without Robolectric, or possibly implement more of the Robolectric stack. See how that goes…
The important concept to take away is you can code your logic using the best practice methodologies of your choosing, assuming you keep the UI out of the logic, and write a complete set of tests to be run in both Android studios and Xcode.
For parts of your app that need to be exposed to shared code but cannot themselves be shared, the simple pattern is to create an interface in the shared code, and implement it on each platform. This is one of the core concepts of Doppl. Weaving shared code with platform specific code is natural and intuitive.
The obvious example here is the UiInterface provided in each presenter. To allow the shared code to manipulate the UI code, an interface is created in the presenter, which is then implemented by the platform specific UI, and passed into your shared code.
You can do something similar with things such as location listeners, bluetooth, etc.
First of all, we’re hiring. I think it’s very important I get that out there.
Second, we’re looking at an early stage release of “everything” shortly after Google I/O. That includes gradle plugin, libraries, etc. We’ve grown the Doppl team and are rapidly sorting out docs and code.
Third, we’re setting up a Slack group to start chatting. Until we create a signup page, email email@example.com
After a little tweaking, there are a few extra branches to try some stuff. The master branch uses “Squeaky”, which is a rewrite of ormlite I did a couple years ago, but never really promoted.
There’s another branch that uses SQLDelight for the database. There’s a third branch that uses greendao. Those were pretty simple. Then I decided to ruin my weekend and port SQLCipher to Doppl. The 4th branch is ‘greendaoencrypted’, which uses greenDAO encrypted db with SQLChiper. This is both experimental and somewhat more difficult to set up, as we can’t distribute SQLCipher directly, but you can do it. I believe in you.
Also, J2objc just released version 2! Our lightly modified J2objc runtime is up to date with master, so we’ll be at v2 as well.