Wednesday, 23 December 2015

SuperSLiM Milestone 1

I’ve reached Milestone 1 for development on the new version of SuperSLiM. This is a complete rewrite of the library to fix long outstanding problems in the original design. You can see the roadmap for version 5 up on Trello. I expect Milestone 2 to be completed within the next couple of weeks.

Milestone 1

Milestone 1 was pretty much all about getting a good foundation for the library in place. The internal graph and SLM APIs are sorted out with support for a basic layout, predictive animations, and an adapter implementation. The new design is very flexible and makes extending the library very clean and easy.


The library is now written in Kotlin. Kotlin is presently heading for a 1.0 release itself. When that happens, I’ll be doing a code review of the library to identify and address any unnecessary garbage collection or other performance related problems.

What is implemented


There is an adapter available. It implements a graph which can store objects for view binding. Making changes to the graph notifies RecyclerView and SuperSlimLayoutManager of the changes, this kicks off the predictive animations.

There is no need to use the provided adapter, you just need to implement AdapterContract on your own adapter and keep SuperSlimLayoutManager notified of, well, a lot of things.


The actual LayoutManager class is still pretty bare, but the internal graph is very extensive. As RecyclerView works with a single dimension of items as does not bundle additional state with the item change notifications, the logical structure of the section graph is lost. This means the SuperSLiMLayoutManager has to track changes itself by requiring the adapter to notify it directly. These events are later matched up with those reported by RecyclerView. There is some difficulty in that RecyclerView modifies, splits up, and reorders events.

SuperSLiMLayoutManager can now be declared in your XML layout like the built-in LayoutManagers.


It also loads the common RecyclerView layout configurations declared in XML.


In the past, instantiating the layout manager was complicated by support for custom SLMs. However, in the new design SLMs are provided by a subclass of the SectionConfig class which means SuperSlimLayoutManager is now as easy to use as LinearLayoutManager.

Section Layout Managers (SLMs)

For the new SectionLayoutManager (SLM) API, I have hidden as much complexity as is possible to make writing new layouts simple.

Each SLM now works in a virtual space and talks to the layout through a helper. The helper, amongst other things, translates actions from the virtual space into real coordinates in the RecyclerView. A part of the coordinate transformation introduces effects from configuration options like stack from end and reverse layout. This allows SLMs to simply work with a logical vertical scrolling view, left-to-right, and top-to-bottom, but have the effect of rendering a RecyclerView interface that is any combination of stack from end, reverse layout, left-to-right, right-to-left, horizontal scrolling, or vertical scrolling.

As SuperSLiM implements a heterogeneous graph the layout helper also hides subsection and item differences behind the Child abstraction. This simplifies SLMs massively.

Predictive animations are also almost completely hidden by layout helper. The only complications is that a SLM must report space that was used by removed views. This is something only the SLM can know so I couldn’t hide that too. The result of this design is that disappearing views, appearing views, and the rest of that will just happen magically without the SLM having to do anything extra.

I still have work to do on scrolling the view. There will be significant changes from this, but I expect these to be mostly extensions of the existing design.

Project Page
Help support SuperSLiM on Patreon

Friday, 13 November 2015

Again: Supporting Android Typedefs in Kotlin

Before reading on, it is important to note that Android lint checks do not run on Kotlin code. However, it is possible to annotate Kotlin code such that lint can correctly check Java code against the annotated interfaces.

There is an issue tracking lint support for Kotlin here.

Typedef (Enumerated Annotations)

Previously, I wrote about how to get a library written in Kotlin to interoperate with IntDef and StringDef. The method I outlined got the lint check working in a partial state. However, here is what you have to do to get the annotation to work properly.

In Kotlin, declare the constants that are the values in the typedef.


package com.example.datepicker

