{"id":15622152,"url":"https://github.com/skydoves/whatif","last_synced_at":"2025-05-15T01:04:14.861Z","repository":{"id":37975626,"uuid":"207059648","full_name":"skydoves/WhatIf","owner":"skydoves","description":"☔ Fluent syntactic sugar to handle single if-else statements, nullable, collections, and booleans for Kotlin and KMP.","archived":false,"fork":false,"pushed_at":"2024-10-22T03:23:19.000Z","size":687,"stargazers_count":911,"open_issues_count":1,"forks_count":36,"subscribers_count":14,"default_branch":"main","last_synced_at":"2025-04-06T17:09:46.648Z","etag":null,"topics":["android","builder-pattern","expression","extensions","if-else","kotlin","nullable","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":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"skydoves","custom":["https://www.paypal.me/skydoves","https://www.buymeacoffee.com/skydoves"]}},"created_at":"2019-09-08T04:05:14.000Z","updated_at":"2025-04-05T18:43:24.000Z","dependencies_parsed_at":"2023-02-14T07:31:42.725Z","dependency_job_id":"b1beea7a-136f-4381-b31a-713e3080d0d7","html_url":"https://github.com/skydoves/WhatIf","commit_stats":null,"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skydoves%2FWhatIf","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skydoves%2FWhatIf/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skydoves%2FWhatIf/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/skydoves%2FWhatIf/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/skydoves","download_url":"https://codeload.github.com/skydoves/WhatIf/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248784965,"owners_count":21161208,"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","builder-pattern","expression","extensions","if-else","kotlin","nullable","skydoves"],"created_at":"2024-10-03T09:53:05.961Z","updated_at":"2025-04-13T21:29:06.331Z","avatar_url":"https://github.com/skydoves.png","language":"Kotlin","readme":"![whatif](https://user-images.githubusercontent.com/24237865/127761307-b19f130f-dce6-4b14-a590-42361a8567e5.png)\u003cbr\u003e\n\n\n\u003cp align=\"center\"\u003e\n☔ Fluent Kotlin expressions for handling single if-else statements, nullable, collections, and boolean. This library supports Kotlin Multiplatform.\n\u003c/p\u003e\n\u003cbr\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://devlibrary.withgoogle.com/products/android/repos/skydoves-whatif\"\u003e\u003cimg alt=\"Google\" src=\"https://skydoves.github.io/badges/google-devlib.svg\"/\u003e\u003c/a\u003e\u003cbr\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/WhatIf/actions\"\u003e\u003cimg alt=\"Build Status\" src=\"https://github.com/skydoves/WhatIf/workflows/Android%20CI/badge.svg\"/\u003e\u003c/a\u003e\n  \u003ca href=\"https://androidweekly.net/issues/issue-406\"\u003e\u003cimg alt=\"Android Weekly\" src=\"https://skydoves.github.io/badges/android-weekly.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://skydoves.github.io/libraries/whatif/html/index.html\"\u003e\u003cimg alt=\"Javadoc\" src=\"https://skydoves.github.io/badges/dokka-whatif.svg\"/\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n## Download\n[![Maven Central](https://img.shields.io/maven-central/v/com.github.skydoves/whatif.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22com.github.skydoves%22%20AND%20a:%22whatif%22)\n\n☔ WhatIf has been downloaded in more than __300k__ Kotlin and Android projects all over the world! \u003cbr\u003e\u003cbr\u003e\n![downloads](https://user-images.githubusercontent.com/24237865/101273131-2187a980-37d6-11eb-9000-e1cd10f87b0d.png)\n\n### Gradle\nAdd the dependency below to your module's `build.gradle` file:\n\n```gradle\ndependencies {\n    implementation(\"com.github.skydoves:whatif:1.2.1\")\n}\n```\n\nFor Kotlin Multiplatform, add the dependency below to your module's `build.gradle.kts` file:\n\n```kotlin\nsourceSets {\n    val commonMain by getting {\n        dependencies {\n            implementation(\"com.github.skydoves:whatif:1.2.1\")\n        }\n    }\n}\n```\n\n## Usage\n\nWhatIf fully supports Kotlin Multiplatform, making it versatile for use in pure Kotlin modules as well as other platforms. You can leverage it in various use cases, including Jetpack Compose, where it helps streamline conditional logic. For instance, you can integrate `WhatIf` in Jetpack Compose to handle conditional rendering, as shown in the example below. This flexibility allows developers to maintain clean, readable code across different Kotlin Multiplatform projects.\n\n```kotlin\nBox(\n  modifier = Modifier\n      .align(Alignment.Center)\n      .clickable { isBlueColor = !isBlueColor }\n      .whatIfMap(isBlueColor, { it.background(Color.Blue) }, { it.background(Color.Cyan) })\n      .whatIfMap(isBlueColor, { it.size(120.dp) }, { it.size(240.dp) }),\n)\n```\n\n![preview](https://github.com/user-attachments/assets/99d73a48-2e8e-4e99-b553-2c7e57382bfd)\n\n### WhatIf\n\n`WhatIf` is a Kotlin expression that triggers a lambda expression (`whatIf` block) when the provided boolean condition is true and the object is non-null. It's a concise way to handle conditional logic without needing verbose if-else statements, enabling cleaner, more readable code for specific actions when conditions are met.\n\n```kotlin\nval nullableBoolean: Boolean? = true\nwhatIf(nullableBoolean) {\n  log(\"not-null and true : $nullableBoolean\")\n}\n```\n\nHere is an extension for nullable booleans.\n\n```kotlin\nnullableBoolean.whatIf {\n  log(\"not-null and true : $nullableBoolean\")\n}\n```\n\n### WhatIfNot\n\nThe `whatIf` expression consists of three main parts: `given`, `whatIf`, and `whatIfNot`. If the condition is true and the target is non-null, the `whatIf` lambda is executed. However, if the condition is false or the target is null, the `whatIfNot` lambda will be invoked instead. The `whatIfNot` block is optional, so if there's no need to handle the false/null case, it can simply be omitted, allowing for more concise code when necessary.\n\n```kotlin\nwhatIf(\n  given = nullableBoolean,\n  whatIf = { log(\"not-null and true : $nullableBoolean\") },\n  whatIfNot = { log(\"null or false : $nullableBoolean\") }\n)\n```\n\nHere's an extension function designed specifically for nullable booleans.\n\n```kotlin\nnullableBoolean.whatIf(\n  whatIf = { log(\"not-null and true : $nullableBoolean\") },\n  whatIfNot = { log(\"not-null or false : $nullableBoolean\") }\n)\n```\n\n### WhatIf in the builder pattern\n\nSometimes, you need to configure a builder differently depending on the available options. This is where `WhatIf` proves useful, especially when using a chaining function like in builder patterns. It can be seamlessly applied to various builder patterns, such as `AlertDialog.Builder` or any other similar construct, allowing conditional logic to be injected cleanly and fluently based on the provided conditions, without breaking the flow of method chaining.\n\n```kotlin\nval balloon = Balloon.Builder(baseContext)\n  .setArrowSize(10)\n  .setArrowVisible(true)\n  .whatIf(nullableBoolean) { setTextColor(Color.YELLOW) }\n  .whatIf(nullableBoolean, { setText(\"Hello, whatIf\") }, { setText(\"Good-Bye whatIf\") })\n  .setWidthRatio(1.0f)\n  .build()\n```\n\n### WhatIfNotNull\n\n`WhatIfNotNull` is a Kotlin expression that triggers the `whatIf` lambda when the target object is not null. This function simplifies handling nullable objects, allowing you to perform actions only when the object is valid, making your code cleaner by avoiding manual null checks. It's particularly useful for eliminating boilerplate when working with nullable types in Kotlin.\n\n```kotlin\nval nullableObject: Person? = Person()\nnullableObject.whatIfNotNull {\n  log(\"$it is not null\")\n}\n```\n\nYou can also handle cases where the target object is null. In such scenarios, instead of executing the `whatIf` lambda, the `whatIfNot` lambda will be triggered. This ensures that null cases are properly managed, providing an alternative action when the object is null, making your code more robust and adaptable to nullable conditions.\n\n```kotlin\nnullableObject.whatIfNotNull(\n  whatIf = { log(\"$it is not null.\") },\n  whatIfNot = { log(\"$it is null.\") }\n)\n```\n\n### WhatIfNotNullAs\n\n`WhatIfNotNullAs` is an expression for invoking `whatIf` lambda when the target object is not null and the target can be cast by the desired type, the receiver will get a casted type.\n\n```diff\n- (serializable as? Poster?)?.let { poster -\u003e\n- \n- }\n\n+ parcelable.whatIfNotNullAs\u003cPoster\u003e { poster -\u003e\n+  log(poster.name)\n+ }\n```\n\nYou can also handle the exception case (target is null or can't cast by the desired type) using `whatIfNot`.\n\n```diff\n- (serializable as? Poster?)?.let { poster -\u003e\n-  log(poster.name)\n- } ?: let {\n-  // do something\n- }\n\n+ serializable.whatIfNotNullAs\u003cPoster\u003e(\n+  whatIf = { poster -\u003e log(poster.name) },\n+  whatIfNot = { \n+    // do something\n+  })\n```\n\n### WhatIfNotNullOrEmpty\n\nAn expression for invoking the `whatIf` lambda when the target, such as a **string**, **collection**, or **array**, is neither null nor empty. If the target is null or empty, the `whatIfNot` lambda will be executed instead. This approach ensures that you can easily handle non-empty, valid collections or arrays, while providing an alternative behavior for null or empty cases, streamlining conditional logic when dealing with these data types.\n\n```kotlin\nval nullableString: String? = \"NotNullOrEmpty\"\nnullableString.whatIfNotNullOrEmpty { \n  log(\"$it is not null and not empty\")\n}\n```\n\nHere is an example for collections.\n\n```kotlin\nnullableList.whatIfNotNullOrEmpty {\n  log(\"list $it is not null and not empty\")\n}\n```\n\nYou can also handle the null or empty case.\n\n```kotlin\nnullableList.whatIfNotNullOrEmpty(\n  whatIf = { log(\"list $it is not null and not empty\") },\n  whatIfNot = { log(\"list is null or empty\") }\n)\n```\n\nHere is the same example for the array.\n\n```kotlin\nnullableArray.whatIfNotNullOrEmpty {\n  log(\"$it is not null and not empty\")\n}\n```\n#### Array\nArray, ByteArray, ShortArray, IntArray, LongArray, FloatArray, DoubleArray, BooleanArray, CharArray\n\n#### Collections \n\nYou can use some expressions for List, Map, and Set.\n\n- whatIfNotNullOrEmpty: An expression for invoking `whatIf` when the `List` is not null and not empty.\n- addWhatIfNotNull: An expression for adding an element and invoking `whatIf` when the element is not null.\n- addAllWhatIfNotNull: An expression for adding an element and invoking `whatIf` when the element is not null.\n- removeWhatIfNotNull: An expression for removing an element and invoking `whatIf` when the element is not null.\n- removeAllWhatIfNotNull: An expression for removing a collection of element and invoking `whatIf` when the element is not null.\n\n\n### WhatIfMap\n\nThe basic concept is the same as `whatIf`. An expression for invoking `whatIf` when the target object is not null. It is useful when the type of the receiver and the result should be different.\u003cbr\u003e\n\n```kotlin\nval length: Int = nullableString.whatIfMap(\n  whatIf = { it.length },\n  whatIfNot = {\n    log(\"$it, nullableString is null.\")\n    -1\n  }\n)\n```\n\nYou can use a default value instead of the `whatIfNot` and it can be omitted.\n\n```kotlin\nval length = nullableString.whatIfMap(\n    default = -1\n  ) { \n  log(\"$it, length can not over than 5.\")\n  5\n}\n```\n\n### whatIfElse\nAn expression for invoking `whatIf` lambda when the target boolean is not null and false.\n```kotlin\nnullableBoolean.whatIfElse {\n  log(\"nullableBoolean is not null and false\")\n}\n```\n\n### WhatIfAnd, WhatIfOr\nAn expression for invoking `whatIf` lambda when the target boolean is true and/or a predicate receiver is true.\u003cbr\u003e\n```kotlin\nnullableBoolean.whatIfAnd(predicate) {\n  log(\"nullableBoolean is true and the predicate is also true\")\n}\n\nnullableBoolean.whatIfOr(predicate) {\n  log(\"nullableBoolean is true or the predicate is true\")\n}\n```\n\n## WhatIf for Android Extension\n\nYou can use the whatIf extensions related to the Android project.\u003cbr\u003e\n\n[![Maven Central](https://img.shields.io/maven-central/v/com.github.skydoves/whatif-android-ext.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22com.github.skydoves%22%20AND%20a:%22whatif-android%22)\n\n### Gradle\n\nAdd the dependency below to your **module**'s `build.gradle` file:\n\n```gradle\ndependencies {\n    implementation \"com.github.skydoves:whatif-android-ext:version\"\n}\n```\n\n### WhatIf for Android Activity\n### WhatIfHasExtras\nAn expression for invoking `whatIf` lambda when the Activity's intent extras is not null and not empty.\n```kotlin\nvar foo: String? = null\nthis@MainActivity.whatIfHasExtras {\n  foo = \"${it.getString(\"foo\")}\"\n}\n```\nYou can also handle the null case.\u003cbr\u003e\n```kotlin\nthis@MainActivity.whatIfHasExtras(\n   whatIf = { foo = \"${it.getString(\"foo\")}\" },\n   whatIfNot = { log(\"intent extras is null or empty.\") }\n)\n```\nYou can null-check and typecast simultaneously when you getting intent extra data.\n```kotlin\nwhatIfHasSerializableExtra\u003cPoster\u003e(\"poster\") { poster -\u003e\n ...\n}\nwhatIfHasParcelableExtra\u003cPoster\u003e(\"poster\") { poster -\u003e\n ...\n}\n```\n\n### WhatIf for Android fragment\n#### whatIfNotNullContext\nAn expression for invoking `whatIf` lambda  when the Context is not null.\n```kotlin\nclass WhatIfFragment : Fragment() {\n\n  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {\n    super.onViewCreated(view, savedInstanceState)\n\n    whatIfNotNullContext {\n      Toast.makeText(it, \"context is not null!\", Toast.LENGTH_SHORT).show()\n    }\n  }\n}\n```\n\n#### whatIfNotNullArguments\nAn expression for invoking `whatIf` when the `Fragment.getArguments` is not null.\n```kotlin\nwhatIfNotNullArguments {\n  it.getString(\"name\").whatIfNotNull {\n    log(\"my name is $it\")\n  }\n}\n```\n\n#### whatIfNotNullActivity\nAn expression for invoking `whatIf` lambda when the Activity is not null.\n```kotlin\nwhatIfNotNullActivity { activity -\u003e\n  activity.supportFragmentManager.addOnBackStackChangedListener {\n    // .. //\n  }\n}\n```\n\n#### whatIfFindParentInterface\n An expression for invoking `whatIf` lambe when the `Fragment` has an `T` interface as a parent. Let's assume we have a `MainActivity` that implements `OnClickCallback` interface,\n\n ```kotlin\nclass MainActivity : AppCompatActivity(), OnClickCallback {\n  ...\n}\n```\n\nYou can get the parent Activity's `OnClickCallback` interface on Fragment as following with the `whatIfFindParentInterface`:\n```kotlin\nclass MainFragment: Fragment() {\n\n override fun onCreateView(\n  inflater: LayoutInflater,\n  container: ViewGroup?,\n  savedInstanceState: Bundle?\n ): View? {\n  return super.onCreateView(inflater, container, savedInstanceState)\n  \n  whatIfFindParentInterface\u003cOnClickCallback\u003e { \n   it.onClickedButtonFromFragment()\n  }\n }\n}\n```\n\n## Find this library useful? :heart:\nSupport it by joining **__[stargazers](https://github.com/skydoves/whatif/stargazers)__** for this repository. :star: \u003cbr\u003e\nAlso, **__[follow](https://github.com/skydoves)__** me for my next creations! 🤩\n\n# License\n```xml\nCopyright 2019 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 License.\n```\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%2Fwhatif","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fskydoves%2Fwhatif","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fskydoves%2Fwhatif/lists"}