{"id":15627619,"url":"https://github.com/skydoves/lazybones","last_synced_at":"2025-04-07T11:10:36.410Z","repository":{"id":37715798,"uuid":"232824014","full_name":"skydoves/lazybones","owner":"skydoves","description":"😴 A lazy and fluent syntactic sugar for observing Activity, Fragment, and ViewModel lifecycles with lifecycle-aware properties.","archived":false,"fork":false,"pushed_at":"2022-02-06T15:44:52.000Z","size":366,"stargazers_count":353,"open_issues_count":0,"forks_count":17,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-03-31T10:05:30.244Z","etag":null,"topics":["android","expression","extensions","kotlin","lazy","lifecycle","lifecycle-aware","skydoves"],"latest_commit_sha":null,"homepage":"","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/skydoves.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null},"funding":{"github":"skydoves","custom":["https://www.paypal.me/skydoves","https://www.buymeacoffee.com/skydoves"]}},"created_at":"2020-01-09T14:10:09.000Z","updated_at":"2024-10-31T01:23:59.000Z","dependencies_parsed_at":"2022-09-26T21:50:14.810Z","dependency_job_id":null,"html_url":"https://github.com/skydoves/lazybones","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skydoves%2Flazybones","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skydoves%2Flazybones/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skydoves%2Flazybones/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skydoves%2Flazybones/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/skydoves","download_url":"https://codeload.github.com/skydoves/lazybones/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247640465,"owners_count":20971557,"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","expression","extensions","kotlin","lazy","lifecycle","lifecycle-aware","skydoves"],"created_at":"2024-10-03T10:18:00.928Z","updated_at":"2025-04-07T11:10:36.376Z","avatar_url":"https://github.com/skydoves.png","language":"Kotlin","readme":"# Lazybones\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://opensource.org/licenses/Apache-2.0\"\u003e\u003cimg alt=\"License\" src=\"https://img.shields.io/badge/License-Apache%202.0-blue.svg\"/\u003e\u003c/a\u003e\n  \u003ca href=\"https://android-arsenal.com/api?level=15\"\u003e\u003cimg alt=\"API\" src=\"https://img.shields.io/badge/API-15%2B-brightgreen.svg?style=flat\"/\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/skydoves/Lazybones/actions/workflows/android.yml\"\u003e\u003cimg alt=\"Build Status\" src=\"https://github.com/skydoves/Lazybones/actions/workflows/android.yml/badge.svg\"/\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/skydoves\"\u003e\u003cimg alt=\"Profile\" src=\"https://skydoves.github.io/badges/skydoves.svg\"/\u003e\u003c/a\u003e\n  \u003ca href=\"https://androidweekly.net/issues/issue-463\"\u003e\u003cimg alt=\"Android Weekly\" src=\"https://skydoves.github.io/badges/android-weekly.svg\"/\u003e\u003c/a\u003e\n  \u003ca href=\"https://skydoves.github.io/libraries/lazybones/html/lazybones/com.skydoves.lazybones/index.html\"\u003e\u003cimg alt=\"Javadoc\" src=\"https://skydoves.github.io/badges/javadoc-lazybones.svg\"/\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n😴 A lazy and fluent syntactic sugar for Android and ViewModel Lifecycle properties. \u003cbr\u003e\nLazybones allows you to track and observe Activity, Fragment, and ViewModel lifecycles on lifecycle-aware properties.\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n\u003cimg src=\"https://user-images.githubusercontent.com/24237865/72173497-0cb26280-341b-11ea-8d0a-5a000773600f.png\" width=\"734\" height=\"251\"/\u003e\n\u003c/p\u003e\n\n\u003e \u003cp align=\"center\"\u003eAh... I'm a super lazy person. \u003cbr\u003eI just want to declare initialization and disposition together. \u003c/p\u003e\n\n## Including in your project\n\n[![Maven Central](https://img.shields.io/maven-central/v/com.github.skydoves/lazybones.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22com.github.skydoves%22%20AND%20a:%22lazybones%22)\n\n### Gradle \nAdd the codes below to your **root** `build.gradle` file (not your module build.gradle file).\n```gradle\nallprojects {\n    repositories {\n        mavenCentral()\n    }\n}\n```\n\nNext, add the dependency below to your **module**'s `build.gradle` file.\n\n```gradle\ndependencies {\n    implementation \"com.github.skydoves:lazybones:1.0.4\"\n}\n```\n## SNAPSHOT \n[![Lazybones](https://img.shields.io/static/v1?label=snapshot\u0026message=lazybones\u0026logo=apache%20maven\u0026color=C71A36)](https://oss.sonatype.org/content/repositories/snapshots/com/github/skydoves/lazybones/) \u003cbr\u003e\nSnapshots of the current development version of Lazybones are available, which track [the latest versions](https://oss.sonatype.org/content/repositories/snapshots/com/github/skydoves/lazybones/).\n\n```gradle\nrepositories {\n   maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }\n}\n```\n\n# Usage\n\nLazybones provides `lifecycleAware` extension functions over the `LifecycleOwner`, which allows you to track and observe lifecycle changes on the same changing scope. Therefore, Lazybones can prevent function fragmentation as the lifecycle changes.\n\n## lifecycleAware\nYou can initialize a lifecycle-aware object with the `lifecycleAware` extension. The `lifecycleAware` can be used to register/unregister listeners, initailize/clear, show/dismiss, and dispose objects following the lifecycle changes of the `lifecycleOwner`. With the `by` keyword and `lazy()` methhod, you can initialize an object lazily as the following example:\n\n```kotlin\nval myDialog: Dialog by lifecycleAware { getDarkThemeDialog(baseContext) }\n    .onCreate { this.show() } // show the dialog when the lifecycle's state is onCreate.\n    .onDestroy { this.dismiss() } // dismiss the dialog when the lifecycle's state is onDestroy.\n    .lazy() // initlize the dialog lazily.\n```\n\nIn the `onCreate` and `onDestroy` lambda scope, you can omit the `this` keyword. As you can see the following example, the `MediaPlayer` will be initialized and the `start()` will be executed on the `onCreate` state of the lifecycle. The `pause()`, `stop()`, and `release()` methods will be executed along the next lifecycle state.\n\n```kotlin\nprivate val mediaPlayer: MediaPlayer by lifecycleAware {\n    MediaPlayer.create(this, R.raw.bgm3)\n}.onCreate {\n    isLooping = true\n    start()\n}.onStop {\n    pause()\n}.onResume {\n    start()\n}.onDestroy {\n    stop()\n    release()\n}.lazy() // initialize the instance lazily.\n```\n\nThe code above works the same as the following codes:\n\n```kotlin\nprivate val mediaPlayer: MediaPlayer by lazy { MediaPlayer.create(this, R.raw.bgm3) }\n\noverride fun onCreate(savedInstanceState: Bundle?) {\n  super.onCreate(savedInstanceState)\n  mediaPlayer.isLooping = true\n  mediaPlayer.start()\n}\n\noverride fun onPause() {\n  super.onPause()\n  mediaPlayer.pause()\n}\n\noverride fun onStop() {\n  super.onStop()\n  mediaPlayer.pause()\n}\n\noverride fun onResume() {\n  super.onResume()\n  mediaPlayer.start()\n}\n\noverride fun onDestroy() {\n  super.onDestroy()\n  mediaPlayer.stop()\n  mediaPlayer.release()\n}\n```\n\n### CompositeDisposable in RxJava2\n\nYou can utilize Lazybones with RxJava as the following example:\n\n```kotlin\nval compositeDisposable by lifecycleAware { CompositeDisposable() }\n    .onDestroy { dispose() } // call the dispose() method when onDestroy this activity.\n    .lazy() // initialize a CompositeDisposable lazily.\n```\n\nAs the above example, you can initialize and dispose of `CompositeDisposable` on the same method chain of the `lifecycleAware` extension.\n\n### LifecycleAware Extensions\n\nWe can execute lambda functions following lifecycle changes and here are lifecycle relevant methods for the `lifecycleAware` extension.\n\n```kotlin\n.onCreate { } // the lambda will be invoked when onCreate.\n.onStart { } // the lambda will be invoked when onStart.\n.onResume { } // the lambda will be invoked when onResume.\n.onPause { } // the lambda will be invoked when onPause.\n.onStop { } // the lambda will be invoked when onStop.\n.onDestroy { }  // the lambda will be invoked when onDestroy.\n.on(On.Create) { } // we can set the lifecycle state manually as an attribute.\n```\n\n### LifecycleAware in Normal Classes\n\nThe `lifecycleAware` is an extension of the `lifecycleOwner`, so you can use it on a `LifecycleOwner` instance as the following:\n\n```kotlin\nclass SomeClass(lifecycleOwner: LifecycleOwner) {\n\n  private val compositeDisposable by lifecycleOwner.lifecycleAware { CompositeDisposable() }\n    .onDestroy { it.dispose() }\n    .lazy()\n\n   ...\n```\n\n## LifecycleAwareProperty\n\nYou can also initialize the `lifecycleAware` property immediately with the following example:\n\n```kotlin\nprivate val lifecycleAwareProperty = lifecycleAware(CompositeDisposable())\n    // observe lifecycle's state and call the dispose() method when onDestroy  \n    .observeOnDestroy { dispose() }\n```\n\nThe `CompositeDisposable` will be initialized immediately, and it will be disposed of on the `observeOnDestroy` scope. Also, you can access the value of the property via the `value` field.\n\n```kotlin\nlifecycleAwareProperty.value.add(disposable)\nlifecycleAwareProperty.value.dispose()\n```\n\nYou can observe the lifecycle changes with `observe_` methods.\u003cbr\u003e\n\n```kotlin\nclass MainActivity : AppCompatActivity() {\n\n  private val lifecycleAwareProperty = lifecycleAware(DialogUtil.getDarkTheme())\n\n  override fun onCreate(savedInstanceState: Bundle?) {\n    super.onCreate(savedInstanceState)\n    setContentView(binding.root)\n\n    lifecycleAwareProperty\n      .observeOnCreate { show() }\n      .observeOnDestroy { dismiss() }\n      .observeOnAny { .. }\n      .observeOn(On.CREATE) { .. }\n```\n\nYou can initialize them with the Kotlin DSL way as the following:\n\n```kotlin\nprivate val lifecycleAwareProperty = lifecycleAware(getDarkThemeDialog())\n    .observe {\n      onCreate { show() }\n      onResume { restart() }\n      onDestroy { dismiss() }\n    }\n\n```\n\n### LifecycleAware for normal classes\n\nThe `lifecycleAware` is an extension of the `lifecycleOwner`, so you can use it on the `LifecycleOwner` instance as the following:\n\n```kotlin\nclass SomeClass(lifecycleOwner: LifecycleOwner) {\n\n  private val TAG = MainViewModel::class.java.simpleName\n  private val lifecycleAwareProperty = lifecycleOwner.lifecycleAware(Rabbit())\n\n init {\n    this.lifecycleAwareProperty\n      .observeOnCreate { Log.d(TAG, \"OnCreate: $this\") }\n      .observeOnStart { Log.d(TAG, \"OnStart: $this\") }\n      .observeOnResume { Log.d(TAG, \"OnResume: $this\") }\n      .observeOnPause { Log.d(TAG, \"OnPause: $this\") }\n      .observeOnStop { Log.d(TAG, \"OnStop: $this\") }\n      .observeOnDestroy { Log.d(TAG, \"OnDestroy: $this\") }\n      .observeOnAny { }\n      .observeOn(On.CREATE) { }\n  }\n  ...\n```\n\n## Lazybones for ViewModel\n\n![carbon](https://user-images.githubusercontent.com/24237865/151923496-547e6fab-0a67-42b4-94da-6b0a1ce9088a.png)\n\nLazybones supports `lifecycleAware` for Jetpack ViewModel to track and observe the lifecycle changes of the ViewModel. Basically `Lazybones-ViewModel` allows you to observe two lifecycle changes: **Initialize** and **Clear**.\n\n### Gradle\n\n[![Maven Central](https://img.shields.io/maven-central/v/com.github.skydoves/lazybones.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22com.github.skydoves%22%20AND%20a:%22lazybones%22)\n\nAdd the dependency below to your **module's** `build.gradle` file:\n\n```gradle\ndependencies {\n    implementation \"com.github.skydoves:lazybones-viewmodel:1.0.4\"\n}\n```\n\n### LifecycleAware on ViewModel\n\nYou can use the `lifecycleAwrare` extension function on your ViewModel and observe lifecycle changes as the following example:\n\n```kotlin\nclass MyViewModel : ViewModel() {\n\n  private val lifecycleAwareCompositeDisposable = lifecycleAware { CompositeDisposable() }\n    .onInitialize {\n      Log.d(TAG, \"ViewModel is initialized\")\n    }.onClear {\n      Log.d(TAG, \"ViewModel is cleared\")\n      dispose() // dispose CompositeDisposable when viewModel is getting cleared\n    }\n}\n```\n\nYou can get the value of the `lifecycleAware` with `value()` method as the following:\n\n```kotlin\nval compositeDisposable = lifecycleAwareCompositeDisposable.value()\ncompositeDisposable.add(disposable)\n```\n\nThe example above shows you to initialize `CompositeDisposable` and observe the ViewModel's lifecycle changes. The `CompositeDisposable` will be disposed when ViewModel will be cleared such as `onCleared` is called.\n\n### Lazy LifecycleAware on ViewModel\n\nYou can initialize `lifecycleAware` lazyily with the `by` keyword and `lazy()` function as the following:\n\n```kotlin\nclass MyViewModel : ViewModel() {\n\n  private val compositeDisposable: CompositeDisposable by lifecycleAware { CompositeDisposable() }\n    .onInitialize {\n      Log.d(TAG, \"viewModel is initialized\")\n    }.onClear {\n      Log.d(TAG, \"viewModel is cleared\")\n      dispose() // dispose CompositeDisposable when viewModel is getting cleared\n    }.lazy()\n}\n```\n\n## LifecycleAwareProperty on ViewModel\n\nYou can also initialize the `lifecycleAware` property immediately and observe the lifecycle changes as the following example:\n\n```kotlin\nval lifecycleAwareDisposable = lifecycleAware(CompositeDisposable())\n\ninit {\n  lifecycleAwareDisposable\n    .observeOnInitialize {  }\n    .observeOnClear {  }\n    .observeOn(OnViewModel.CLEAR) { .. }\n}\n```\n\n## Find this library useful? :heart:\nSupport it by joining __[stargazers](https://github.com/skydoves/Lazybones/stargazers)__ for this repository. :star:\u003cbr\u003e\nAnd __[follow](https://github.com/skydoves)__ me for my next creations! 🤩\n\n# License\n```xml\nCopyright 2020 skydoves (Jaewoong Eum)\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 L\n","funding_links":["https://github.com/sponsors/skydoves","https://www.paypal.me/skydoves","https://www.buymeacoffee.com/skydoves"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskydoves%2Flazybones","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskydoves%2Flazybones","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskydoves%2Flazybones/lists"}