To bury Java early

    image

    Much has been said about the "beauty" of Java code, but in my opinion, the main thing is not a tool, but the ability to use it. Under cat, an attempt to write declarative DSL for layout for Android without even inventing a new programming language !

    Layout in Java has always been associated with pain.

    float dp = getResources().getDisplayMetrics().density;
    FrameLayout root = new FrameLayout(this);
    root.setBackgroundColor(RED);
    root.setLayoutParams(
            new ViewGroup.LayoutParams(
                    MATCH_PARENT,
                    (int)(100f*dp)));
    FrameLayout child = new FrameLayout(this);
    child.setBackgroundColor(GREEN);
    FrameLayout.LayoutParams childParams =
            new FrameLayout.LayoutParams(
                    (int)(50f*dp),
                    (int)(50f*dp));
    childParams.gravity = CENTER;
    child.setLayoutParams(childParams);
    root.addView(child);

    Result:



    And it's not even that the code looks scary (and it's scary as hell). The main problem is that it is impossible not to make a mistake. I reloaded this code 3 times here, for the first and second times naively believing that I could write everything correctly right away, and carefully rechecking everything only the third. You will say that the matter is my carelessness and you will be right, but even if you can make a mess of such a simple layout, what can we say about something more complicated?

    But why is everything so sad with Java layout? In my opinion, the main reason is the ability to typeset in xml and the lack of a Java layout tool.

    Cons xml


    For me there are 3.

    The first is an overhead.
    Why waste the resources of already not very powerful Android devices on operations such as inflate and findViewById? A lot of time and effort was spent on optimizing these operations, but they did not become free of this.

    The second is cumbersome.



    Depressing is the need to duplicate tags, write before each attribute “android:”, and then develop partial blindness to read this code.

    The third is the limitation of language.
    Suppose I want to make a signature for an avatar more than the avatar itself by 10dp.



    But this cannot be done because xml does not support expressions.

    Why not Anko?


    Anko is a DSL with which you can declaratively describe markup on Kotlin.

    frameLayout {
        backgroundColor = RED
        frameLayout {
            backgroundColor = GREEN
        }.lparams(dip(50), dip(50)) {
            gravity = CENTER
        }
    }.lparams(matchParent, dip(100))

    We get all the features of a full-fledged programming language, better performance and do not even suffer with the layout of the interface in Java!

    Everything is fine, but, in my opinion, it is indecent to drag along a whole runtime of a language when developing libraries. 500 kb - not so much for the final application, but for the library - obviously bust.

    Janko


    As it turned out, the Java capabilities are enough to typeset declaratively.

    new frameLayout(this) {{
        new lparams(this) {{
            width  = MATCH_PARENT;
            height = dip(100);
        }}._();
        backgroundColor = RED;
        new frameLayout(this) {{
            new lparams(this) {{
                width  = dip(50);
                height = dip(50);
                gravity = CENTER;
            }}._();
            backgroundColor = GREEN;
        }}._();
    }}._();

    The language supports untitled code blocks. They are executed before the constructor of the class immediately after the constructor of the parent class.

    class A {
        // block
        {
            // some code
        }
    }

    I used this very opportunity of Java not to write the name of the variable in which the widget lies to change each of its properties.

    Example with an avatar and signature.

    new imageView(this) {{
        new lparams(this) {{
            width = dimen(R.dimen.avatarSide);
            height = dimen(R.dimen.avatarSide);
        }}._();
    }}._();
    new textView(this) {{
        new lparams(this) {{
            width = dimen(R.dimen.avatarSide) + dip(10);
            height = WRAP_CONTENT;
        }}._();
    }}._();

    It looks a little strange.



    It looks like a man in a monocle and an operator on a scala. But for proof of concept - that's enough.

    Summary


    0). On Kotlin, the code looks like this:

    object : frameLayout(this) {
        init {
            object : lparams(this) {
                init {
                    width = MATCH_PARENT
                    height = dip(100f)
                }
            }.`_`()
            backgroundColor = RED
            object : frameLayout(this) {
                init {
                    object : lparams(this) {
                        init {
                            width = dip(50f)
                            height = dip(50f)
                            gravity = CENTER
                        }
                    }.`_`()
                    backgroundColor = GREEN
                }
            }.`_`()
        }
    }.`_`()

    1) The weight of aar is 12kb
    2) Idea does not interrupt formatting
    3) Java code can sometimes be given an unexpected appearance for Java

    Repository with a library and examples
    Benchmark

    Usually a little faster than Anko, which is funny.

    I expected that my mini-library would be the last refuge of this monster, but even from there I sawed it in favor of Litho , which performs measurment and layout in another thread. Thanks eirnym for the link.

    Only registered users can participate in the survey. Please come in.

    Bury back?

    • 64.7% Yes 261
    • 35.2% No 142

    Also popular now: