Minimal UI library for Android inspired by React

Overview

Anvil - reactive views for Android

Join the chat at https://gitter.im/zserge/anvil Build Status Android Weekly


logo

Anvil is a small Java library for creating reactive user interfaces. Originally inspired by React, it suits well as a view layer for MVVM or Redux design patterns.


Features

  • Super small (4 hand-written classes + 1 generated class)
  • Easy to learn (top-level API is only 5 functions)
  • Fast (uses no reflection¹)
  • Efficient (views are updated lazily, if the data change didn't affect the view - it remains untouched)
  • Easy to read declarative syntax
  • Java 8 and Kotlin-friendly, but supports Java 6 as well
  • XML layouts are supported, too

¹Reflection is still used to inflate views once (standard XML inflater does the same thing, so no performance loss here).

Installation

// build.gradle
repositories {
    jcenter()
}
dependencies {
    compile 'co.trikita:anvil-sdk15:0.5.0'
}

Anvil comes in multiple builds for different minimal SDK versions:

  • anvil-sdk15 (ICS, 99.7% of devices)
  • anvil-sdk19 (Kitkat, 94.3% of devices)
  • anvil-sdk21 (Lollipop, 82.3% of devices)

API levels 16, 17, 18, 22 or 23 are not added because they had very few UI-related methods added.

Examples

Normally you would write your layouts in XMLs, then get your views by their IDs and set their listeners, finally you would observe your data and modify view properties as your data changes.

Anvil simplifies most of this boring routine.

First, add a static import that makes it much easier to write your view:

import static trikita.anvil.DSL.*;

Next, declare your layout, assign event listeners and bind data:

public int ticktock = 0;
public void onCreate(Bundle b) {
    super.onCreate(b);
    setContentView(new RenderableView(this) {
        @Override
        public void view() {
            linearLayout(() -> {
                size(MATCH, MATCH);
                padding(dip(8));
                orientation(LinearLayout.VERTICAL);

                textView(() -> {
                    size(MATCH, WRAP);
                    text("Tick-tock: " + ticktock);
                });

                button(() -> {
                    size(MATCH, WRAP);
                    text("Close");
                    // Finish current activity when the button is clicked
                    onClick(v -> finish());
                });
            });
        }
    });
}

Here we've created a very simple reactive view and added it to our Activity. We've declared our layout (a LinearLayout with a TextView inside). We've defined styles (width, height, orientation and padding). We've set OnClickListener to the button. We've also bound a variable "ticktock" to the text property inside a TextView.

Next, let's update your views as your data changes:

ticktock++;
Anvil.render();

At this point your layout will be updated and the TextView will contain text "Tick-Tock: 1" instead of "Tick-Tock: 0". However the only actual view method being called would be setText().

You should know that there is no need to call Anvil.render() inside your event listeners, it's already triggered after each UI listener call:

public void view() {
    linearLayout(() -> {
        textView(() -> {
            text("Clicks: " + numClicks);
        });
        button(() -> {
            text("Click me");
            onClick(v -> {
                numClicks++; // text view will be updated automatically
            });
        });
    });
}

Made with Anvil

Talalarmo Slide Spot Quilt

You may find more Anvil examples for Java 6, Java 8 and Kotlin at

How it works

No magic. When a renderable object is being constructed there are 3 types of operations: push view, modify some attribute of the current view, and pop view. If you're familiar with incremental DOM - Anvil follows the same approach.

Pushing a view adds it as a child to the parent view from the top of the stack. Attribute modification simply sets the given property to the current view on top of the stack. Pop unwinds the stack.

When you mount this layout (assuming the name is "John"):

linearLayout(() -> {
    textView(() -> {
        text("Hello " + name);
    });
});

It does the following sequence of actions:

Push LinearLayout (adding it to the root view)
Push TextView (adding it to the linear layout)
Attr text "Hello John" (calling setText of the TextView)
Pop
Pop

The only trick is that these actions are cached into a so called "virtual layout" - a tree-like structure matching the actual layout of views and their properties.

So when you call Anvil.render() next time it compares the sequence of actions with the cache and skips property values if they haven't change. Which means on the next Anvil.render() call the views will remain untouched. This caching technique makes render a very quick operation (having a layout of 100 views, 10 attributes each you can do about 4000 render cycles per second!).

Now, if you modify the name from "John" to "Jane" and call Anvil.render() it will do the following:

Push LinearLayout (noop)
Push TextView (noop)
Attr text "Hello Jane" (comparing with "Hello John" from the pervious render,
  noticing the difference and calling setText("Hello Jane") to the TextView)
Pop
Pop

So if you modify one of the variables "bound" to some of the attributes - the cache will be missed and attribute will be updated.

For all event listeners a "proxy" is generated, which delegates its method calls to your actual event listener, but calls Anvil.render() after each method. This is useful, because most of your data models are modified when the user interacts with the UI, so you write less code without calling Anvil.render() from every listener. Remember, no-op renders are very fast.

Supported languages and API levels

Anvil is written in Java 7, but its API is designed to use lambdas as well, so in modern times it's recommended to use Anvil with Java8/Retrolambda or Kotlin.

Syntax is a bit different for each language, but it's very intuitive anyway.

Java 6 without lambdas:

public void view() {
    o (linearLayout(),
      orientation(LinearLayout.VERTICAL),

        o (textView(),
          text("...")),
        
        o (button(),
          text("..."),
          onClick(myListener)));
}

Java 8 + RetroLambda:

public void view() {
    linearLayout(() -> {
        orientation(LinearLayout.VERTICAL);
        textView(() -> {
            text("....");
        });
        button(() -> {
            text(".....");
            onClick(v -> {
                ....
            });
        });
    });
}

Kotlin:

public override fun view() {
    linearLayout {
        orientation(LinearLayout.VERTICAL)
        textView {
            text("....")
        }
        button {
            text("....")
            onClick { v ->
                ...
            }
        }
    }
}

Anvil library contains only a few classes to work with the virtual layout, but most of the DSL (domain-specific language describing how to create views/layouts and set their attributes) is generated from android.jar.

API

Here's a list of classes and methods you need to know to work with Anvil like a pro:

  • Anvil.Renderable - functional interface that one should implement to describe layout structure, style and data bindings.

  • Anvil.mount(View, Anvil.Renderable) - mounts renderable layout into a View or a ViewGroup

  • Anvil.unmount(View) - unmounts renderable layout from the View removing all its child views if it's a ViewGroup

  • Anvil.render() - starts a new render cycle updating all mounted views

  • Anvil.currentView(): View - returns the view which is currently being rendered. Useful in some very rare cases and only inside the Renderable's method view() to get access to the real view and modifying it manually.

  • RenderableView - a most typical implementation of Anvil.Renderable. Extending this class and overriding its method view() allows to create self-contained reactive components that are mounted and unmounted automatically.

  • RenderableAdapter - extending this class and overriding its getCount(), getItem(int) and view(int) allows to create lists where each item is a standalone reactive renderable object.

  • RenderableAdapter.withItems(list, cb(index, item)) - a shortcut to create simple adapters for the given list of items. cb is a lambda that describes the layout and bindings of a certain list item at the given index.

DSL

The bottom part of the iceberg is Anvil DSL.

DSL consists of a few handwritten property setters, but most of it is generated from java classes in the android SDK.

See a full list of the DSL methods for each API level here.

Property setters

The setters are named as the view methods from Android SDK, but without the "set" prefix. E.g. "text(s)" instead of "setText(s)", "backgroundDrawable(d)" instead of "setBackgroundDrawable(d)" and so on.

Event listeners

Event listeners also have names from the Android SDK, but without the "set" prefix and the "Listener" suffix, e.g. "onClick" instead of "setOnClickListener".

Handwritten bindings

For LayoutParams the bindings can't be generated easily, so it was faster to write them manually:

  • size(width, height) - set width and height. Special constants like WRAP, FILL and MATCH are available.
  • dip(x) - returns the value in pixels for the dimension in density-independent pixels. Often used with size, padding or margin properties.
  • margin(m), margin(h, v), margin(l, t, r, b) - set view margin for all 4 sides, for horizontal/vertical dimensions or for each side individually.
  • weight(w) - modifies view layout weight.
  • layoutGravity(g) - modifies layout gravity of a view. Common constants like START, END, CENTER, CENTER_VERTICAL, etc. are available.
  • align(verb, anchor), align(verb) - base functions for relative layout params.
  • above(id), alignBaseline(id), alignBottom(id), alignEnd(id), alignLeft(id), alignParentBottom(), alignParentEnd(), alignParentLeft(), alignParentRight(), alignParentStart(), alignParentTop(), alignRight(id), alignTop(id), below(id), centerHorizontal(), centerVertical(), centerInParent(), toEndOf(id), toLeftOf(id), toRightOf(id), toStartOf(id) - all possible settings for relative layout params

A few bindings have been written for other use cases which we find useful:

  • init(Runnable) - executes a runnable once, useful to initialize custom views (see also Anvil.currentView()).
  • R() - returns a Resources object associated with the current view. Useful for multiple screen support (sizes, dpi, orientation etc).
  • isPortrait() - returns true if a screen is portrait-oriented. Useful for tweaking layouts for different orientations.
  • typeface(font) - loads font from assets by its file name and sets the typeface to a TextView
  • padding(p), padding(h, v), padding(l, t, r, b) - set view padding for all 4 sides, for horizontal/vertical dimensions or for each side individually.
  • visibility(flag) - sets the visibility property to View.VISIBLE or View.GONE depending on the flag boolean value
  • shadowLayer(radius, dx, dy, color) - sets shadow layer of a TextView
  • onTextChanged(textWatcher) - binds a text watcher to an EditText. No Anvil.render() is called in this case, because you're likely to get an infinite recursion.
  • text(StringBuilder) - binds a string builder to the edit text, so when you change its contents - the edit text is changed, and if you type something manually - the string builder gets modified. So far it's the only two-way data binding, becayse TextWatcher is a complicated beast.
  • onItemSelected(lambda) - accepts a functional interface to handle a Spinner events. onNothingSelected() method is omitted, because it's rarely used anyway.

If a binding you need is not in the list - please, check issue #27 and report it there.

A special case for animations is added:

  • anim(trigger, Animator) - starts animation when trigger is true, cancels it when the trigger becomes false.

Finally, a few low-level DSL functions are there, which you would no need unless you want to write your own property setters or custom view builders:

  • v(class, attrs...) - pushes view, applies attributes, doesn't pop the view.
  • o(), x() - names that look like bullets, actually pop the view. These are used in Java 6 syntax.
  • v(class, renderable) - pushes the view, applies the renderable to fulfil attributes and child views, pops the view. This is used in Java 8 and Kotlin syntax.
  • attr(func, value) - checks the cache for the given value of the given property setter function. Often used to create your own property setter binding.

XML layouts

If you're migrating an existing project to Anvil or if you prefer to keep your view layouts declared in XML - you can do so:

public override fun view() {
    // A designer gave us an XML with some fancy layout:
    // a viewgroup with a button and a progress bar in it
    xml(R.layout.my_layout) {
        backgroundColor(Settings.bgColor) // will modify root layout view color

        withId(R.id.my_button) {
            // button state may depend on some variable
            enabled(isMyButtonEnabled)
                // button click listener can be attached
                onClick { v ->
                    ...
                }
        }

        withId(R.id.my_progress_bar) {
            visible(isMyProgressBarShown)
            progress(someProgressValue)
        }
    }
}

Here xml() creates a view node, much like frameLayout() or textView(), except for it uses an XML file to inflate the views, not the direct view class constructor. Much like view "builders", xml() takes a renderable lambda as a parameter and uses that to modify the created view.

Any attribute setters will affect the root view from the XML layout.

If you want to modify attributes of the child views from the XML - you should use withId() to assign a renderable to a view with the given ID. You may not follow the hierarchy of the child views, e.g. all your withId() calls may be nested as the views are nested in the XML, or may be direct children of the xml() renderable. xml() calls can be nested, too.

xml() also allows you to create views that can not be inflated from Java code but only from XML (such as hostozintal progress bars) or any other views where AttributeSet must be given or the views that rely on the onFinishInflate method to be called.

withId() call is not limited to XML views, it can be used for views declared in code that have IDs. So if you have a custom viewgroup that creates its child views automatically and assigns some IDs to them - you can still modify their properties using withId(). Also, if any views are created inside the withId() or xml() - they will be appeneded to the view group:

v(MyComponent.java, () -> {
    withId(R.id.child_view, () -> {
        // R.id.child_view was implicitely created in MyComponent's constructor
        // but we still can modify it here
    });

    textView(() -> {
        // This textView will be appeneded to MyComponent layout
    });
});

License

Code is distributed under MIT license, feel free to use it in your proprietary projects as well.

Comments
  • config() called many times on startup

    config() called many times on startup

    I need to add a photo-taking activity to my application, and I'm using Anvil for the view. I've just updated to 0.0.9.

    I'm trying out the new config() functionality (I use my homemade ref system in my existing activities) and am running into an issue.

    Basically, config() function is being called on every user interaction, and even multiple times without any interaction at startup (it seems to be called 4 times at activity startup without any callbacks or calls to Anvil.render()). The issue is that in my config() function I wire up a SurfaceView to a camera instance. When a picture is taken, the config() block is called again (even though the SurfaceView has never disappeared from the screen, or changed in any way, nor any of its parents) and tries to set up the SurfaceView again, which fails because the camera is no longer in the right mode.

    I think I can work around this by adding a boolean flag to indicate that the camera has been initialized and then only calling the code in config if it hasn't been called before, but my understanding is that config should do this itself, and only be called when there has been an actual change to an element or its parents. Is my understanding correct?

    opened by corbt 19
  • Manually getting a view

    Manually getting a view

    Ok, so I need to manually get a view from a layout managed by Anvil. I have a TextureView that I need to hook up to the camera. The view I need is always visible in the activity, so Anvil should always render it. Currently what I'm trying is based on a technique described here:

    v<AutoFitTextureView> {
        -size(FILL, 400)
        -id(R.id.camera_preview)
    }
    

    And then later on, still within onCreate:

    mTextureView = findViewById(R.id.camera_preview) as AutoFitTextureView
    

    but Android isn't able to find the view (findViewById returns null). Is there a better way to capture a reference to a view object than what I'm doing here? I think the ideal would be to implement something similar to React's refs, but I'd be happy with a workaround.

    opened by corbt 15
  • is it abandoned due to reactnative?

    is it abandoned due to reactnative?

    react native has been announced over a month. I don't think it'll be ready any time soon. besides, a pure java implementation will still have its space due to performance concerns over js-java bridge.

    question 
    opened by wangii 13
  • Setting styles

    Setting styles

    Really happy with how Anvil is working, and I'm writing new functionality for my app using it.

    I'm having trouble assigning styles to elements created by anvil. For example, I want to add a shadow to the text on a button. Using standard layouts I can do something like the following:

    <style name="ButtonText">
            <item name="android:shadowColor">#000000</item>
            <item name="android:shadowDx">1</item>
            <item name="android:shadowDy">1</item>
            <item name="android:shadowRadius">2</item>
        </style>
    

    and then set the style from XML. However, it doesn't look like there is a way to set the style on an element programmatically, and thus no way to do it from anvil. Am I missing something?

    opened by corbt 11
  • Support library difficulties and ugliness

    Support library difficulties and ugliness

    Hi, I love this library so far, it's so refreshing! But, there is one thing holding me back and making me wanna go back to XML, which is that the appcompat-v7 and support-v4 DSLs have conflicting methods with the core DSL. Also, it kills me that we have to write appCompatButton instead of just button and have it automatically use the appropriate version.

    I would gladly work with someone on the issue (I'm not too good at making APIs on my own, hehe).

    Thanks in advance, Graknol

    opened by graknol 10
  • illegalArgumentException: The key must be an application-specific resource id

    illegalArgumentException: The key must be an application-specific resource id

    After introducing a few more view to my app using anvil, it starts throwing these when I switch views calling setContentView:

    09-12 21:15:13.137  19964-19964/net.kjeldahl.secdrones E/AndroidRuntime﹕ FATAL EXCEPTION: main
        Process: net.kjeldahl.secdrones, PID: 19964
        java.lang.IllegalArgumentException: The key must be an application-specific resource id.
                at android.view.View.setTag(View.java:18542)
                at trikita.anvil.BaseAttrs$9.apply(BaseAttrs.java:308)
                at trikita.anvil.Anvil.inflateNode(Anvil.java:249)
                at trikita.anvil.Anvil.inflateNode(Anvil.java:233)
                at trikita.anvil.Anvil.inflateNode(Anvil.java:233)
                at trikita.anvil.Anvil.inflateNode(Anvil.java:233)
                at trikita.anvil.Anvil.render(Anvil.java:106)
                at trikita.anvil.RenderableView.onMeasure(RenderableView.java:84)
                at android.view.View.measure(View.java:18788)
    

    Any ideas why, and/or what I need to do to fix it?

    opened by mariusk 10
  • Overload resolution ambiguity with adapter(RenderableArrayAdapter)

    Overload resolution ambiguity with adapter(RenderableArrayAdapter)

    I have the following test activity in kotlin that is causing an error that appears to be related to the implementation of RenderableArrayAdapter:

    import android.app.Activity
    import android.os.Bundle
    
    import android.content.Context;
    import android.util.Log
    import android.widget.Button;
    import android.widget.LinearLayout;
    import android.widget.ListView
    import android.widget.TextView;
    import trikita.anvil.RenderableView;
    
    import trikita.anvil.RenderableView;
    import trikita.anvil.BaseAttrs.*;
    import trikita.anvil.Nodes
    import trikita.anvil.RenderableArrayAdapter
    import trikita.anvil.v10.Attrs.*;
    
    class UsersList: Activity() {
        override fun onCreate(b: Bundle?) {
            super<Activity>.onCreate(b)
    
            var testNames: Array<String> = array("Bob Jones", "John Black", "Other Name")
    
            setContentView(object: RenderableView(this) {
                public override fun view() =
                        v<LinearLayout> {
                            - size(FILL, FILL)
                            - orientation(LinearLayout.VERTICAL)
    
                            v<TextView> {
                                - text("Names")
                            }
    
                            v<ListView> {
                                adapter(object : RenderableArrayAdapter<String>(testNames) {
                                    override fun itemView(p0: Int, p1: String?): Nodes.ViewNode? {
                                        throw UnsupportedOperationException()
                                    }
                                })
                            }
                        }
            });
        }
    }
    

    The compiler throws the following error for the adapter() function call:

    Error:(37, 29) Overload resolution ambiguity:
    public open fun adapter(arg: android.widget.ListAdapter!): trikita.anvil.Nodes.AttrNode! defined in trikita.anvil.v10.Attrs
    public open fun adapter(arg: android.widget.Adapter!): trikita.anvil.Nodes.AttrNode! defined in trikita.anvil.v10.Attrs
    public open fun adapter(arg: android.widget.SpinnerAdapter!): trikita.anvil.Nodes.AttrNode! defined in trikita.anvil.v10.Attrs
    

    It looks like this is because RenderableArrayAdapter implements ListAdapter and SpinnerAdapter (and I guess Adapter as well). But since there are different implementation bodies the method doesn't resolve. Is there something I'm doing wrong here, or should adapter be combined into a single method call that dispatches internally based on its argument type?

    opened by corbt 9
  • Anvil.currentView() is null inside render method

    Anvil.currentView() is null inside render method

    Any ideas why the following exception is being thrown by withId()?

    Caused by: java.lang.RuntimeException: Anvil.currentView() is null
    at trikita.anvil.BaseDSL.withId(BaseDSL.java:688)
    

    The issue occurs in the render cycle immediately after the view in question is removed from its parent, like this:

    Pass 1:

    linearLayout(() -> {
        v(SomeView.class, () -> {});
        v(SomeView.class, () -> {});
        v(SomeView.class, () -> {});
    }) 
    

    Pass 2:

    linearLayout(() -> {
        v(SomeView.class, () -> {});
        // Removed
        v(SomeView.class, () -> {});
    }) 
    

    SomeView's render method where the crash is thrown is essentially this:

    @Override
    public void view() {
        xml(R.layout.some_view, () -> {
            // Crash here
            withId(R.id.button, () -> {
            }
        }
    
    opened by danhawkes 8
  • Broken TextInputLayout with support library 24.2.0

    Broken TextInputLayout with support library 24.2.0

    Android support library 24.2.0 introduced these changes to TextInputLayout:

         public TextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) {
              ...
    +        mInputFrame = new FrameLayout(context);
    +        mInputFrame.setAddStatesFromChildren(true);
    +        addView(mInputFrame);
              ...
         }
         ...
         public void addView(View child, int index, final ViewGroup.LayoutParams params) {
             if (child instanceof EditText) {
    +            mInputFrame.addView(child, new FrameLayout.LayoutParams(params));
    +
    +            // Now use the EditText's LayoutParams as our own and update them to make enough space
    +            // for the label
    +            mInputFrame.setLayoutParams(params);
    +            updateInputLayoutMargins();
    +
                 setEditText((EditText) child);
    -            super.addView(child, 0, updateEditTextMargin(params));
             } else {
             ...
    

    Anvil's rendering breaks TextInputLayout as it always tries to replace FrameLayout inside with EditText. I really like Anvil's reactive views approach, however, I'd like to also use latest stable support library. Any suggestions how to overcome this? Thank you.

    opened by jakubkulhan 8
  • onTextChanged implementation

    onTextChanged implementation

    Previously EditText::onTextChanged (in Kotlin) accepted a lambda that was called with the updated text. So I could do something like:

    -onTextChanged { txt -> setVal(txt); Anvil.render() }
    

    Now, onTextChanged requires a full TextWatcher implementation. Of greater concern, it appears to be adding the watcher to the EditText over and over again, with every render. So after a few updates to the field the UI begins lagging noticeably.

    The old onTextChanged syntax was sufficient for my needs and more concise. I'm planning on creating my own onTextChanged using the old syntax. Is this something that you would be interested in getting a PR for or not?

    opened by corbt 8
  • Rerendering list item in RenderableArrayAdapter

    Rerendering list item in RenderableArrayAdapter

    It seems that individual item views in a RenderableArrayAdapter are only rerendered when they scroll off/on the screen.

    Basically, I have a list of questions that can be selected by the user. Questions that have been answered already are in one color, the current selected question is in another, and questions to be answered are in a third.

    Right now, when a question is selected no change occurs in its view within the RenderableArrayAdapter. It only changes to the selected color when I've scrolled it off/on the screen. I'd like to either be able to force a re-render when the question is clicked, or (even better) have Anvil re-render all the visible cells as part of the Anvil.render() cycle. Is there any reason why this isn't the case?

    opened by corbt 8
  • Would be possible to run the diff tree algorithm in a non UI thread?

    Would be possible to run the diff tree algorithm in a non UI thread?

    We are using Anvil in our project for 2 years now. And in some screens, with a high number of views, we are facing some performance issues. These delays and lags happens even when no changes are made to the views, but a render cycle is fired because a button was clicked for example.

    Based on this, I would like to know if would be possible to perform the Anvil diff tree algorithm in a non UI thread, thus the screen will not be affected by these comparisons. The idea is only to use the UI thread once we detected that we need to update a View, add a view or remove a view.

    opened by niltonvasques 3
  • Migrate to Androidx

    Migrate to Androidx

    This PR dependent on https://github.com/zserge/anvil/pull/133 and should be merged after only it.

    This PR transitions support libs to androidx, also renames anvil-design module to anvil-material. Also solves #128

    opened by sgrekov 0
  • Add ability to pass nullable properties

    Add ability to pass nullable properties

    This PR adds ability to pass nullable values into properties where they are marked by @Nullable annotation. Also, it marks property calls with @NonNull and @Nullable annotations to be more Kotlin friendly. Since this annotations have compile time visibility, generate task now inspects byte code to find these annotations. As for platform sdk annotations, those annotations are started to appear only on latest binaries(API 28), and they are marked as @RecentlyNullable and @RecentlyNonNull

    opened by sgrekov 0
Owner
null
Nucleus is an Android library, which utilizes the Model-View-Presenter pattern to properly connect background tasks with visual parts of an application.

Nucleus Deprecation notice Nucleus is not under develpment anymore. It turns out that Redux architecture scales way better than MVP/MVI/MVVM/MVxxx and

Konstantin Mikheev 2k Nov 18, 2022
Moxy is MVP library for Android

Moxy This Moxy repository is deprecated and no longer supported. Please migrate to the actual version of the Moxy framework at Moxy communuty repo. De

Arello Mobile 1.6k Dec 28, 2022
a MVP library for Android favoring a stateful Presenter

DEPRECATED - no longer actively maintained ThirtyInch - a MVP library for Android This library adds Presenters to Activities and Fragments. It favors

HCI @ gcx 1k Dec 15, 2022
A Mosby based VIPER library for Android

Moviper A Mosby based VIPER library for Android Why Moviper? You got tired because of fact that your Activities and Fragments were becoming god classe

Mateusz Koślacz 78 Nov 29, 2022
Android app built with MVP architectural approach and uses Marvel Comics API that allows developers everywhere to access information about Marvel's vast library of comics. :zap:

Villains & Heroes Android app built with MVP architectural approach and uses Marvel Comics API that allows developers everywhere to access information

André Mion 53 Jul 13, 2022
Crossword library for Android

Ararat Ararat is a crossword library for Android, written for and used by alphacross. It includes: Parsers for various formats CrosswordRenderer, whic

Akop Karapetyan 28 Oct 3, 2022
The most complete and powerful data-binding library and persistence infra for Kotlin 1.3, Android & Splitties Views DSL, JavaFX & TornadoFX, JSON, JDBC & SQLite, SharedPreferences.

Lychee (ex. reactive-properties) Lychee is a library to rule all the data. ToC Approach to declaring data Properties Other data-binding libraries Prop

Mike 112 Dec 9, 2022
A lightweight, good expandability Android library used for displaying different pages like loading, error, empty, timeout or even your custom page when you load a page

中文 | English LoadSir ?? ?? LoadSir是一个高效易用,低碳环保,扩展性良好的加载反馈页管理框架,在加载网络或其他数据时候,根据需求切换状态页面, 可添加自定义状态页面,如加载中,加载失败,无数据,网络超时,如占位图,登录失效等常用页面。可配合网络加载框架,结合返回 状态

KingJA 3.3k Dec 21, 2022
Android part of the Android Studio(IntellijIDEA) OkHttp Profiler plugin

OkHttpProfiler Android Library Created by LocaleBro.com - Android Localization Platform The OkHttp Profiler plugin can show requests from the OkHttp l

Ievgenii 261 Dec 8, 2022
Android common lib, include ImageCache, HttpCache, DropDownListView, DownloadManager, Utils and so on

android-common-lib 关于我,欢迎关注 微博:Trinea 主页:trinea.cn 邮箱:trinea.cn#gmail.com 微信:codek2 主要包括:缓存(图片缓存、预取缓存、网络缓存)、公共View(下拉及底部加载更多ListView、底部加载更多ScrollView、

Trinea 5k Dec 30, 2022
dexposed enable 'god' mode for single android application.

What is it? Dexposed is a powerful yet non-invasive runtime AOP (Aspect-oriented Programming) framework for Android app development, based on the work

Alibaba 4.5k Dec 28, 2022
A small, yet full-featured framework that allows building View-based Android applications

Conductor A small, yet full-featured framework that allows building View-based Android applications. Conductor provides a light-weight wrapper around

BlueLine Labs 3.9k Jan 6, 2023
A Job Queue specifically written for Android to easily schedule jobs (tasks) that run in the background, improving UX and application stability.

This Project is Deprecated! Thanks to everybody who've used Android Priority JobQueue. It was designed in a world where there was no JobScheduler, RxJ

Yigit Boyar 3.4k Dec 31, 2022
A plugin system that runs like a browser, but instead of load web pages, it load apk plugins which runs natively on Android system.

Android Dynamic Loader Android Dynamic Loader is a plugin system. The host application is like a browser, but instead of load web pages, it load plugi

Tu Yimin 1.4k Dec 28, 2022
LiteOrm is a fast, small, powerful ORM framework for Android. LiteOrm makes you do CRUD operarions on SQLite database with a sigle line of code efficiently.

#LiteOrm:Android高性能数据库框架 A fast, small, powerful ORM framework for Android. LiteOrm makes you do CRUD operarions on SQLite database with a sigle line

马天宇 1.5k Nov 19, 2022
🚀Plugin for Android Studio And IntelliJ Idea to generate Kotlin data class code from JSON text ( Json to Kotlin )

JsonToKotlinClass Hi, Welcome! This is a plugin to generate Kotlin data class from JSON string, in another word, a plugin that converts JSON string to

Seal 2.8k Jan 3, 2023
Kick-starts Android application development.

Synopsis If you've made it here, chances are you are not quite as satisfied with the Android application framework as you could be. Same for us, that'

Matthias Käppler 1.3k Dec 4, 2022
Rosie is an Android framework to create applications following the principles of Clean Architecture.

Rosie The only way to make the deadline—the only way to go fast—is to keep the code as clean as possible at all times. — Robert C. Martin in Clean Cod

Karumi 1.8k Dec 28, 2022
Create kotlin android project with one line of command.

README This is an android application template project built with kotlin language and some useful libraries. It provides a creator script to quickly c

nekocode 1.6k Dec 20, 2022