Positronic Net
Better brains for your droids!
--- Robert Thau
Goals
- Eliminate boilerplate --- in UI code and elsewhere
- Eliminate clutter --- focus on the essentials
- Convention over configuration
- Make it easy to store and organize the data you're working on
- Adopt representations that fit the problem space
- Following best practices should not be a pain
What's that got to do with Scala?
- I've got a library which helps with some of this stuff
- Uses Scala as a JVM-native language which...
- Eliminates type-related clutter
- Supports control abstraction
- Supports useful concurrency-related idioms
Outline
- A few words on Android
- Dealing with UI boilerplate
- Callbacks with less pain
- Easier binding of UI components to data structures
- Dealing with data repositories
- Dealing with Android requirements
- Records and record managers
- Messaging for interfaces and updates
- Relations, type hierarchies...
A few words on Android
It's Java-ish. Mostly J2SE, but...
- Custom bytecodes. (Anything involving a ClassLoader breaks.)
- Custom UI layer (not Swing or AWT-based)
- Custom interface to SQLite (not JDBC)
- Custom RPC framework for invoking other apps, and
sharing tables of data
- Compared to a server, resources are... constrained.
Android UI
- Widgets: TextView, Checkbox, ImageView...
- Layout managers: LinearLayout, RelativeLayout...
- List widgets and adapters
- Adapter's job: "fill in widgets for item n"
- All access to UI is restricted to one thread
UI Goals
- Cut down on boilerplate
- Ease showing and updating data items
Cut down on boilerplate: not this...
Mapping data structures to the UI
Want to make things simple...
Setting firstName from firstName, etc., should
not require much fuss:
But that requires:
- Being able to say what "property" a widget relates to
- Being able to get or set "properties" on the record
Where do those widgets come from?
Widget properties...
- Widgets can have IDs...
- ... which are integers ...
- ... which are the value of R.id.propName
- So, use reflection to construct a map from values back to names.
"Reflective properties": explicit getter/setter
"Reflective properties": implicit setter
- No explicit setter
- As if copy is called, but...
- Implementation clones the instance and clobbers the value.
Exploiting this can be dangerous, but also useful.
UI binders
Binds properties of appropriate types to widgets with "matching" IDs.
Dealing with Data
- Platform constraints
- Platform data repositories
- Queries and updates
- Relations
- Other stuff...
Android UI --- DB constraints
- All access to UI is restricted to one thread
- Locking that thread locks up the UI
Implications
UI will stutter or freeze if "UI thread" blocks for...
- ... queries ...
- ... updates ...
- ... net access ...
So, don't do that!
How to do blocking work in the background?
- Android provides basic machinery:
- Can "post work" to be executed on the UI thread...
- ... or other "handler threads".
- But library mechanisms built on top of it can be awkward
So, borrow some better alternatives
- Want UI thread (and others?) to be able to defer work to
background, and have results posted back when available
- Sounds like Actors, Messages and Futures
- Don't want to put full Akka on the phones (yet?)...
- ... but a much cut-down version is still very useful.
Data repositories on Android
- Private SQLite databases, through a custom API
- "Content Provider"s, which do RPC to another process
- Both have ...similar query interfaces
- ... which return instances of the same Cursor interface
- So, can design a quasi-ORM which works for both
Basic concepts
- Want UI to do queries and updates through messaging
with actor-like entities
- Records are in messages both ways (inserts, queries)...
- ... so they must be immutable
Example: some simple data
Records ... and RecordManagers
(Partial) Message typing
- A Query on TodoItems always yields IndexedSeq[TodoItem]...
- ... so we shouldn't have to declare type of the future
- Same for FindById --- which returns a different type of
Future
- Type: QueryAction[ IndexedSeq[T], V ] --- different Vs
- For Query, V is IndexedSeq[T]
- For FindById, V is just T
Simple relationships --- schema
Simple relationships --- code
Mapping a simple content provider (1)
Mapping a simple content provider (2)
A messy provider: ContactsContract.Data
- Heterogeneous table representing name, phone, email...
- Common "contact ID" and "type" columns
- "data1" ... "data15", whose interpretation depends on the type
Data base class (simplified)...
Data subclass: StructuredName
Other stuff
- Shorthand for other platform components (app lifecycle,
invoking other apps)
- "Notifications" framework
- ... and unrestricted access to the full platform API, if
Positronic Net has no wrapper, or you just don't like it.
To find more...
https://github.com/rst/positronic_net
https://rst.github.com/positronic_docs.html