{"id":25319699,"url":"https://github.com/aghajari/xmlbypass","last_synced_at":"2025-10-28T22:31:17.725Z","repository":{"id":57732272,"uuid":"487723670","full_name":"Aghajari/XmlByPass","owner":"Aghajari","description":"Get the Highest Android UI performance! XmlByPass is an annotationProcessor library for Android which auto generates the java code of your xml layouts in Source level (before compile)","archived":false,"fork":false,"pushed_at":"2022-08-18T15:44:10.000Z","size":19968,"stargazers_count":10,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2023-07-28T10:08:21.666Z","etag":null,"topics":["android-layout","layout","programmatically","xml"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Aghajari.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-05-02T05:12:17.000Z","updated_at":"2022-09-18T12:43:49.000Z","dependencies_parsed_at":"2022-09-10T19:51:46.056Z","dependency_job_id":null,"html_url":"https://github.com/Aghajari/XmlByPass","commit_stats":null,"previous_names":[],"tags_count":0,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Aghajari%2FXmlByPass","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Aghajari%2FXmlByPass/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Aghajari%2FXmlByPass/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Aghajari%2FXmlByPass/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Aghajari","download_url":"https://codeload.github.com/Aghajari/XmlByPass/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238734068,"owners_count":19521557,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android-layout","layout","programmatically","xml"],"created_at":"2025-02-13T20:54:40.628Z","updated_at":"2025-10-28T22:31:10.898Z","avatar_url":"https://github.com/Aghajari.png","language":"Java","readme":"# XmlByPass\n ![XmlByPass](./images/header.png)\n \n[![Platform](https://img.shields.io/badge/platform-android-green.svg)](http://developer.android.com/index.html)\n[![Maven Central](https://img.shields.io/maven-central/v/io.github.aghajari/XmlByPass.svg?label=Maven%20Central)](https://search.maven.org/artifact/io.github.aghajari/XmlByPass/1.0.1/aar)\n[![Join the chat at https://gitter.im/Aghajari/community](https://badges.gitter.im/Aghajari/community.svg)](https://gitter.im/Aghajari/community?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge\u0026utm_content=badge)\n\nGet the Highest Android UI performance!\n\nWith  **XmlByPass** you won't need to learn any new thing! just use  **XmlByPass** to get the highest performance from your Xml layouts.\n\nWhen i started developing android applications, i just saw that we develop almost all of the UI with Xml and that made me so unsatisfied cuase it was really really boring. So, i started creating views programmatically then i found it so enjoyable and got a better perfomance for sure. But coding programmatically to create a layout is very time consuming even for simple layouts.\n\nand also as [Karakuri](https://stackoverflow.com/a/35569482) said: \n\u003e Remembering which LayoutParams to use where is great mental gymnastics\n\nBut i will tell you how to do this later (If you wanted ofc)\n\nAs you may know there are so many challenges to create a layout programmatically, \nfor example you need to know about qualifiers (Screen orientation, Screen size, Layout Direction, Night mode and etc.)\n\nAndroid has already handled all of this with resources! [Read more](https://developer.android.com/guide/topics/resources/providing-resources)\n\u003e Almost every app should provide alternative resources to support specific device configurations. For instance, you should include alternative drawable resources for different screen densities and alternative string resources for different languages. At runtime, Android detects the current device configuration and loads the appropriate resources for your app.\n\u003e \n\u003e \u003cimg src=\"https://user-images.githubusercontent.com/30867537/166199347-b4e3ec18-a33a-41fa-ac30-b750290c4dd2.png\" width=300 title=\"Image\"\u003e\n\nWhy should we use XML layouts?\n- As i mentioned, coding programmatically to create a layout is very time consuming meanwhile one of the goals of xml was to prepare quickly.\n- You can easily create a layout, even with a simple drag \u0026 drop (thanks to the Android Studio Designer tools)\n- Almost all of the resources/tutorials of Android on documents/articles/source-codes are presented by **XML**\n- Easy to create layouts for different configurations. (Qualifiers)\n\nHow `LayoutInflater` inflates a Layout?\n\nAndroid pre-compiles every layout but still needs to hold the original xml file, why? cause needs to generate a suitable LayoutParams for container.\nSo, in step of inflation we are always parsing the XML by using [`XmlPullParser`](http://www.xmlpull.org/), but ofc android has written it's own customized parser with native codes (C) which makes it a little faster. Anyway, We never can ignore the fact that creating instance of views are done by reflection (`LayoutInflater#createView(Context, String, String, AttributeSet)`). And without `ViewBinding`, everytime we want to find a `View` we call `View#findViewById(int)` which needs to iterate all childs (including childs of it's child :D)\n\nAs [Andrii Drobiazko](https://medium.com/@c2q9450/performance-comparison-building-android-ui-with-code-anko-vs-xml-layout-cc0abb21c561) wrotes: \n\n\u003e By default, UI in Android is built using XML layout files. it leads to overhead in cpu and ram usage. It can be insensibly for fast and powerful devices, but low-end devices may suffer from resources deficit\n\u003e \n\u003e **Benchmark:**\n\u003e \n\u003e \u003cimg src=\"https://user-images.githubusercontent.com/30867537/166209006-636b3995-51b7-4741-aa4a-62a22ebd5921.png\" width=500 title=\"Image\"\u003e\n\n---\n\u003cp align=\"center\"\u003e\u003cb\u003eAnd there we go! Your savior, XmlByPass :)\u003c/b\u003e\u003c/p\u003e\n\n---\n\n ## Table of Contents  \n- [Introduction](#introduction)\n- [Installation](#installation)\n- [Usage](#usage)\n- [Qualifiers](#qualifiers)\n- [ViewModel](#viewmodel)\n- [Custom Attribute](#custom-attribute)\n- [Performance](#performance)\n- [Author](#author)\n- [License](#license)\n \n ## Introduction\n \n**XmlByPass** is an annotationProcessor library for Android which auto generates the java code of your xml layouts in `Source` level (before compile). That means, you can create your layouts easily and quickly with XML and get all benefits of using xml/resources meanwhile get the performance of creating views programmatically without even knowing about it! (Not joking, you don't need to learn anything new :))\n \n**XmlByPass** supports almost 99% of tags and attributes of XML layouts including `\u003cinclude/\u003e` and `\u003cfragment/\u003e`, And for other 1%, it will auto generate style resources and applies them to the views. Therefore, you can be sure it will 100% work.\n\nNo need to worry about ViewBinding, **XmlByPass** adds views that have an `android:id` with their ID name as Public variables and other views are protected so still you can customize them by inheritance. (You will see sample codes in Usage)\n\n**XmlByPass** supports all [qualifiers](https://developer.android.com/guide/topics/resources/providing-resources). Yay!\n\nAnd one more interesting option, **XmlByPass** brings auto generating [`ViewModel`](https://developer.android.com/topic/libraries/architecture/viewmodel) with [`LiveData`](https://developer.android.com/topic/libraries/architecture/livedata) :)\n\n\n ![XmlByPass](./images/usage.gif)\n\n## Installation\n\nXmlByPass is available in the `mavenCentral()`, so you just need to add it as a dependency (Module gradle)\n\nJava: \n```gradle\nannotationProcessor 'io.github.aghajari:XmlByPass:1.0.2'\nimplementation 'io.github.aghajari:XmlByPassAnnotations:1.0.2'\n```\n\nKotlin: \n```gradle\napply plugin: 'kotlin-kapt'\n\nkapt 'io.github.aghajari:XmlByPass:1.0.2'\nimplementation 'io.github.aghajari:XmlByPassAnnotations:1.0.2'\n```\n\n## Usage\n\nLet's start with Android Studio Hello World project!\n\nThis is `activity_main` (xml layout): \n\n```xml\n\u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\n\u003candroidx.constraintlayout.widget.ConstraintLayout \n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\u003e\n    \n    \u003cTextView\n        android:id=\"@+id/tv\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"Hello World!\"\n        app:layout_constraintBottom_toBottomOf=\"parent\"\n        app:layout_constraintLeft_toLeftOf=\"parent\"\n        app:layout_constraintRight_toRightOf=\"parent\"\n        app:layout_constraintTop_toTopOf=\"parent\" /\u003e\n    \n\u003c/androidx.constraintlayout.widget.ConstraintLayout\u003e\n```\n\nThis is the MainActivity:\n\n\u003cdetails open\u003e\u003csummary\u003e\u003cb\u003eJava\u003c/b\u003e\u003c/summary\u003e\n\u003cp\u003e\n\t\n```java\npublic class MainActivity extends AppCompatActivity {\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_main);\n    }\n}\n```\n\u003c/p\u003e\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e\u003cb\u003eKotlin\u003c/b\u003e\u003c/summary\u003e\n\u003cp\u003e\n\t\n```kotlin\nclass MainActivity : AppCompatActivity() {\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.activity_main)\n    }\n}\n```\n\u003c/p\u003e\u003c/details\u003e\n\n\u003cbr\u003e\n\nAlright, Let's include **XmlByPass**, You won't need to change your xml layout at all! but this is gonna be how your MainActivity looks like: \n\n\u003cdetails open\u003e\u003csummary\u003e\u003cb\u003eJava\u003c/b\u003e\u003c/summary\u003e\n\u003cp\u003e\n\t\n```java\nimport com.aghajari.xmlbypass.XmlByPass;\nimport com.aghajari.xmlbypass.XmlLayout;\n\t\n@XmlByPass(layouts = {\n        @XmlLayout(layout = \"activity_main\", className = \"ActivityMain\")\n})\npublic class MainActivity extends AppCompatActivity {\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(new ActivityMain(this));\n    }\n}\n```\n\u003c/p\u003e\u003c/details\u003e\n\u003cdetails\u003e\u003csummary\u003e\u003cb\u003eKotlin\u003c/b\u003e\u003c/summary\u003e\n\u003cp\u003e\n\t\n```kotlin\nimport com.aghajari.xmlbypass.XmlByPass\nimport com.aghajari.xmlbypass.XmlLayout\n\n@XmlByPass(layouts = [\n    XmlLayout(layout = \"activity_main\", className = \"ActivityMain\")\n])\nclass MainActivity : AppCompatActivity() {\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(ActivityMain(this))\n    }\n}\n```\n\u003c/p\u003e\u003c/details\u003e\n\n\u003cbr\u003e\n\n**XmlByPass** will generate `ActivityMain` automatically, This is how the generated class looks like:\n\n\u003cdetails\u003e\u003csummary\u003e\u003cb\u003eActivityMain.java\u003c/b\u003e\u003c/summary\u003e\n\u003cp\u003e\n \n```java\nimport android.content.Context;\nimport android.util.AttributeSet;\nimport android.widget.TextView;\n\nimport androidx.constraintlayout.widget.ConstraintLayout;\n\npublic class ActivityMain extends ConstraintLayout {\n\n    public TextView tv;\n\n    public ActivityMain(Context context) {\n        this(context, null);\n    }\n\n    public ActivityMain(Context context, AttributeSet attrs) {\n        this(context, attrs, 0);\n    }\n\n    public ActivityMain(Context context, AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n\n        init();\n    }\n\n    protected void init() {\n        initThis();\n        initTv();\n    }\n\n    protected void initThis() {\n        this.setLayoutParams(new ConstraintLayout.LayoutParams(-1, -1));\n    }\n\n    protected void initTv() {\n        tv = new TextView(getContext());\n        tv.setId(R.id.tv);\n        tv.setText(\"Hello World!\");\n        ConstraintLayout.LayoutParams tv_lp = new ConstraintLayout.LayoutParams(-2, -2);\n        tv_lp.bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID;\n        tv_lp.endToEnd = ConstraintLayout.LayoutParams.PARENT_ID;\n        tv_lp.startToStart = ConstraintLayout.LayoutParams.PARENT_ID;\n        tv_lp.topToTop = ConstraintLayout.LayoutParams.PARENT_ID;\n        this.addView(tv, tv_lp);\n    }\n\n}\n```\n\u003c/p\u003e\u003c/details\u003e\n\n---\n\u003cp align=\"center\"\u003e\u003cb\u003eThat's it!\u003c/b\u003e\u003c/p\u003e\n\n---\n\nBy `@XmlLayout(layout = \"*\")` you can mark all layouts, So **XmlByPass** will generate a java class for each existing layout and the name of the class will be the name of it's layout file.\n\n```java\n@XmlByPass(layouts = {@XmlLayout(layout = \"*\")})\npublic class MainActivity extends AppCompatActivity {\n```\n\nBy `packageName` you can set pacakgeName of generated java classes, \nDo not forget to set main package name of your app for R.class\n\n```java\n@XmlByPass(layouts = {...}, packageName = \"com.example.layouts\", R = \"com.example\")\n```\n\nBy `include` you can specify whether **XmlByPass** should generate java class for included layouts or not ([`\u003cinclude/\u003e`](https://developer.android.com/training/improving-layouts/reusing-layouts), it is `true` by default)\n\n```java\n@XmlByPass(layouts = {...}, include = true)\n```\n\nBy `styleable` you can specify whether **XmlByPass** should generate style resource for unknown attributes or not (it is `false` by default)\n\n*Note:* If you enabled the styleable, you may need compile your code twice for the first time, android will load resources first, so you need a second try to import the generated style file.\n```java\n@XmlByPass(layouts = {...}, styleable = true)\n```\n\nBy `viewModel` you can specify whether **XmlByPass** should generate a [`ViewModel`](https://developer.android.com/topic/libraries/architecture/viewmodel) class (Using [`LiveData`](https://developer.android.com/topic/libraries/architecture/livedata)) or not.\n\nThis helps you to implement [MVVM](https://www.geeksforgeeks.org/mvvm-model-view-viewmodel-architecture-pattern-in-android/) architecture easier than before, by only a single xml layout file.\n```java\n@XmlByPass(layouts = {\n        @XmlLayout(layout = \"activity_main\", className = \"ActivityMain\", viewModel = \"ActivityMainViewModel\"),\n}, viewModel = true)\n```\n\n## Qualifiers\n\n\u003cimg src=\"./images/qualifiers.gif\" width=300 title=\"GIF\"\u003e\n\nThis is just a simple test for [qualifiers](https://developer.android.com/guide/topics/resources/providing-resources), Two layouts are made. One for the landscape mode in `layout-land` folder, and another one for other configs in `layout` folder with same name.\n\nThis is the generated java code condition: \n```java\nif (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE)\n   init_land();\nelse\n   init();\n```\n\nAnd this is the way you can customize it in code with a simple inheritance :\n\n```java\n@XmlByPass(layouts = {\n        @XmlLayout(layout = \"activity_main\", className = \"ActivityMain\")\n})\npublic class MainActivity extends AppCompatActivity {\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(new ActivityMain(this) {\n            @Override\n            protected void init_land() {\n                super.init_land();\n                setBackgroundColor(Color.RED);\n            }\n        });\n    }\n}\n```\n\n\u003cimg src=\"./images/customized.png\" width=300 title=\"Image\"\u003e\n\nBy the way, In the example above, on bottom you can see a constraint layout with a simple TextView and a SmileView which both of them are added to the layout by `\u003cinclude/\u003e`\n\n## ViewModel\n**XmlByPass** will automatically generate ViewModels which extend `androidx.lifecycle.ViewModel` for your layout and contains some LiveData variables.\n\nTo use this feature, you must follow a specific structure in your xml so that **XmlByPass** can define variables correctly.\n\nThis structure is very simple and can be created by just adding a few tags to the views.\n\nA quick review: \n\n\u003e By `viewModel` you can specify whether **XmlByPass** should generate a [`ViewModel`](https://developer.android.com/topic/libraries/architecture/viewmodel) class (Using [`LiveData`](https://developer.android.com/topic/libraries/architecture/livedata)) or not.\n\u003e\n\u003e This helps you to implement [MVVM](https://www.geeksforgeeks.org/mvvm-model-view-viewmodel-architecture-pattern-in-android/) architecture easier than before, by only a single xml layout file.\n\u003e ```java\n\u003e @XmlByPass(layouts = {\n\u003e         @XmlLayout(layout = \"activity_main\", className = \"ActivityMain\", viewModel = \"ActivityMainViewModel\"),\n\u003e }, viewModel = true)\n\u003e ```\n\nConsider the following layout:\n```xml\n\u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\n\u003cRelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\".MainActivity\"\u003e\n\n    \u003cTextView\n        android:id=\"@+id/tv\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_centerInParent=\"true\"\n        android:text=\"Hello World!\"/\u003e\n\n\u003c/RelativeLayout\u003e\n```\n\nOk, now see this one:\n```xml\n\u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\n\u003cRelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\".MainActivity\"\u003e\n \n    \u003cTextView\n        android:id=\"@+id/tv\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_centerInParent=\"true\"\u003e\n     \n     \u003ctag android:id=\"@+id/myText\" android:value=\"live;attr=text;Hello World!\"/\u003e\n    \u003c/TextView\u003e\n\n\u003c/RelativeLayout\u003e\n```\n\nWe just added a tag to the TextView :\n```xml\n\u003ctag android:id=\"@+id/myText\" android:value=\"live;attr=text;Hello World!\"/\u003e\n```\n\n- `android:id` specifies the name of the variable\n- `android:value` starts with `live;` so **XmlByPass** can undrestand this tag will be a LiveData\n- `attr=text` means the target attribute is setText(String)\n- `Hello World!` is the initial value of variable\n\nThe generated ViewModel:\n```java\nimport androidx.lifecycle.LiveData;\nimport androidx.lifecycle.MutableLiveData;\nimport androidx.lifecycle.ViewModel;\n\npublic class MyViewModel extends ViewModel {\n\n\tMutableLiveData\u003cString\u003e myText = new MutableLiveData\u003c\u003e(\"Hello World!\");\n\n\tpublic LiveData\u003cString\u003e getMyText() {\n\t\treturn myText;\n\t}\n\n\tpublic void setMyText(String value) {\n\t\tmyText.setValue(value);\n\t}\n\n}\n```\n\nAnd this is how you can change data in MainActivity:\n```java\nMyViewModel viewModel = new ViewModelProvider(this).get(MyViewModel.class);\nviewModel.setMyText(\"Awesome!\");\n```\n\nThe generated java class of your layout will automatically observe the LiveData.\n\n**I prefer to define variables first and use them later.**\n```xml\n\u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\n\u003cRelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\".MainActivity\"\u003e\n \n    \u003ctag android:id=\"@+id/myText\" android:value=\"live;type=string;Hello World!\"/\u003e\n \n    \u003cTextView\n        android:id=\"@+id/tv\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_centerInParent=\"true\"\u003e\n     \n     \u003ctag android:id=\"@+id/myText\" android:value=\"live;func=setText\"/\u003e\n    \u003c/TextView\u003e\n\n\u003c/RelativeLayout\u003e\n```\n\nThis line defines a new LiveData variable with type of `String` :\n```xml\n\u003ctag android:id=\"@+id/myText\" android:value=\"live;type=string;Hello World!\"/\u003e\n```\n\nAnd this one observes tv to myText (The variable that we just defined) and connects it to the `setText` function:\n```xml\n\u003ctag android:id=\"@+id/myText\" android:value=\"live;func=setText\"/\u003e\n```\n\n**Let's start using a custom type!**\n\nConsider the following model:\n```java\npackage com.example;\n\npublic class User {\n\n    public String name;\n\n    public User(String name) {\n        this.name = name;\n    }\n}\n```\n\nAnd this is your xml:\n```xml\n\u003c?xml version=\"1.0\" encoding=\"utf-8\"?\u003e\n\u003cRelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\".MainActivity\"\u003e\n \n    \u003ctag android:id=\"@+id/user\" android:value=\"live;type=com.example.User\"/\u003e\n \n    \u003cTextView\n        android:id=\"@+id/tv\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_centerInParent=\"true\"\u003e\n     \n     \u003ctag android:id=\"@+id/user\" android:value=\"live;src=setText(user.name)\"/\u003e\n    \u003c/TextView\u003e\n\n\u003c/RelativeLayout\u003e\n```\n\nThis line defines a new LiveData variable with type of `com.example.User` :\n```xml\n\u003ctag android:id=\"@+id/user\" android:value=\"live;type=com.example.User\"/\u003e\n```\n\nAnd this one observes tv to the variable and connects it to the `setText` function with the specified source:\n```xml\n\u003ctag android:id=\"@+id/user\" android:value=\"live;src=setText(user.name)\"/\u003e\n```\n\n\nSo view can observe a variable in 3 ways: `src`, `func` and `attr`\n\n## Custom Attribute\n\nAs i said before, **XmlByPass** will generate style resource for unknown attributes. but you can pre define them if you needed to by using `@XmlByPassAttr`:\n\nFor example:\n```java\n@XmlByPassAttr(name = \"app:color\", format = \"color\")\npublic class MainActivity extends AppCompatActivity {\n```\nThis means that there is a `setColor(int)` function in the views that use this attribute\n\n```java\n@XmlByPassAttr(name = \"app:color\", format = \"color\", codeName = \"backgroundColor\")\n```\nThis means that there is a `setBackgroundColor(int)` function in the views that use this attribute\n\n```java\n@XmlByPassAttr(name = \"app:color\", format = \"color\", enums = {\n        @XmlByPassAttrEnum(key = \"black\", value = \"Color.BLACK\"),\n        @XmlByPassAttrEnum(key = \"white\", value = \"Color.WHITE\")\n})\n```\nThis means that there is a `setColor(int)` function in the views that use this attribute and **enums** are replaced by their value.\n\n## Performance\nThis library does not optimize your code, but overwrites it with Java code so that there are no more xml interfaces. If you follow the principles of designing layouts, you can be sure that you will have the highest performance :)\n\nFollow these steps:\n\n- Avoid adding useless parents.\n- Avoid ConstraintLayout as long as you can replace it with FrameLayout or LinearLayout. ([Read more](https://medium.com/android-news/constraint-layout-performance-870e5f238100))\n- Avoid nested layouts and find the best ViewGroup for your position.\n\n\n\n## Author\nAmir Hossein Aghajari\n\n### SUPPORT ❤️\nIf you find this library useful, Support it by joining [**stargazers**](https://github.com/aghajari/XmlByPass/stargazers) for this repository ⭐️\n\n\nLicense\n=======\n\n    Copyright 2022 Amir Hossein Aghajari\n    Licensed under the Apache License, Version 2.0 (the \"License\");\n    you may not use this file except in compliance with the License.\n    You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n    Unless required by applicable law or agreed to in writing, software\n    distributed under the License is distributed on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n    See the License for the specific language governing permissions and\n    limitations under the License.\n\n\u003cbr\u003e\n\u003cdiv align=\"center\"\u003e\n  \u003cimg width=\"64\" alt=\"LCoders | AmirHosseinAghajari\" src=\"https://user-images.githubusercontent.com/30867537/90538314-a0a79200-e193-11ea-8d90-0a3576e28a18.png\"\u003e\n  \u003cbr\u003e\u003ca\u003eAmir Hossein Aghajari\u003c/a\u003e • \u003ca href=\"mailto:amirhossein.aghajari.82@gmail.com\"\u003eEmail\u003c/a\u003e • \u003ca href=\"https://github.com/Aghajari\"\u003eGitHub\u003c/a\u003e\n\u003c/div\u003e\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faghajari%2Fxmlbypass","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faghajari%2Fxmlbypass","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faghajari%2Fxmlbypass/lists"}