class MyKotlinClass {
    companion object {
        const val YEAR = 1L
        const val MONTH = 2L
        const val WEEK = 3L
        const val DAY = 4L

The actual typedef is must be declared in Java.

package com.example.datepicker


@IntDef({MyKotlinClass.YEAR, MyKotlinClass.MONTH, MyKotlinClass.WEEK, MyKotlinClass.DAY})
public @interface DatePickedKind {}

You can now annotate your Kotlin and Java code freely with @DatePickedKind, and Lint will properly check Java code against the annotation.

Saturday, 7 November 2015

Easy SDK version handling with Anko

Anko is a library for Kotlin that implements a bunch of DSLs that significantly simplifies and cleans up your Android code. One of the small pieces it offers are some extension functions to selectively execute code based on the current configuration. It looks like this:
configuration(screenSize = ScreenSize.LARGE, orientation = Orientation.LANDSCAPE) {
    // This code will be only executed
    // if the screen is large and its orientation is landscape
Since it was available I thought it’d be nice to use it to tidy up my code that targets different versions of the Android SDK.
configuration(fromSdk = Build.VERSION_CODES.M) {
    // This code will be only executed
    // on sdk versions 23 and later
However, this has a problem because I want to target multiple version ranges of the SDK. Fortunately, it turns out the function returns null if the configuration check fails. With the power of Elvis ( ?: ) the null return can distinguish when the closure hasn’t been executed and build a cascading configuration selection.
configuration(fromSdk = Build.VERSION_CODES.M) {
    // This code will be only executed
    // on sdk versions 23 and later
} ?: configuration(fromSdk = Build.VERSION_CODES.LOLLIPOP) {
    // This code will be only executed
    // on sdk versions 21 and 22
} ?: {
    // This code will only be executed on 
    // sdk version 20 and earlier

Wednesday, 4 November 2015

Kotlin, IntDef, and Android libraries

Lately I’ve been investing time into Kotlin. Tonight, I was particularly interested in its utility for Android libraries.


Update: Actually, lint doesn’t quite interoperate properly with Kotlin. So, while the following gets IntDefs and the related support annotations working 90%, you have to do things a little different, which I’ve outlined here.

First up is how to use the support library’s IntDef annotation in Kotlin. This is especially important for library development since it is considered best practice to avoid enum usage for Android development. I don’t really want to go into the arguments about this practice, this is just how to use it. As it turns out, this is pretty easy. In Kotlin, using IntDef looks like this;

companion object {
    const val YEAR = 1L
    const val MONTH = 2L
    const val WEEK = 3L
    const val DAY = 4L

annotation class TimePeriod

and the same code in Java looks like this:

public static final long YEAR = 1l
public static final long MONTH = 2l
public static final long WEEK = 3l
public static final long DAY = 4l

public @interface TimePeriod {}


If I am to move to using Kotlin for my librares, one of the things I was most interested in was whether I could write the library to be indistinguishably different to a regular Android Java library. For now I think this is true, you just have to keep using listener objects;

var listener: SomethingHappenedListener? = null

interface SomethingHappenedListener {
    fun somethingHappened(foo: Bar)

and not be tempted to use lambdas:

var listener: ((foo: Bar) -> Unit)? = null

However, this issue is specific to only single method listeners.

Moving on

In the future, sometime, I am curious about the opportunity to use Kotlins DSL utility as a compliment to a libraries regular API, though this would be Kotlin specific. Hmm, this brings to mind that I actually haven’t yet checked to see what the DSLs look like in Java land. Well I am sure that IntelliJ will cook something up that compiles.

Friday, 28 August 2015

SuperSLiM 'should've been a weekly' update

In the past few weeks I should have written a couple of regular weekly updates, but I didn't, and I feel bad about that. Anyway, on to the good things.

SuperSLiM has been making good progress with a complete adapter interface, a near complete database backed example app, and a working but not fully tested linear layout.


In testing the new section graph adapter functions well with the stock recycler view layouts and is working with the SuperSLiM LinearSLM. This will resolve version 0.4 issues with dynamic data. At the moment the section graph has to maintain quite a bit of metadata to map items into the flat structure the recycler view expects. This means performing changes to the section graph can perform quite a bit of work at times. For some cases it may be worth using a slightly different implementation which sacrifices access performance from the recycler view side for increased performance when making changes to the graph. Also, I found it trivial to add collapsible sections to the adapter, so that is now done.

I'll be writing a follow-up post on actually using the adapter, and its minor differences from a regular recycler view adapter.


This example app is a simple demonstration of working with dynamic data and SuperSLiM. It is a simple display of countries in the world grouped into a hierarchy of sections analogous with regions and subregions. Sections can be collapsed, and all items edited, added, and deleted.

Monday, 27 July 2015

SuperSLiM weekly update

This week I have had less time for SuperSLiM than I imagined, but with the time I've had, I have continued work on the public API and the internal state for the library. Much of the work has been pen and paper documentation and modelling, but much of an example of how to write a data driven app with SuperSLiM has been written as a by-product.

For the public API I've settled on using a graph as a proxy to control the output of the library. In the previous post I discussed the section graph and its interaction with the traditional RecyclerView adapter. In the end I decided to go ahead with embedding the adapter into the section graph, which I believe makes working with RecyclerView and SuperSLiM quite simple. Now you simply add, remove, and update sections and items in the graph. There is no need to turn the graph structure into the sequence of views that RecyclerView requires, SuperSLiM does it all in the background.

The step after working on the changes to the public API was to revisit the design for the internal state of the library. In previous implementations a simple graph of the section structure was maintained by recording state from views encountered during layout passes. SuperSLiM now pulls the complete graph structure from the adapter, and doesn't have to interrogate views just to build the current graph section for every layout pass.

During the next week I am continuing work on the internal section graph. There are changes for the internal SLM API that need to be implemented, and I need to update the LinearSLM to reflect this.

If you want to help support SuperSLiM development, please consider visiting the patreon campaign page and become a patron by pledging a small donation. Thanks.

Tuesday, 21 July 2015

SuperSLiM section graph

In the last post I discussed I was working on the public API for SuperSLiM. This work really concerns the role of RecyclerView.Adapter in the API, that is, if SuperSLiM requires you to create and maintain a section graph, then do you also need to implement an adapter?

First, why is it important to explicitly create a section graph? In past versions, SuperSLiM generated a section graph from the adapter. This worked well enough at first, and it was nice that the API was basically the same as a normal layout manager. As it turned out, simply using the adapter and bundling all the side-channel data into layout parameters resulted in a lot of extra work being done to generate the section data. This was most noticeable when views that weren't even to be displayed would be bound multiple times. While caching fixed many of these problems, ultimately this played havoc with image caching and loading, and often resulted in unpredictable performance issues. To solve these problems I decided to make the section graph explicit.

So now there are two representations of your data, the section graph for SuperSLiM, and the adapter for RecyclerView. However, since the section graph is a known data model, we can simplify this and hide the adapter in the details. The result is something that looks something like this, where your application is talking to the section graph, and it manages everything for you, like the adapter used to.