{"id":13611173,"url":"https://github.com/programadorthi/synthetic-to-viewbinding","last_synced_at":"2025-05-15T16:32:46.823Z","repository":{"id":96415432,"uuid":"598366528","full_name":"programadorthi/synthetic-to-viewbinding","owner":"programadorthi","description":"A Intellij plugin to migrate Kotlin synthetics to Jetpack view binding","archived":false,"fork":false,"pushed_at":"2023-02-16T18:41:51.000Z","size":123,"stargazers_count":21,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-03T11:37:10.625Z","etag":null,"topics":["android","android-extensions","android-studio","intellij-plugin","kotlin","kotlin-syntetics","viewbinding-android"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/programadorthi.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,"governance":null,"roadmap":null,"authors":null}},"created_at":"2023-02-07T00:34:31.000Z","updated_at":"2024-03-27T03:06:23.000Z","dependencies_parsed_at":"2023-07-13T13:45:37.076Z","dependency_job_id":null,"html_url":"https://github.com/programadorthi/synthetic-to-viewbinding","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/programadorthi%2Fsynthetic-to-viewbinding","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/programadorthi%2Fsynthetic-to-viewbinding/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/programadorthi%2Fsynthetic-to-viewbinding/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/programadorthi%2Fsynthetic-to-viewbinding/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/programadorthi","download_url":"https://codeload.github.com/programadorthi/synthetic-to-viewbinding/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254377312,"owners_count":22061118,"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","android-extensions","android-studio","intellij-plugin","kotlin","kotlin-syntetics","viewbinding-android"],"created_at":"2024-08-01T19:01:52.503Z","updated_at":"2025-05-15T16:32:46.487Z","avatar_url":"https://github.com/programadorthi.png","language":"Kotlin","funding_links":[],"categories":["Kotlin"],"sub_categories":[],"readme":"# synthetic-to-viewbinding\nA Intellij plugin to migrate Kotlin synthetics to Jetpack view binding\n\n\u003e Please, this plugin is not perfect. Read all sections below before use it.\n\u003e \n\u003e It was developed using my context that can be totally different from your. Keep it in mind!\n\n#### This plugin supports kotlin source and build.gradle(.kts) files only.\n\n## How to use\n1. Install the plugin from Marketplace (link soon)\n2. On the android module, enable viewBinding in your build.gradle(.kts)\n```groovy\nandroid {\n    // New AGP version setup\n    viewBinding.enable = true\n    // Old AGP version setup\n    buildFeatures {\n        viewBinding true\n    }\n}\n```\n3. Right click on your class or module and select the menu: `Refactor -\u003e Migrate Synthetic to ViewBinding`\n4. In the popup select your options, filters and click in the button `Run`.\n\n\u003e Popup options are from your IDE code styles settings and run after view binding migration. \n\n## Features\n\n- Activity, Dialog, ViewGroup and View migration\n- Replace setContentView(R.layout.name) with setContentView(binding.root)\n- Remove View.inflate() or LayoutInflate.inflate from init {} blocks\n- Support for multiple synthetics in the same class\n- Remove plugin and android extensions configurations from build(.gradle|.kts)\n- Update @Parcelize imports and add plugin to build(.gradle|.kts)\n- Generate bind behaviors to ViewStub inflate()\n- Organize imports, Reformat code, Code cleanup based on your IDE code style settings\n\n\u003e At the end, all synthetics references become lazy {} properties because replacing all references with `binding.` prefix is a mess and is easy for pull request reviewers.\n\nFrom:\n```kotlin\nclass MyClass : AnySupportedType {\n    fun something() {\n        synthetic1.do()\n        synthetic2.do()\n        ...\n    }\n}\n```\nTo:\n```kotlin\nclass MyClass : AnySupportedType {\n    // For Activity, Dialog, ViewGroup or View without parent\n    // Inside MyClass is the same as: MyViewBinding.inflate(layoutInflater)\n    private val bindingName by viewBinding(MyViewBinding::inflate)\n    // For ViewGroup or View used as xml root tag and it is inflated already\n    // Like: my_layout.xml\n    // \u003ccom.example.MyClass\u003e ... \u003c/com.example.MyClass\u003e\n    // Inside MyClass is the same as: MyLayoutBinding.bind(this)\n    private val bindingName by viewBinding(MyLayoutBinding::bind)\n    // For ViewGroup or View not used as xml root tag and will be the parent\n    // Like: my_layout.xml\n    // \u003cSomeLayout\u003e ... \u003c/SomeLayout\u003e\n    // Inside MyClass is the same as: MyLayoutBinding.inflate(layoutInflater, this, true) \n    private val bindingName by viewBindingAsChild(MyLayoutBinding::inflate)\n    // For ViewGroup or View having \u003cmerge\u003e as xml root tag.\n    // Like: my_layout.xml\n    // \u003cmerge\u003e ... \u003c/merge\u003e\n    // Inside MyClass is the same as: MyLayoutBinding.inflate(layoutInflater, this) \n    private val bindingName by viewBindingMergeTag(MyLayoutBinding::inflate)\n\n    private val synthetic1 by lazy { bindingName.synthetic1 }\n    private val synthetic2 by lazy { bindingName.synthetic2 }\n    \n    // for \u003cinclude/\u003e layout\n    // include layout binding are, almost, already resolved by view binding plugin\n    // so we do not need do manual bind like: MyIncludeLayout.bind(bindingName.root)\n    private val includeId by lazy { bindingName.includeId }\n    \n    // for ViewStub\n    private val viewStubId by lazy { \n        val view = bindingName.viewStubId.inflate()\n        ViewStubBinding.bind(view)\n    }\n    \n    fun something() {\n        synthetic1.do()\n        synthetic2.do()\n        includeId.do()\n        viewStubId.something()\n    }\n}\n```\n\nThings to know here:\n1. `viewBinding` came from our custom extension functions and all rights to [@Zhuinden](https://github.com/Zhuinden/simple-stack) article [Simple one-liner ViewBinding in Fragments and Activities with Kotlin](https://medium.com/@Zhuinden/simple-one-liner-viewbinding-in-fragments-and-activities-with-kotlin-961430c6c07c)\n2. If you do not have this kind of extensions, you are free to adapt the plugin. Maybe I do in the future. Pull requests are welcome!\n\n## Groupie features\n\n- Replace super type from Item to BindableItem\u003cMyViewBinding\u003e\n\nFrom:\n```kotlin\nclass MyViewHolder : Item() {\n    ...\n}\n```\nTo:\n```kotlin\nclass MyViewHolder : BindableItem\u003cMyViewBinding\u003e() {\n    ...\n}\n```\n\n- Add initializeViewBinding(view) function\n\n```kotlin\nclass MyViewHolder : BindableItem\u003cMyViewBinding\u003e() {\n    override fun initializeViewBinding(view: View): MyViewBinding =\n        MyViewBinding.bind(view)\n}\n``` \n\n- Replace `itemView` or `contentView` with `root`\n- Replace `GroupieViewHolder` functions parameters with MyViewBinding class\n\nFrom:\n```kotlin\nclass MyViewHolder : Item() {\n    override fun bind(viewHolder: GroupieViewHolder, position: Int) {\n        ...\n    }\n}\n``` \nTo:\n```kotlin\nclass MyViewHolder : BindableItem\u003cMyViewBinding\u003e() {\n    override fun bind(viewHolder: MyViewBinding, position: Int) {\n        ...\n    }\n}\n``` \n\n# Things not supported to keep in mind\n\n- Fragments because we do not use it anywhere! :D\n- RecyclerView.Adapter because we use Groupie instead.\n- Inner classes\n- Constructor layout Activity|Fragment(R.layout.something)\n- Functions having `GroupieViewHolder` as argument type but there is no synthetic references in your body are not changed by default.\n```kotlin\nclass MyViewHolder : Item() {\n    // bind parameter type will not be replaced because it is difficult to know the view binding type\n    override fun bind(viewHolder: GroupieViewHolder, position: Int) {\n        // No synthetic references here or used in another function like\n        functionHavingSyntheticReferences(viewHolder)\n    }\n}\n``` \n- Functions having multiples GroupieViewHolder because I do not know whom is the source of truth to synthetics inside it.\n```kotlin\nclass MyViewHolder : Item() {\n    // Two references to GroupieViewHolder to know the source of truth to synthetics :/\n    fun GroupieViewHolder.doSomenthing(other: GroupieViewHolder) {\n        // synthetic references here\n    }\n}\n``` \n- Referencing root view with itemView at same time because itemView is root already\n\nFrom:\n```kotlin\nclass MyViewHolder : Item() {\n    fun doSomenthing(viewHolder: GroupieViewHolder) {\n        // here itemView and rootTagId are the same root tag\n        viewHolder.itemView.rootTagId.something()\n    }\n}\n``` \nTo:\n```kotlin\nclass MyViewHolder : BindableItem\u003cMyViewBinding\u003e() {\n    fun doSomenthing(viewHolder: MyViewBinding) {\n        // will change to root but it is an error\n        viewHolder.root.rootTagId.something()\n    }\n}\n``` \n- ViewStub resolution property when declared by lazy { viewStub.inflate() } or referenced in \u003cinclude/\u003e. As you saw above, properties for ViewStub are automatically generated. So, if you have custom inflation, you need to fix\n- \u003cinclude/\u003e layouts binding not resolved by view binding plugin. As you saw above, includes are almost resolve by view binding plugin. But, sometimes, you will need to do manual binding.\n\n## Author\n- Thiago Santos - [@programadorthi](https://github.com/programadorthi)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprogramadorthi%2Fsynthetic-to-viewbinding","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fprogramadorthi%2Fsynthetic-to-viewbinding","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprogramadorthi%2Fsynthetic-to-viewbinding/lists"}