{"id":19882809,"url":"https://github.com/reactivecircus/flowbinding","last_synced_at":"2025-05-16T02:10:34.806Z","repository":{"id":37396931,"uuid":"201777295","full_name":"ReactiveCircus/FlowBinding","owner":"ReactiveCircus","description":"Kotlin Coroutines Flow binding APIs for Android's platform and unbundled UI widgets, inspired by RxBinding.","archived":false,"fork":false,"pushed_at":"2023-03-09T04:02:19.000Z","size":16348,"stargazers_count":907,"open_issues_count":6,"forks_count":42,"subscribers_count":21,"default_branch":"main","last_synced_at":"2025-04-01T11:05:42.458Z","etag":null,"topics":["android","androidx","kotlin","kotlin-coroutines","kotlin-flow","material-components"],"latest_commit_sha":null,"homepage":"https://reactivecircus.github.io/FlowBinding/","language":"Kotlin","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/ReactiveCircus.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2019-08-11T14:46:20.000Z","updated_at":"2025-03-13T06:39:55.000Z","dependencies_parsed_at":"2024-01-14T02:37:44.052Z","dependency_job_id":"62b6c0f6-0d6a-470a-ab65-d2ecd1dba062","html_url":"https://github.com/ReactiveCircus/FlowBinding","commit_stats":null,"previous_names":[],"tags_count":20,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ReactiveCircus%2FFlowBinding","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ReactiveCircus%2FFlowBinding/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ReactiveCircus%2FFlowBinding/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ReactiveCircus%2FFlowBinding/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ReactiveCircus","download_url":"https://codeload.github.com/ReactiveCircus/FlowBinding/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247847610,"owners_count":21006100,"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","androidx","kotlin","kotlin-coroutines","kotlin-flow","material-components"],"created_at":"2024-11-12T17:18:34.208Z","updated_at":"2025-04-08T13:06:47.104Z","avatar_url":"https://github.com/ReactiveCircus.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# FlowBinding\n\n![CI](https://github.com/ReactiveCircus/FlowBinding/workflows/Build/badge.svg)\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/io.github.reactivecircus.flowbinding/flowbinding-android/badge.svg)](https://search.maven.org/search?q=g:io.github.reactivecircus.flowbinding)\n[![Android API](https://img.shields.io/badge/API-14%2B-blue.svg?label=API\u0026maxAge=300)](https://www.android.com/history/)\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n\nKotlin Flow binding APIs for Android's platform and unbundled UI widgets, inspired by [RxBinding][rxbinding].\n\n[Flow][flow] is (conceptually) a reactive streams implementation provided by the [kotlinx-coroutines-core][kotlinx-coroutines] artifact.\n\n**FlowBinding** offers an extensive set of extension functions that turn traditional callbacks / listeners on Android UI widgets into the `Flow` type.\n\n## Article\n\n- [Binding Android UI with Kotlin Flow][article] - featured in [Kotlin Weekly #170][kotlin-weekly]\n- [FlowBinding 1.0](https://dev.to/ychescale9/flowbinding-1-0-44h)\n\n## Download\n\nDependencies are hosted on [Maven Central][maven-central].\n\nLatest version:\n\n```groovy\ndef flowbinding_version = \"1.2.0\"\n```\n\n### Platform Bindings\n\n```groovy\nimplementation \"io.github.reactivecircus.flowbinding:flowbinding-android:${flowbinding_version}\"\n```\n\n### AndroidX Bindings\n\n```groovy\nimplementation \"io.github.reactivecircus.flowbinding:flowbinding-activity:${flowbinding_version}\"\nimplementation \"io.github.reactivecircus.flowbinding:flowbinding-appcompat:${flowbinding_version}\"\nimplementation \"io.github.reactivecircus.flowbinding:flowbinding-core:${flowbinding_version}\"\nimplementation \"io.github.reactivecircus.flowbinding:flowbinding-drawerlayout:${flowbinding_version}\"\nimplementation \"io.github.reactivecircus.flowbinding:flowbinding-lifecycle:${flowbinding_version}\"\nimplementation \"io.github.reactivecircus.flowbinding:flowbinding-navigation:${flowbinding_version}\"\nimplementation \"io.github.reactivecircus.flowbinding:flowbinding-preference:${flowbinding_version}\"\nimplementation \"io.github.reactivecircus.flowbinding:flowbinding-recyclerview:${flowbinding_version}\"\nimplementation \"io.github.reactivecircus.flowbinding:flowbinding-swiperefreshlayout:${flowbinding_version}\"\nimplementation \"io.github.reactivecircus.flowbinding:flowbinding-viewpager:${flowbinding_version}\"\nimplementation \"io.github.reactivecircus.flowbinding:flowbinding-viewpager2:${flowbinding_version}\"\n```\n\n### Material Components Bindings\n\n```groovy\nimplementation \"io.github.reactivecircus.flowbinding:flowbinding-material:${flowbinding_version}\"\n```\n\nSnapshots of the development version are available in [Sonatype's `snapshots` repository][snap].\n\n## Usage\n\n### Binding UI Events \n\nTo observe click events on an Android `View`:\n\n```kotlin\nfindViewById\u003cButton\u003e(R.id.button)\n    .clicks() // binding API available in flowbinding-android\n    .onEach {\n        // handle button clicked\n    }\n    .launchIn(uiScope)\n```\n\n### Binding Scope\n\n`launchIn(scope)` is a shorthand for `scope.launch { flow.collect() }` provided by the **kotlinx-coroutines-core** library.\n\nThis `uiScope` in the example above is a `CoroutineScope` that defines the lifecycle of this `Flow`. The binding implementation will respect this scope by unregistering the callback / listener automatically when the scope is cancelled.\n\nIn the context of Android lifecycle this means the `uiScope` passed in here should be a scope that's bound to the `Lifecycle` of the view the widget lives in.\n\n`androidx.lifecycle:lifecycle-runtime-ktx:2.2.0` introduced an extension property `LifecycleOwner.lifecycleScope: LifecycleCoroutineScope` which will be cancelled when the `Lifecycle` is destroyed.\n\nIn an `Activity` it might look something like this:\n\n\n```kotlin\nclass ExampleActivity : AppCompatActivity() {\n    \n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.activity_example)\n\n        findViewById\u003cViewPager2\u003e(R.id.viewPager)\n            .pageSelections() // binding API available in flowbinding-viewpager2\n            .onEach { pagePosition -\u003e\n                // handle pagePosition\n            }\n            .launchIn(lifecycleScope) // provided by lifecycle-runtime-ktx\n    }\n}\n```\n\nIn a `Fragment`:\n\n```kotlin\nclass ExampleFragment : Fragment(R.layout.example_fragment_layout) {\n    \n    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n        val binding = ExampleFragmentLayoutBinding.bind(view)\n        binding.viewPager\n            .pageSelections() // binding API available in flowbinding-viewpager2\n            .onEach { pagePosition -\u003e\n                // handle pagePosition\n            }\n            .launchIn(viewLifecycleOwner.lifecycleScope) // provided by lifecycle-runtime-ktx\n    }\n}\n```\n\nNote that with **FlowBinding** you no longer need to unregister / remove listeners or callbacks in `onDestroy()` as this is done automatically for you.\n\n### Binding UI Events with Additional Information\n\nSome UI widgets might hold a state internally which you might want to observe with a `Flow`.\n\nFor example with a `TabLayout` you might want to observe and react to the Tab selection events. In this case the binding API returns a `Flow` of custom `TabLayoutSelectionEvent` type which contains the currently selected `Tab`:\n\n```kotlin\ntabLayout.tabSelectionEvents()\n    .filterIsInstance\u003cTabLayoutSelectionEvent.TabSelected\u003e() // only care about TabSelected events\n    .onEach { event -\u003e\n        // sync selected tab title to some other UI element\n        selectedTabTitle.text = event.tab.text\n    }\n    .launchIn(uiScope)\n``` \n\n### Skipping Initial Value\n\nBindings which emit a stream of state changes return the `InitialValueFlow`.\n\nAn `InitialValueFlow` emits the **current** value (state) of the widget immediately upon collection of the `Flow`.\n\nIn some cases you might want to **skip** the initial emission of the current value. This can be done by calling the `skipInitialValue()` on the `InitialValueFlow`:\n\n```kotlin\nslider.valueChanges()\n    .skipInitialValue()\n    .onEach { value -\u003e\n        // handle value\n    }\n    .launchIn(uiScope) // current value won't be emitted immediately\n```\n\n### Additional Samples\n\nAll binding APIs are documented with **Example of usage**.\n\nAll bindings are covered by **instrumented tests** which you may want to refer to.  \n\n## Roadmap\n\nOur goal is to provide most of the bindings provided by **RxBinding**, while shifting our focus to supporting more modern **AndroidX** APIs such as **ViewPager2** and the new components in **Material Components** as they become available.\n\nList of all bindings available:\n\n* [Platform bindings][flowbinding-android]\n* [AndroidX Activity bindings][flowbinding-activity]\n* [AndroidX AppCompat bindings][flowbinding-appcompat]\n* [AndroidX Core bindings][flowbinding-core]\n* [AndroidX DrawerLayout bindings][flowbinding-drawerlayout]\n* [AndroidX Lifecycle bindings][flowbinding-lifecycle]\n* [AndroidX Navigation Component bindings][flowbinding-navigation]\n* [AndroidX Preference bindings][flowbinding-preference]\n* [AndroidX RecyclerView bindings][flowbinding-recyclerview]\n* [AndroidX SwipeRefreshLayout bindings][flowbinding-swiperefreshlayout]\n* [AndroidX ViewPager bindings][flowbinding-viewpager]\n* [AndroidX ViewPager2 bindings][flowbinding-viewpager2]\n* [Material Components bindings][flowbinding-material]\n\nPlease feel free to create an issue if you think a useful binding is missing or you want a new binding added to the library.\n\n## Credits\n\nThis library is inspired by [RxBinding][rxbinding] which provides RxJava binding APIs for Android's UI widgets.\n\nMany thanks to RxBinding's author [Jake Wharton][jake] and its contributors.\n\n## License\n\n```\nCopyright 2019 Yang Chen\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n   http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n```\n[kotlin-weekly]: https://mailchi.mp/kotlinweekly/kotlin-weekly-170\n[article]: https://dev.to/ychescale9/binding-android-ui-with-kotlin-flow-22ok\n[maven-central]: https://search.maven.org/search?q=g:io.github.reactivecircus.flowbinding\n[snap]: https://s01.oss.sonatype.org/content/repositories/snapshots/\n[rxbinding]: https://github.com/JakeWharton/RxBinding\n[jake]: https://github.com/JakeWharton\n[flow]: https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines.flow/-flow/\n[kotlinx-coroutines]: https://github.com/Kotlin/kotlinx.coroutines\n[flowbinding-android]: flowbinding-android/\n[flowbinding-activity]: flowbinding-activity/\n[flowbinding-appcompat]: flowbinding-appcompat/\n[flowbinding-core]: flowbinding-core/\n[flowbinding-drawerlayout]: flowbinding-drawerlayout/\n[flowbinding-material]: flowbinding-material/\n[flowbinding-lifecycle]: flowbinding-lifecycle/\n[flowbinding-navigation]: flowbinding-navigation/\n[flowbinding-preference]: flowbinding-preference/\n[flowbinding-recyclerview]: flowbinding-recyclerview/\n[flowbinding-swiperefreshlayout]: flowbinding-swiperefreshlayout/\n[flowbinding-viewpager]: flowbinding-viewpager/\n[flowbinding-viewpager2]: flowbinding-viewpager2/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freactivecircus%2Fflowbinding","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freactivecircus%2Fflowbinding","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freactivecircus%2Fflowbinding/lists"}