├── app ├── .gitignore ├── src │ └── main │ │ ├── res │ │ ├── values │ │ │ ├── strings.xml │ │ │ ├── colors.xml │ │ │ └── themes.xml │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ └── ic_launcher_round.png │ │ ├── mipmap-anydpi-v26 │ │ │ ├── ic_launcher.xml │ │ │ └── ic_launcher_round.xml │ │ ├── layout │ │ │ ├── activity_second.xml │ │ │ └── activity_main.xml │ │ ├── values-night │ │ │ └── themes.xml │ │ ├── drawable-v24 │ │ │ └── ic_launcher_foreground.xml │ │ └── drawable │ │ │ └── ic_launcher_background.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ └── com │ │ └── skydoves │ │ └── bundlerdemo │ │ ├── UserInfo.kt │ │ ├── MainActivity.kt │ │ ├── SecondActivity.kt │ │ ├── MainFragment.kt │ │ └── Poster.kt └── build.gradle ├── bundler ├── .gitignore ├── src │ ├── main │ │ ├── AndroidManifest.xml │ │ └── java │ │ │ └── com │ │ │ └── skydoves │ │ │ └── bundler │ │ │ ├── SingleShotLiveData.kt │ │ │ ├── IntentLiveDataProvider.kt │ │ │ ├── BundleOf.kt │ │ │ ├── ActivityBundleObserveLazy.kt │ │ │ ├── FragmentBundleObserveLazy.kt │ │ │ ├── IntentOf.kt │ │ │ ├── FragmentBundler.kt │ │ │ ├── ActivityBundler.kt │ │ │ ├── Bundler.kt │ │ │ ├── FragmentBundleLazy.kt │ │ │ ├── ActivityBundleLazy.kt │ │ │ ├── FragmentBundleValue.kt │ │ │ └── ActivityBundleValue.kt │ └── test │ │ └── java │ │ └── com │ │ └── skydoves │ │ └── bundler │ │ ├── TestFragment.kt │ │ ├── TestActivity.kt │ │ ├── data │ │ ├── UserInfo.kt │ │ ├── PosterSerializable.kt │ │ └── Poster.kt │ │ ├── IntentLiveDataProviderTest.kt │ │ ├── SingleShotLiveDataTest.kt │ │ ├── FragmentBundleObserveLazyTest.kt │ │ ├── BundlerTest.kt │ │ ├── ActivityBundleObserveLazyTest.kt │ │ ├── IntentOfTest.kt │ │ ├── ActivityBundlerTest.kt │ │ ├── FragmentBundlerTest.kt │ │ └── FragmentBundleLazyTest.kt └── build.gradle ├── settings.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── Bug_report.md │ └── Feature_request.md ├── workflows │ └── android.yml ├── CODEOWNERS └── pull_request_template.md ├── spotless.gradle ├── spotless.license.kt ├── dependencies.gradle ├── .gitignore ├── gradle.properties ├── gradlew.bat ├── gradlew ├── README.md └── LICENSE /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /bundler/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':bundler' 2 | include ':app' 3 | rootProject.name = "Bundler" -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Bundler 3 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skydoves/Bundler/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: skydoves 2 | custom: ["https://www.paypal.me/skydoves", "https://www.buymeacoffee.com/skydoves"] 3 | -------------------------------------------------------------------------------- /bundler/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skydoves/Bundler/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skydoves/Bundler/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skydoves/Bundler/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skydoves/Bundler/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skydoves/Bundler/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skydoves/Bundler/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skydoves/Bundler/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skydoves/Bundler/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skydoves/Bundler/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skydoves/Bundler/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Oct 31 00:23:46 KST 2020 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip 7 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /spotless.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.diffplug.spotless" 2 | apply from: "$rootDir/dependencies.gradle" 3 | spotless { 4 | kotlin { 5 | target "**/*.kt" 6 | ktlint("$versions.ktlintGradle").userData(['indent_size': '2', 'continuation_indent_size': '2']) 7 | licenseHeaderFile "$rootDir/spotless.license.kt" 8 | trimTrailingWhitespace() 9 | endWithNewline() 10 | } 11 | } -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_second.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFBB86FC 4 | #FF6200EE 5 | #FF3700B3 6 | #FF03DAC5 7 | #FF018786 8 | #FF000000 9 | #FFFFFFFF 10 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Something is crashing or not working as intended 4 | 5 | --- 6 | 7 | **Please complete the following information:** 8 | - Library Version [e.g. v1.0.0] 9 | - Affected Device(s) [e.g. Samsung Galaxy s10 with Android 9.0] 10 | 11 | **Describe the Bug:** 12 | 13 | Add a clear description about the problem. 14 | 15 | **Expected Behavior:** 16 | 17 | A clear description of what you expected to happen. 18 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 10 | 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem?** 8 | 9 | A clear and concise description of what the problem is. 10 | 11 | **Describe the solution you'd like:** 12 | 13 | A clear and concise description of what you want to happen. 14 | 15 | **Describe alternatives you've considered:** 16 | 17 | A clear description of any alternative solutions you've considered. 18 | -------------------------------------------------------------------------------- /.github/workflows/android.yml: -------------------------------------------------------------------------------- 1 | name: Android CI 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: set up JDK 1.8 17 | uses: actions/setup-java@v1 18 | with: 19 | java-version: 1.8 20 | - name: Make Gradle executable 21 | run: chmod +x ./gradlew 22 | - name: Build with Gradle 23 | run: ./gradlew build 24 | - name: Build Debug APK 25 | run: ./gradlew assembleDebug 26 | -------------------------------------------------------------------------------- /spotless.license.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Designed and developed by 2020 skydoves (Jaewoong Eum) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Lines starting with '#' are comments. 2 | # Each line is a file pattern followed by one or more owners. 3 | 4 | # More details are here: https://help.github.com/articles/about-codeowners/ 5 | 6 | # The '*' pattern is global owners. 7 | # Not adding in this PR, but I'd like to try adding a global owner set with the entire team. 8 | # One interpretation of their docs is that global owners are added only if not removed 9 | # by a more local rule. 10 | 11 | # Order is important. The last matching pattern has the most precedence. 12 | # The folders are ordered as follows: 13 | 14 | # In each subsection folders are ordered first by depth, then alphabetically. 15 | # This should make it easy to add new rules without breaking existing ones. 16 | * @skydoves -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Guidelines 2 | Describe the big picture of your changes here to communicate to the maintainers why we should accept this pull request. If it fixes a bug or resolves a feature request, be sure to link to that issue. 3 | 4 | ### Types of changes 5 | What types of changes does your code introduce? 6 | 7 | - [ ] Bugfix (non-breaking change which fixes an issue) 8 | - [ ] New feature (non-breaking change which adds functionality) 9 | - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) 10 | 11 | ### Preparing a pull request for review 12 | Ensure your change is properly formatted by running: 13 | 14 | ```gradle 15 | $ ./gradlew spotlessApply 16 | ``` 17 | 18 | Please correct any failures before requesting a review. -------------------------------------------------------------------------------- /dependencies.gradle: -------------------------------------------------------------------------------- 1 | ext.versions = [ 2 | minSdk : 16, 3 | compileSdk : 30, 4 | versionCode : 4, 5 | versionName : '1.0.3', 6 | 7 | gradleBuildTool : '4.1.1', 8 | spotlessGradle : '5.9.0', 9 | ktlintGradle : '0.41.0', 10 | dokkaGradle : '1.4.30', 11 | mavenPublish : '0.14.2', 12 | 13 | kotlin : '1.4.31', 14 | androidxAppcompat : '1.2.0', 15 | 16 | // unit test 17 | junit : '4.13.1', 18 | androidxTest : '1.3.0', 19 | robolectric : '4.4', 20 | archCompomentVersion: '2.1.0', 21 | mockitoKotlinVersion: '2.2.0', 22 | 23 | // for demo 24 | googleMaterial : '1.3.0-alpha03', 25 | constraintVersion : '2.0.4', 26 | ] 27 | -------------------------------------------------------------------------------- /bundler/src/test/java/com/skydoves/bundler/TestFragment.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Designed and developed by 2020 skydoves (Jaewoong Eum) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.skydoves.bundler 18 | 19 | import androidx.fragment.app.Fragment 20 | 21 | class TestFragment : Fragment() 22 | -------------------------------------------------------------------------------- /app/src/main/res/values/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/values-night/themes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16 | -------------------------------------------------------------------------------- /bundler/src/test/java/com/skydoves/bundler/TestActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Designed and developed by 2020 skydoves (Jaewoong Eum) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.skydoves.bundler 18 | 19 | import androidx.activity.ComponentActivity 20 | 21 | class TestActivity : ComponentActivity() 22 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/skydoves/bundlerdemo/UserInfo.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Designed and developed by 2020 skydoves (Jaewoong Eum) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.skydoves.bundlerdemo 18 | 19 | data class UserInfo( 20 | val id: Long, 21 | val nickname: String 22 | ) { 23 | 24 | companion object { 25 | 26 | fun create() = UserInfo(1000, "skydoves") 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /bundler/src/test/java/com/skydoves/bundler/data/UserInfo.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Designed and developed by 2020 skydoves (Jaewoong Eum) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.skydoves.bundler.data 18 | 19 | data class UserInfo( 20 | val id: Long, 21 | val nickname: String, 22 | val position: String 23 | ) { 24 | companion object { 25 | fun create() = UserInfo(1000, "skydoves", "Android") 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.application' 3 | id 'kotlin-android' 4 | id 'org.jetbrains.kotlin.plugin.parcelize' 5 | } 6 | 7 | apply from: "$rootDir/dependencies.gradle" 8 | 9 | android { 10 | compileSdkVersion versions.compileSdk 11 | defaultConfig { 12 | applicationId "com.skydoves.bundlerdemo" 13 | minSdkVersion versions.minSdk 14 | targetSdkVersion versions.compileSdk 15 | versionCode versions.versionCode 16 | versionName versions.versionName 17 | } 18 | lintOptions { 19 | abortOnError false 20 | } 21 | kotlinOptions { 22 | jvmTarget = '1.8' 23 | } 24 | buildFeatures { 25 | viewBinding true 26 | } 27 | } 28 | 29 | dependencies { 30 | implementation "com.google.android.material:material:$versions.googleMaterial" 31 | implementation "androidx.constraintlayout:constraintlayout:$versions.constraintVersion" 32 | implementation project(":bundler") 33 | } 34 | 35 | apply from: "$rootDir/spotless.gradle" -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # Files for the ART/Dalvik VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # Generated files 12 | bin/ 13 | gen/ 14 | out/ 15 | 16 | # Gradle files 17 | /.idea 18 | .gradle/ 19 | build/ 20 | 21 | # Local configuration file (sdk path, etc) 22 | local.properties 23 | 24 | # Proguard folder generated by Eclipse 25 | proguard/ 26 | 27 | # Log Files 28 | *.log 29 | 30 | # Android Studio Navigation editor temp files 31 | .navigation/ 32 | 33 | # Android Studio captures folder 34 | captures/ 35 | 36 | # Intellij 37 | *.iml 38 | .idea/workspace.xml 39 | .idea/tasks.xml 40 | .idea/gradle.xml 41 | .idea/dictionaries 42 | .idea/libraries 43 | 44 | # Mac 45 | *.DS_Store 46 | 47 | # Keystore files 48 | *.jks 49 | 50 | # External native build folder generated in Android Studio 2.2 and later 51 | .externalNativeBuild 52 | 53 | # Google Services (e.g. APIs or Firebase) 54 | google-services.json 55 | 56 | # Freeline 57 | freeline.py 58 | freeline/ 59 | freeline_project_description.json -------------------------------------------------------------------------------- /bundler/build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'com.android.library' 3 | id 'org.jetbrains.dokka' 4 | id 'kotlin-android' 5 | } 6 | 7 | apply from: "$rootDir/dependencies.gradle" 8 | 9 | android { 10 | compileSdkVersion versions.compileSdk 11 | defaultConfig { 12 | minSdkVersion versions.minSdk 13 | targetSdkVersion versions.compileSdk 14 | versionCode versions.versionCode 15 | versionName versions.versionName 16 | } 17 | kotlinOptions { 18 | jvmTarget = '1.8' 19 | } 20 | buildFeatures { 21 | buildConfig false 22 | } 23 | } 24 | 25 | kotlin { 26 | explicitApi() 27 | } 28 | 29 | tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all { 30 | kotlinOptions.freeCompilerArgs += ["-XXLanguage:+InlineClasses"] 31 | kotlinOptions.freeCompilerArgs += ["-Xopt-in=kotlin.OptIn"] 32 | } 33 | 34 | dependencies { 35 | implementation "androidx.appcompat:appcompat:$versions.androidxAppcompat" 36 | 37 | // unit test 38 | testImplementation "junit:junit:$versions.junit" 39 | testImplementation "androidx.test:core:$versions.androidxTest" 40 | testImplementation "org.robolectric:robolectric:$versions.robolectric" 41 | testImplementation "androidx.arch.core:core-testing:$versions.archCompomentVersion" 42 | testImplementation "com.nhaarman.mockitokotlin2:mockito-kotlin:$versions.mockitoKotlinVersion" 43 | } 44 | 45 | apply plugin: "com.vanniktech.maven.publish" 46 | apply from: '../spotless.gradle' -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/skydoves/bundlerdemo/MainActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Designed and developed by 2020 skydoves (Jaewoong Eum) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.skydoves.bundlerdemo 18 | 19 | import android.os.Bundle 20 | import androidx.appcompat.app.AppCompatActivity 21 | import com.skydoves.bundler.intentOf 22 | 23 | class MainActivity : AppCompatActivity() { 24 | 25 | override fun onCreate(savedInstanceState: Bundle?) { 26 | super.onCreate(savedInstanceState) 27 | setContentView(R.layout.activity_main) 28 | 29 | // generate random instances. 30 | val poster = Poster.create() 31 | val userInfo = UserInfo.create() 32 | 33 | // / start the SecondActivity with intent data. 34 | intentOf { 35 | +("id" to userInfo.id) 36 | +("name" to userInfo.nickname) 37 | "nickName" eq userInfo.nickname 38 | putExtra("poster", poster) 39 | putExtra("posterArray", arrayOf(poster)) 40 | putExtra("posterArrayList", arrayListOf(poster)) 41 | startActivity(this@MainActivity) 42 | } 43 | 44 | // / start the MainFragment with intent data. 45 | supportFragmentManager.beginTransaction() 46 | .replace(R.id.container, MainFragment.create(userInfo, poster)) 47 | .addToBackStack(null) 48 | .commit() 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/skydoves/bundlerdemo/SecondActivity.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Designed and developed by 2020 skydoves (Jaewoong Eum) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.skydoves.bundlerdemo 18 | 19 | import android.os.Bundle 20 | import android.util.Log 21 | import androidx.appcompat.app.AppCompatActivity 22 | import com.skydoves.bundler.bundle 23 | import com.skydoves.bundler.bundleArray 24 | import com.skydoves.bundler.bundleArrayList 25 | import com.skydoves.bundler.bundleValue 26 | 27 | class SecondActivity : AppCompatActivity() { 28 | 29 | private val id: Long by bundle("id", -1) 30 | private val name: String? by bundle("name") 31 | private val poster: Poster? by bundle("poster") 32 | 33 | private val posterArray by bundleArray("posterArray") 34 | private val posterListArray by bundleArrayList("posterArrayList") { arrayListOf(Poster.create()) } 35 | 36 | override fun onCreate(savedInstanceState: Bundle?) { 37 | super.onCreate(savedInstanceState) 38 | setContentView(R.layout.activity_second) 39 | 40 | Log.d(TAG, "id: $id") 41 | Log.d(TAG, "id: ${bundleValue("name", "")}") 42 | Log.d(TAG, "name: $name") 43 | Log.d(TAG, "poster: $poster") 44 | Log.d(TAG, "posterArray: ${posterArray?.get(0)}") 45 | Log.d(TAG, "posterListArray: ${posterListArray?.get(0)}") 46 | } 47 | 48 | companion object { 49 | 50 | private val TAG = SecondActivity::class.java.simpleName 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2020 skydoves (Jaewoong Eum) 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # 16 | 17 | # Jvm environments 18 | org.gradle.jvmargs=-Xmx4g 19 | 20 | # AndroidX 21 | android.useAndroidX=true 22 | 23 | # Required to publish to Nexus 24 | systemProp.org.gradle.internal.publish.checksums.insecure=true 25 | 26 | # Increase timeout when pushing to Sonatype 27 | systemProp.org.gradle.internal.http.connectionTimeout=120000 28 | systemProp.org.gradle.internal.http.socketTimeout=120000 29 | 30 | # Maven 31 | GROUP=com.github.skydoves 32 | POM_PACKAGING=aar 33 | 34 | VERSION_NAME=1.0.5-SNAPSHOT 35 | 36 | POM_ARTIFACT_ID=bundler 37 | POM_NAME=bundler 38 | POM_DESCRIPTION=Android Intent & Bundle extensions that insert and retrieve values elegantly. 39 | 40 | POM_URL=https://github.com/skydoves/bundler/ 41 | POM_SCM_URL=https://github.com/skydoves/bundler/ 42 | POM_SCM_CONNECTION=scm:git:git://github.com/skydoves/bundler.git 43 | POM_SCM_DEV_CONNECTION=scm:git:git://github.com/skydoves/bundler.git 44 | 45 | POM_LICENCE_NAME=The Apache Software License, Version 2.0 46 | POM_LICENCE_URL=http://www.apache.org/licenses/LICENSE-2.0.txt 47 | POM_LICENCE_DIST=repo 48 | 49 | POM_DEVELOPER_ID=skydoves 50 | POM_DEVELOPER_NAME=Jaewoong Eum 51 | POM_DEVELOPER_URL=https://github.com/skydoves/ 52 | 53 | RELEASE_REPOSITORY_URL=https://oss.sonatype.org/service/local/staging/deploy/maven2/ 54 | SNAPSHOT_REPOSITORY_URL=https://oss.sonatype.org/content/repositories/snapshots/ 55 | -------------------------------------------------------------------------------- /app/src/main/java/com/skydoves/bundlerdemo/MainFragment.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Designed and developed by 2020 skydoves (Jaewoong Eum) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.skydoves.bundlerdemo 18 | 19 | import android.os.Bundle 20 | import android.util.Log 21 | import android.view.LayoutInflater 22 | import android.view.View 23 | import android.view.ViewGroup 24 | import androidx.fragment.app.Fragment 25 | import com.skydoves.bundler.bundle 26 | import com.skydoves.bundler.intentOf 27 | 28 | class MainFragment : Fragment() { 29 | 30 | private val id: Long by bundle("id", -1) 31 | private val name: String by bundle("name", "") 32 | private val poster: Poster? by bundle("poster") 33 | 34 | override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { 35 | val view = inflater.inflate(R.layout.activity_main, container, false) 36 | return view.rootView 37 | } 38 | 39 | override fun onViewCreated(view: View, savedInstanceState: Bundle?) { 40 | super.onViewCreated(view, savedInstanceState) 41 | 42 | Log.d(TAG, "id: $id") 43 | Log.d(TAG, "name: $name") 44 | Log.d(TAG, "poster: $poster") 45 | } 46 | 47 | companion object { 48 | 49 | private val TAG = MainFragment::class.java.simpleName 50 | 51 | fun create(userInfo: UserInfo, poster: Poster): MainFragment { 52 | return MainFragment().apply { 53 | arguments = intentOf { 54 | +("id" to userInfo.id) 55 | +("name" to userInfo.nickname) 56 | +("poster" to poster) 57 | }.extras 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /bundler/src/test/java/com/skydoves/bundler/data/PosterSerializable.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Designed and developed by 2020 skydoves (Jaewoong Eum) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.skydoves.bundler.data 18 | 19 | import java.io.Serializable 20 | 21 | data class PosterSerializable( 22 | val id: Long, 23 | val name: String?, 24 | val release: String?, 25 | val playtime: String?, 26 | val description: String?, 27 | val plot: String?, 28 | val poster: String? 29 | ) : Serializable { 30 | 31 | companion object { 32 | fun create() = PosterSerializable( 33 | id = 0, 34 | name = "Frozen II", 35 | release = "2019", 36 | playtime = "1 h 43 min", 37 | description = "Frozen II, also known as Frozen 2, is a 2019 American 3D computer-animated musical fantasy film produced by Walt Disney Animation Studios. The 58th animated film produced by the studio, it is the sequel to the 2013 film Frozen and features the return of directors Chris Buck and Jennifer Lee, producer Peter Del Vecho, songwriters Kristen Anderson-Lopez and Robert Lopez, and composer Christophe Beck. Lee also returns as screenwriter, penning the screenplay from a story by her, Buck, Marc E. Smith, Anderson-Lopez, and Lopez,[2] while Byron Howard executive-produced the film.[a][1] Veteran voice cast Kristen Bell, Idina Menzel, Josh Gad, Jonathan Groff, and Ciarán Hinds return as their previous characters, and they are joined by newcomers Sterling K. Brown, Evan Rachel Wood, Alfred Molina, Martha Plimpton, Jason Ritter, Rachel Matthews, and Jeremy Sisto.", 38 | plot = "King Agnarr of Arendelle tells a story to his young children, Elsa and Anna, that their grandfather, King Runeard, established a treaty with the neighboring tribe of Northuldra by building a dam in their homeland, the Enchanted Forest. However, a fight occurs, resulting in Runeard's death. The battle enrages the elemental spirits of Earth, Fire, Water, and Air of the forest. The spirits disappear and a wall of mist traps everyone in the Enchanted Forest. Young Agnarr barely escapes due to the help of an unknown savior.", 39 | poster = "https://user-images.githubusercontent.com/24237865/75087936-5c1d9f80-553e-11ea-81d3-a912634dd8f7.jpg" 40 | ) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/skydoves/bundlerdemo/Poster.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Designed and developed by 2020 skydoves (Jaewoong Eum) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.skydoves.bundlerdemo 18 | 19 | import android.os.Parcelable 20 | import kotlinx.parcelize.Parcelize 21 | 22 | @Parcelize 23 | data class Poster( 24 | val id: Long, 25 | val name: String, 26 | val release: String, 27 | val playtime: String, 28 | val description: String, 29 | val plot: String, 30 | val poster: String 31 | ) : Parcelable { 32 | 33 | companion object { 34 | 35 | fun create() = Poster( 36 | id = 0, 37 | name = "Frozen II", 38 | release = "2019", 39 | playtime = "1 h 43 min", 40 | description = "Frozen II, also known as Frozen 2, is a 2019 American 3D computer-animated musical fantasy film produced by Walt Disney Animation Studios. The 58th animated film produced by the studio, it is the sequel to the 2013 film Frozen and features the return of directors Chris Buck and Jennifer Lee, producer Peter Del Vecho, songwriters Kristen Anderson-Lopez and Robert Lopez, and composer Christophe Beck. Lee also returns as screenwriter, penning the screenplay from a story by her, Buck, Marc E. Smith, Anderson-Lopez, and Lopez,[2] while Byron Howard executive-produced the film.[a][1] Veteran voice cast Kristen Bell, Idina Menzel, Josh Gad, Jonathan Groff, and Ciarán Hinds return as their previous characters, and they are joined by newcomers Sterling K. Brown, Evan Rachel Wood, Alfred Molina, Martha Plimpton, Jason Ritter, Rachel Matthews, and Jeremy Sisto.", 41 | plot = "King Agnarr of Arendelle tells a story to his young children, Elsa and Anna, that their grandfather, King Runeard, established a treaty with the neighboring tribe of Northuldra by building a dam in their homeland, the Enchanted Forest. However, a fight occurs, resulting in Runeard's death. The battle enrages the elemental spirits of Earth, Fire, Water, and Air of the forest. The spirits disappear and a wall of mist traps everyone in the Enchanted Forest. Young Agnarr barely escapes due to the help of an unknown savior.", 42 | poster = "https://user-images.githubusercontent.com/24237865/75087936-5c1d9f80-553e-11ea-81d3-a912634dd8f7.jpg" 43 | ) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /bundler/src/main/java/com/skydoves/bundler/SingleShotLiveData.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Designed and developed by 2020 skydoves (Jaewoong Eum) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.skydoves.bundler 18 | 19 | import android.util.Log 20 | import androidx.annotation.MainThread 21 | import androidx.lifecycle.LifecycleOwner 22 | import androidx.lifecycle.MutableLiveData 23 | import androidx.lifecycle.Observer 24 | import java.util.concurrent.atomic.AtomicBoolean 25 | 26 | /** 27 | * @author skydoves (Jaewoong Eum) 28 | * 29 | * SingleShotLiveData is an implementation of the [MutableLiveData] that emits [T] data 30 | * only a single time to a single observer. We can observe only once using one observer. 31 | * And the observer will be unregistered from the [SingleShotLiveData] after observing data at once. 32 | */ 33 | @PublishedApi 34 | internal class SingleShotLiveData constructor( 35 | initialValue: T? = null 36 | ) : MutableLiveData() { 37 | 38 | private val emitted = AtomicBoolean(false) 39 | 40 | init { 41 | value = initialValue 42 | } 43 | 44 | @MainThread 45 | override fun observe(owner: LifecycleOwner, observer: Observer) { 46 | if (emitted.compareAndSet(false, true)) { 47 | super.observe( 48 | owner, 49 | { 50 | observer.onChanged(it) 51 | removeObserver(observer) 52 | } 53 | ) 54 | } else { 55 | Log.i(TAG, "SingleShotLiveData already has been emitted data.") 56 | } 57 | } 58 | 59 | @MainThread 60 | override fun observeForever(observer: Observer) { 61 | if (emitted.compareAndSet(false, true)) { 62 | super.observeForever { 63 | observer.onChanged(it) 64 | removeObserver(observer) 65 | } 66 | } else { 67 | Log.i(TAG, "SingleShotLiveData already has been emitted data.") 68 | } 69 | } 70 | 71 | @MainThread 72 | override fun setValue(value: T?) { 73 | if (!emitted.get()) { 74 | super.setValue(value) 75 | } else { 76 | Log.i(TAG, "SingleShotLiveData already has been emitted data.") 77 | } 78 | } 79 | 80 | override fun postValue(value: T?) { 81 | if (!emitted.get()) { 82 | super.postValue(value) 83 | } else { 84 | Log.i(TAG, "SingleShotLiveData already has been emitted data.") 85 | } 86 | } 87 | 88 | companion object { 89 | private const val TAG = "SingleShotLiveData" 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /bundler/src/test/java/com/skydoves/bundler/IntentLiveDataProviderTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Designed and developed by 2020 skydoves (Jaewoong Eum) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.skydoves.bundler 18 | 19 | import androidx.lifecycle.Observer 20 | import com.nhaarman.mockitokotlin2.mock 21 | import com.nhaarman.mockitokotlin2.verify 22 | import com.skydoves.bundler.IntentLiveDataProvider.provideArrayIntentLiveData 23 | import com.skydoves.bundler.IntentLiveDataProvider.provideArrayListIntentLiveData 24 | import com.skydoves.bundler.IntentLiveDataProvider.provideIntentLiveData 25 | import com.skydoves.bundler.data.Poster 26 | import org.hamcrest.CoreMatchers.`is` 27 | import org.hamcrest.MatcherAssert.assertThat 28 | import org.junit.Test 29 | import org.junit.runner.RunWith 30 | import org.robolectric.RobolectricTestRunner 31 | import org.robolectric.annotation.Config 32 | 33 | @Config(sdk = [21]) 34 | @RunWith(RobolectricTestRunner::class) 35 | class IntentLiveDataProviderTest { 36 | 37 | @Test 38 | fun provideIntentLiveDataTest() { 39 | val intLiveData = provideIntentLiveData { 123 } 40 | 41 | val intObserver = mock>() 42 | intLiveData.observeForever(intObserver) 43 | 44 | verify(intObserver).onChanged(123) 45 | 46 | val poster = Poster.create() 47 | val posterLiveData = provideIntentLiveData { poster } 48 | 49 | val posterObserver = mock>() 50 | posterLiveData.observeForever(posterObserver) 51 | 52 | verify(posterObserver).onChanged(poster) 53 | } 54 | 55 | @Test 56 | fun provideArrayIntentLiveDataTest() { 57 | val posterArrayLiveData = provideArrayIntentLiveData { 58 | arrayOf(Poster.create(), Poster.create()) 59 | } 60 | 61 | assertThat(posterArrayLiveData.value?.size, `is`(2)) 62 | 63 | val observer = mock>>() 64 | posterArrayLiveData.observeForever(observer) 65 | 66 | verify(observer).onChanged(arrayOf(Poster.create(), Poster.create())) 67 | } 68 | 69 | @Test 70 | fun provideArrayListIntentLiveDataTest() { 71 | val posterArrayListLiveData = provideArrayListIntentLiveData { 72 | arrayListOf(Poster.create(), Poster.create()) 73 | } 74 | 75 | assertThat(posterArrayListLiveData.value?.size, `is`(2)) 76 | 77 | val observer = mock>>() 78 | posterArrayListLiveData.observeForever(observer) 79 | 80 | verify(observer).onChanged(arrayListOf(Poster.create(), Poster.create())) 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /bundler/src/main/java/com/skydoves/bundler/IntentLiveDataProvider.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Designed and developed by 2020 skydoves (Jaewoong Eum) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.skydoves.bundler 18 | 19 | import androidx.annotation.MainThread 20 | import androidx.lifecycle.LiveData 21 | 22 | /** 23 | * @author skydoves (Jaewoong Eum) 24 | * 25 | * A provider for providing [LiveData] which has the desired intent data. 26 | */ 27 | @PublishedApi 28 | internal object IntentLiveDataProvider { 29 | 30 | /** 31 | * Provide a [LiveData] which has a primitive and references type of extended data from intent. 32 | * The implementation of the [LiveData] is a [SingleShotLiveData] that emits data only a single time to 33 | * a single observer. We can observe only once using one observer. And the observer will be unregistered 34 | * from the [SingleShotLiveData] after observing data at once. 35 | * 36 | * @param initialValue An initial value for a new [LiveData]. 37 | */ 38 | @MainThread 39 | @PublishedApi 40 | internal inline fun provideIntentLiveData( 41 | crossinline initialValue: () -> T? 42 | ): LiveData { 43 | return SingleShotLiveData(initialValue()) 44 | } 45 | 46 | /** 47 | * Provide a [LiveData] which has a references array type of extended data from intent. 48 | * The implementation of the [LiveData] is a [SingleShotLiveData] that emits data only a single time to 49 | * a single observer. We can observe only once using one observer. And the observer will be unregistered 50 | * from the [SingleShotLiveData] after observing data at once. 51 | * 52 | * @param initialValue An initial value for a new [LiveData]. 53 | */ 54 | @MainThread 55 | @PublishedApi 56 | internal inline fun provideArrayIntentLiveData( 57 | crossinline initialValue: () -> Array? 58 | ): LiveData> { 59 | return SingleShotLiveData>(initialValue()) 60 | } 61 | 62 | /** 63 | * Provide a [LiveData] which has a references array list type of extended data from intent. 64 | * The implementation of the [LiveData] is a [SingleShotLiveData] that emits data only a single time to 65 | * a single observer. We can observe only once using one observer. And the observer will be unregistered 66 | * from the [SingleShotLiveData] after observing data at once. 67 | * 68 | * @param initialValue An initial value for a new [LiveData]. 69 | */ 70 | @MainThread 71 | @PublishedApi 72 | internal inline fun provideArrayListIntentLiveData( 73 | crossinline initialValue: () -> ArrayList? 74 | ): LiveData> { 75 | return SingleShotLiveData>(initialValue()) 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto init 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto init 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :init 68 | @rem Get command-line arguments, handling Windows variants 69 | 70 | if not "%OS%" == "Windows_NT" goto win9xME_args 71 | 72 | :win9xME_args 73 | @rem Slurp the command line arguments. 74 | set CMD_LINE_ARGS= 75 | set _SKIP=2 76 | 77 | :win9xME_args_slurp 78 | if "x%~1" == "x" goto execute 79 | 80 | set CMD_LINE_ARGS=%* 81 | 82 | :execute 83 | @rem Setup the command line 84 | 85 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 86 | 87 | 88 | @rem Execute Gradle 89 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 90 | 91 | :end 92 | @rem End local scope for the variables with windows NT shell 93 | if "%ERRORLEVEL%"=="0" goto mainEnd 94 | 95 | :fail 96 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 97 | rem the _cmd.exe /c_ return code! 98 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 99 | exit /b 1 100 | 101 | :mainEnd 102 | if "%OS%"=="Windows_NT" endlocal 103 | 104 | :omega 105 | -------------------------------------------------------------------------------- /bundler/src/test/java/com/skydoves/bundler/data/Poster.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Designed and developed by 2020 skydoves (Jaewoong Eum) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.skydoves.bundler.data 18 | 19 | import android.os.Parcel 20 | import android.os.Parcelable 21 | 22 | data class Poster( 23 | val id: Long, 24 | val name: String?, 25 | val release: String?, 26 | val playtime: String?, 27 | val description: String?, 28 | val plot: String?, 29 | val poster: String? 30 | ) : Parcelable { 31 | 32 | constructor(parcel: Parcel) : this( 33 | parcel.readLong(), 34 | parcel.readString(), 35 | parcel.readString(), 36 | parcel.readString(), 37 | parcel.readString(), 38 | parcel.readString(), 39 | parcel.readString() 40 | ) 41 | 42 | override fun writeToParcel(parcel: Parcel, flags: Int) { 43 | parcel.writeLong(id) 44 | parcel.writeString(name) 45 | parcel.writeString(release) 46 | parcel.writeString(playtime) 47 | parcel.writeString(description) 48 | parcel.writeString(plot) 49 | parcel.writeString(poster) 50 | } 51 | 52 | override fun describeContents() = 0 53 | 54 | companion object CREATOR : Parcelable.Creator { 55 | override fun createFromParcel(parcel: Parcel): Poster { 56 | return Poster(parcel) 57 | } 58 | 59 | override fun newArray(size: Int): Array { 60 | return arrayOfNulls(size) 61 | } 62 | 63 | fun create() = Poster( 64 | id = 0, 65 | name = "Frozen II", 66 | release = "2019", 67 | playtime = "1 h 43 min", 68 | description = "Frozen II, also known as Frozen 2, is a 2019 American 3D computer-animated musical fantasy film produced by Walt Disney Animation Studios. The 58th animated film produced by the studio, it is the sequel to the 2013 film Frozen and features the return of directors Chris Buck and Jennifer Lee, producer Peter Del Vecho, songwriters Kristen Anderson-Lopez and Robert Lopez, and composer Christophe Beck. Lee also returns as screenwriter, penning the screenplay from a story by her, Buck, Marc E. Smith, Anderson-Lopez, and Lopez,[2] while Byron Howard executive-produced the film.[a][1] Veteran voice cast Kristen Bell, Idina Menzel, Josh Gad, Jonathan Groff, and Ciarán Hinds return as their previous characters, and they are joined by newcomers Sterling K. Brown, Evan Rachel Wood, Alfred Molina, Martha Plimpton, Jason Ritter, Rachel Matthews, and Jeremy Sisto.", 69 | plot = "King Agnarr of Arendelle tells a story to his young children, Elsa and Anna, that their grandfather, King Runeard, established a treaty with the neighboring tribe of Northuldra by building a dam in their homeland, the Enchanted Forest. However, a fight occurs, resulting in Runeard's death. The battle enrages the elemental spirits of Earth, Fire, Water, and Air of the forest. The spirits disappear and a wall of mist traps everyone in the Enchanted Forest. Young Agnarr barely escapes due to the help of an unknown savior.", 70 | poster = "https://user-images.githubusercontent.com/24237865/75087936-5c1d9f80-553e-11ea-81d3-a912634dd8f7.jpg" 71 | ) 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /bundler/src/test/java/com/skydoves/bundler/SingleShotLiveDataTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Designed and developed by 2020 skydoves (Jaewoong Eum) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.skydoves.bundler 18 | 19 | import androidx.arch.core.executor.testing.InstantTaskExecutorRule 20 | import androidx.lifecycle.Observer 21 | import com.nhaarman.mockitokotlin2.mock 22 | import com.nhaarman.mockitokotlin2.verify 23 | import com.nhaarman.mockitokotlin2.verifyNoMoreInteractions 24 | import org.hamcrest.MatcherAssert.assertThat 25 | import org.hamcrest.core.Is.`is` 26 | import org.junit.Rule 27 | import org.junit.Test 28 | import org.junit.runner.RunWith 29 | import org.robolectric.RobolectricTestRunner 30 | import org.robolectric.annotation.Config 31 | 32 | @Config(sdk = [21]) 33 | @RunWith(RobolectricTestRunner::class) 34 | class SingleShotLiveDataTest { 35 | 36 | @get:Rule 37 | var instantExecutorRule = InstantTaskExecutorRule() 38 | 39 | @Test 40 | fun observeTest() { 41 | val oneShotLiveData = SingleShotLiveData("one") 42 | 43 | val observer = mock>() 44 | oneShotLiveData.observeForever(observer) 45 | 46 | verify(observer).onChanged("one") 47 | 48 | oneShotLiveData.setValue("two") 49 | 50 | verifyNoMoreInteractions(observer) 51 | } 52 | 53 | @Test 54 | fun observeWithMultipleObserversTest() { 55 | val oneShotLiveData = SingleShotLiveData("one") 56 | 57 | val observer0 = mock>() 58 | oneShotLiveData.observeForever(observer0) 59 | 60 | val observer1 = mock>() 61 | oneShotLiveData.observeForever(observer1) 62 | 63 | verify(observer0).onChanged("one") 64 | verifyNoMoreInteractions(observer1) 65 | 66 | oneShotLiveData.setValue("two") 67 | 68 | verifyNoMoreInteractions(observer0) 69 | verifyNoMoreInteractions(observer1) 70 | } 71 | 72 | @Test 73 | fun setValueTest() { 74 | val oneShotLiveData = SingleShotLiveData("one") 75 | assertThat(oneShotLiveData.value, `is`("one")) 76 | 77 | oneShotLiveData.setValue("two") 78 | assertThat(oneShotLiveData.value, `is`("two")) 79 | 80 | oneShotLiveData.setValue("three") 81 | assertThat(oneShotLiveData.value, `is`("three")) 82 | 83 | val observer = mock>() 84 | oneShotLiveData.observeForever(observer) 85 | 86 | verify(observer).onChanged("three") 87 | 88 | oneShotLiveData.setValue("four") 89 | verifyNoMoreInteractions(observer) 90 | } 91 | 92 | @Test 93 | fun postValueTest() { 94 | val oneShotLiveData = SingleShotLiveData("one") 95 | assertThat(oneShotLiveData.value, `is`("one")) 96 | 97 | oneShotLiveData.postValue("two") 98 | assertThat(oneShotLiveData.value, `is`("two")) 99 | 100 | oneShotLiveData.postValue("three") 101 | assertThat(oneShotLiveData.value, `is`("three")) 102 | 103 | val observer = mock>() 104 | oneShotLiveData.observeForever(observer) 105 | 106 | verify(observer).onChanged("three") 107 | 108 | oneShotLiveData.postValue("four") 109 | verifyNoMoreInteractions(observer) 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /bundler/src/main/java/com/skydoves/bundler/BundleOf.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Designed and developed by 2020 skydoves (Jaewoong Eum) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.skydoves.bundler 18 | 19 | /* 20 | * Copyright (C) 2018 The Android Open Source Project 21 | * 22 | * Licensed under the Apache License, Version 2.0 (the "License"); 23 | * you may not use this file except in compliance with the License. 24 | * You may obtain a copy of the License at 25 | * 26 | * http://www.apache.org/licenses/LICENSE-2.0 27 | * 28 | * Unless required by applicable law or agreed to in writing, software 29 | * distributed under the License is distributed on an "AS IS" BASIS, 30 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 31 | * See the License for the specific language governing permissions and 32 | * limitations under the License. 33 | */ 34 | 35 | import android.os.Build 36 | import android.os.Bundle 37 | import android.os.IBinder 38 | import android.os.Parcelable 39 | import android.util.Size 40 | import android.util.SizeF 41 | import java.io.Serializable 42 | 43 | /** 44 | * Returns a new [Bundle] with the given key/value pairs as elements. 45 | * 46 | * @throws IllegalArgumentException When a value is not a supported type of [Bundle]. 47 | */ 48 | internal fun bundleOf(vararg pairs: Pair) = Bundle(pairs.size).apply { 49 | for ((key, value) in pairs) { 50 | when (value) { 51 | null -> putString(key, null) // Any nullable type will suffice. 52 | 53 | // Scalars 54 | is Boolean -> putBoolean(key, value) 55 | is Byte -> putByte(key, value) 56 | is Char -> putChar(key, value) 57 | is Double -> putDouble(key, value) 58 | is Float -> putFloat(key, value) 59 | is Int -> putInt(key, value) 60 | is Long -> putLong(key, value) 61 | is Short -> putShort(key, value) 62 | 63 | // References 64 | is Bundle -> putBundle(key, value) 65 | is CharSequence -> putCharSequence(key, value) 66 | is Parcelable -> putParcelable(key, value) 67 | 68 | // Scalar arrays 69 | is BooleanArray -> putBooleanArray(key, value) 70 | is ByteArray -> putByteArray(key, value) 71 | is CharArray -> putCharArray(key, value) 72 | is DoubleArray -> putDoubleArray(key, value) 73 | is FloatArray -> putFloatArray(key, value) 74 | is IntArray -> putIntArray(key, value) 75 | is LongArray -> putLongArray(key, value) 76 | is ShortArray -> putShortArray(key, value) 77 | 78 | // Reference arrays 79 | is Array<*> -> { 80 | val componentType = value::class.java.componentType!! 81 | @Suppress("UNCHECKED_CAST") // Checked by reflection. 82 | when { 83 | Parcelable::class.java.isAssignableFrom(componentType) -> { 84 | putParcelableArray(key, value as Array) 85 | } 86 | String::class.java.isAssignableFrom(componentType) -> { 87 | putStringArray(key, value as Array) 88 | } 89 | CharSequence::class.java.isAssignableFrom(componentType) -> { 90 | putCharSequenceArray(key, value as Array) 91 | } 92 | Serializable::class.java.isAssignableFrom(componentType) -> { 93 | putSerializable(key, value) 94 | } 95 | else -> { 96 | val valueType = componentType.canonicalName 97 | throw IllegalArgumentException( 98 | "Illegal value array type $valueType for key \"$key\"" 99 | ) 100 | } 101 | } 102 | } 103 | 104 | // Last resort. Also we must check this after Array<*> as all arrays are serializable. 105 | is Serializable -> putSerializable(key, value) 106 | 107 | else -> { 108 | if (Build.VERSION.SDK_INT >= 18 && value is IBinder) { 109 | putBinder(key, value) 110 | } else if (Build.VERSION.SDK_INT >= 21 && value is Size) { 111 | putSize(key, value) 112 | } else if (Build.VERSION.SDK_INT >= 21 && value is SizeF) { 113 | putSizeF(key, value) 114 | } else { 115 | val valueType = value.javaClass.canonicalName 116 | throw IllegalArgumentException("Illegal value type $valueType for key \"$key\"") 117 | } 118 | } 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /bundler/src/main/java/com/skydoves/bundler/ActivityBundleObserveLazy.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Designed and developed by 2020 skydoves (Jaewoong Eum) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.skydoves.bundler 18 | 19 | import android.app.Activity 20 | import androidx.lifecycle.LiveData 21 | import com.skydoves.bundler.IntentLiveDataProvider.provideArrayIntentLiveData 22 | import com.skydoves.bundler.IntentLiveDataProvider.provideArrayListIntentLiveData 23 | import com.skydoves.bundler.IntentLiveDataProvider.provideIntentLiveData 24 | 25 | /** 26 | * @author skydoves (Jaewoong Eum) 27 | * 28 | * Returns a [LiveData] which has a retrieved primitive type of extended data from the Intent. 29 | * The implementation of the [LiveData] is a [SingleShotLiveData] that emits data only a single time to 30 | * a single observer. We can observe only once using one observer. And the observer will be unregistered 31 | * from the [SingleShotLiveData] after observing data at once. 32 | * 33 | * @param key The name of the desired item. 34 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 35 | */ 36 | @JvmSynthetic 37 | @InlineBundleDsl 38 | inline fun Activity.observeBundle( 39 | key: String, 40 | defaultValue: T 41 | ): Lazy> { 42 | return lazy(LazyThreadSafetyMode.NONE) { 43 | val initialValue by bundle(key, defaultValue) 44 | provideIntentLiveData { 45 | initialValue 46 | } 47 | } 48 | } 49 | 50 | /** 51 | * @author skydoves (Jaewoong Eum) 52 | * 53 | * Returns a [LiveData] which has a references primitive type of extended data from the Intent. 54 | * The implementation of the [LiveData] is a [SingleShotLiveData] that emits data only a single time to 55 | * a single observer. We can observe only once using one observer. And the observer will be unregistered 56 | * from the [SingleShotLiveData] after observing data at once. 57 | * 58 | * @param key The name of the desired item. 59 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 60 | */ 61 | @JvmSynthetic 62 | @InlineBundleDsl 63 | inline fun Activity.observeBundle( 64 | key: String, 65 | crossinline defaultValue: () -> T? = { null } 66 | ): Lazy> { 67 | return lazy(LazyThreadSafetyMode.NONE) { 68 | val initialValue by bundle(key, defaultValue) 69 | provideIntentLiveData { 70 | initialValue 71 | } 72 | } 73 | } 74 | 75 | /** 76 | * @author skydoves (Jaewoong Eum) 77 | * 78 | * Returns a [LiveData] which has a references array type of extended data from the Intent. 79 | * The implementation of the [LiveData] is a [SingleShotLiveData] that emits data only a single time to 80 | * a single observer. We can observe only once using one observer. And the observer will be unregistered 81 | * from the [SingleShotLiveData] after observing data at once. 82 | * 83 | * @param key The name of the desired item. 84 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 85 | */ 86 | @JvmSynthetic 87 | @InlineBundleDsl 88 | inline fun Activity.observeBundleArray( 89 | key: String, 90 | crossinline defaultValue: () -> Array? = { null } 91 | ): Lazy>> { 92 | return lazy(LazyThreadSafetyMode.NONE) { 93 | val initialValue by bundleArray(key, defaultValue) 94 | provideArrayIntentLiveData { 95 | initialValue 96 | } 97 | } 98 | } 99 | 100 | /** 101 | * @author skydoves (Jaewoong Eum) 102 | * 103 | * Returns a [LiveData] which has a references array list type of extended data from the Intent. 104 | * The implementation of the [LiveData] is a [SingleShotLiveData] that emits data only a single time to 105 | * a single observer. We can observe only once using one observer. And the observer will be unregistered 106 | * from the [SingleShotLiveData] after observing data at once. 107 | * 108 | * @param key The name of the desired item. 109 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 110 | */ 111 | @JvmSynthetic 112 | @InlineBundleDsl 113 | inline fun Activity.observeBundleArrayList( 114 | key: String, 115 | crossinline defaultValue: () -> ArrayList? = { null } 116 | ): Lazy>> { 117 | return lazy(LazyThreadSafetyMode.NONE) { 118 | val initialValue by bundleArrayList(key, defaultValue) 119 | provideArrayListIntentLiveData { 120 | initialValue 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /bundler/src/main/java/com/skydoves/bundler/FragmentBundleObserveLazy.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Designed and developed by 2020 skydoves (Jaewoong Eum) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.skydoves.bundler 18 | 19 | import androidx.fragment.app.Fragment 20 | import androidx.lifecycle.LiveData 21 | import com.skydoves.bundler.IntentLiveDataProvider.provideArrayIntentLiveData 22 | import com.skydoves.bundler.IntentLiveDataProvider.provideArrayListIntentLiveData 23 | import com.skydoves.bundler.IntentLiveDataProvider.provideIntentLiveData 24 | 25 | /** 26 | * @author skydoves (Jaewoong Eum) 27 | * 28 | * Returns a [LiveData] which has a retrieved primitive type of extended data from the arguments. 29 | * The implementation of the [LiveData] is a [SingleShotLiveData] that emits data only a single time to 30 | * a single observer. We can observe only once using one observer. And the observer will be unregistered 31 | * from the [SingleShotLiveData] after observing data at once. 32 | * 33 | * @param key The name of the desired item. 34 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 35 | */ 36 | @JvmSynthetic 37 | @InlineBundleDsl 38 | inline fun Fragment.observeBundle( 39 | key: String, 40 | defaultValue: T 41 | ): Lazy> { 42 | return lazy(LazyThreadSafetyMode.NONE) { 43 | val initialValue by bundle(key, defaultValue) 44 | provideIntentLiveData { 45 | initialValue 46 | } 47 | } 48 | } 49 | 50 | /** 51 | * @author skydoves (Jaewoong Eum) 52 | * 53 | * Returns a [LiveData] which has a references primitive type of extended data from the arguments. 54 | * The implementation of the [LiveData] is a [SingleShotLiveData] that emits data only a single time to 55 | * a single observer. We can observe only once using one observer. And the observer will be unregistered 56 | * from the [SingleShotLiveData] after observing data at once. 57 | * 58 | * @param key The name of the desired item. 59 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 60 | */ 61 | @JvmSynthetic 62 | @InlineBundleDsl 63 | inline fun Fragment.observeBundle( 64 | key: String, 65 | crossinline defaultValue: () -> T? = { null } 66 | ): Lazy> { 67 | return lazy(LazyThreadSafetyMode.NONE) { 68 | val initialValue by bundle(key, defaultValue) 69 | provideIntentLiveData { 70 | initialValue 71 | } 72 | } 73 | } 74 | 75 | /** 76 | * @author skydoves (Jaewoong Eum) 77 | * 78 | * Returns a [LiveData] which has a references array type of extended data from the arguments. 79 | * The implementation of the [LiveData] is a [SingleShotLiveData] that emits data only a single time to 80 | * a single observer. We can observe only once using one observer. And the observer will be unregistered 81 | * from the [SingleShotLiveData] after observing data at once. 82 | * 83 | * @param key The name of the desired item. 84 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 85 | */ 86 | @JvmSynthetic 87 | @InlineBundleDsl 88 | inline fun Fragment.observeBundleArray( 89 | key: String, 90 | crossinline defaultValue: () -> Array? = { null } 91 | ): Lazy>> { 92 | return lazy(LazyThreadSafetyMode.NONE) { 93 | val initialValue by bundleArray(key, defaultValue) 94 | provideArrayIntentLiveData { 95 | initialValue 96 | } 97 | } 98 | } 99 | 100 | /** 101 | * @author skydoves (Jaewoong Eum) 102 | * 103 | * Returns a [LiveData] which has a references array list type of extended data from the arguments. 104 | * The implementation of the [LiveData] is a [SingleShotLiveData] that emits data only a single time to 105 | * a single observer. We can observe only once using one observer. And the observer will be unregistered 106 | * from the [SingleShotLiveData] after observing data at once. 107 | * 108 | * @param key The name of the desired item. 109 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 110 | */ 111 | @JvmSynthetic 112 | @InlineBundleDsl 113 | inline fun Fragment.observeBundleArrayList( 114 | key: String, 115 | crossinline defaultValue: () -> ArrayList? = { null } 116 | ): Lazy>> { 117 | return lazy(LazyThreadSafetyMode.NONE) { 118 | val initialValue by bundleArrayList(key, defaultValue) 119 | provideArrayListIntentLiveData { 120 | initialValue 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /bundler/src/test/java/com/skydoves/bundler/FragmentBundleObserveLazyTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Designed and developed by 2020 skydoves (Jaewoong Eum) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.skydoves.bundler 18 | 19 | import androidx.lifecycle.Observer 20 | import com.nhaarman.mockitokotlin2.mock 21 | import com.nhaarman.mockitokotlin2.verify 22 | import com.nhaarman.mockitokotlin2.verifyNoMoreInteractions 23 | import com.skydoves.bundler.data.Poster 24 | import org.hamcrest.CoreMatchers 25 | import org.hamcrest.MatcherAssert 26 | import org.junit.Test 27 | import org.junit.runner.RunWith 28 | import org.robolectric.RobolectricTestRunner 29 | import org.robolectric.annotation.Config 30 | 31 | @Config(sdk = [21]) 32 | @RunWith(RobolectricTestRunner::class) 33 | class FragmentBundleObserveLazyTest { 34 | 35 | @Test 36 | fun observeBundleLazyTest() { 37 | val fragment = TestFragment() 38 | fragment.arguments = intentOf { 39 | putExtra("int", 123) 40 | }.extras 41 | 42 | val intLiveData by fragment.observeBundle("int", 0) 43 | 44 | val intObserver = mock>() 45 | intLiveData.observeForever(intObserver) 46 | 47 | verify(intObserver).onChanged(123) 48 | } 49 | 50 | @Test 51 | fun observeBundleLazyTwiceTest() { 52 | val fragment = TestFragment() 53 | fragment.arguments = intentOf { 54 | putExtra("int", 123) 55 | }.extras 56 | 57 | val intLiveData by fragment.observeBundle("int", 0) 58 | 59 | val intObserver0 = mock>() 60 | intLiveData.observeForever(intObserver0) 61 | 62 | verify(intObserver0).onChanged(123) 63 | 64 | val intObserver1 = mock>() 65 | intLiveData.observeForever(intObserver1) 66 | 67 | verifyNoMoreInteractions(intObserver1) 68 | } 69 | 70 | @Test 71 | fun observeBundleLazyDefaultValueTest() { 72 | val fragment = TestFragment() 73 | 74 | val intLiveData by fragment.observeBundle("int", 123) 75 | 76 | val observer = mock>() 77 | intLiveData.observeForever(observer) 78 | 79 | verify(observer).onChanged(123) 80 | } 81 | 82 | fun observeBundleReferenceLazyTest() { 83 | val activity = TestActivity() 84 | activity.intent = intentOf { 85 | putExtra("poster", Poster.create()) 86 | } 87 | 88 | val posterLiveData by activity.observeBundle("poster") 89 | 90 | val posterObserver = mock>() 91 | posterLiveData.observeForever(posterObserver) 92 | 93 | verify(posterObserver).onChanged(Poster.create()) 94 | } 95 | 96 | @Test 97 | fun observeBundleLazyNullTest() { 98 | val fragment = TestFragment() 99 | 100 | val posterLiveData by fragment.observeBundle("poster") 101 | 102 | val posterObserver = mock>() 103 | posterLiveData.observeForever(posterObserver) 104 | 105 | verify(posterObserver).onChanged(null) 106 | } 107 | 108 | @Test 109 | fun observeBundleArrayLazyTest() { 110 | val fragment = TestFragment() 111 | fragment.arguments = intentOf { 112 | putExtra("posterArray", arrayOf(Poster.create(), Poster.create())) 113 | }.extras 114 | val posterArrayLiveData by fragment.observeBundleArray("posterArray") 115 | 116 | MatcherAssert.assertThat(posterArrayLiveData.value?.size, CoreMatchers.`is`(2)) 117 | 118 | val observer = mock>>() 119 | posterArrayLiveData.observeForever(observer) 120 | 121 | verify(observer).onChanged(arrayOf(Poster.create(), Poster.create())) 122 | } 123 | 124 | @Test 125 | fun observeBundleArrayLazyNullTest() { 126 | val fragment = TestFragment() 127 | 128 | val posterArrayLiveData by fragment.observeBundleArray("posterArray") 129 | 130 | val observer = mock>>() 131 | posterArrayLiveData.observeForever(observer) 132 | 133 | verify(observer).onChanged(null) 134 | } 135 | 136 | @Test 137 | fun observeBundleArrayListLazyTest() { 138 | val fragment = TestFragment() 139 | fragment.arguments = intentOf { 140 | putExtra("posterArrayList", arrayListOf(Poster.create(), Poster.create())) 141 | }.extras 142 | val posterArrayListLiveData by fragment.observeBundleArrayList("posterArrayList") 143 | 144 | MatcherAssert.assertThat(posterArrayListLiveData.value?.size, CoreMatchers.`is`(2)) 145 | 146 | val observer = mock>>() 147 | posterArrayListLiveData.observeForever(observer) 148 | 149 | verify(observer).onChanged(arrayListOf(Poster.create(), Poster.create())) 150 | } 151 | 152 | @Test 153 | fun observeBundleArrayListLazyNullTest() { 154 | val fragment = TestFragment() 155 | 156 | val posterArrayListLiveData by fragment.observeBundleArrayList("posterArrayList") 157 | 158 | val observer = mock>>() 159 | posterArrayListLiveData.observeForever(observer) 160 | 161 | verify(observer).onChanged(null) 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /bundler/src/test/java/com/skydoves/bundler/BundlerTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Designed and developed by 2020 skydoves (Jaewoong Eum) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.skydoves.bundler 18 | 19 | import android.content.Intent 20 | import com.skydoves.bundler.data.Poster 21 | import com.skydoves.bundler.data.UserInfo 22 | import org.hamcrest.MatcherAssert.assertThat 23 | import org.hamcrest.core.Is.`is` 24 | import org.junit.Test 25 | import org.junit.runner.RunWith 26 | import org.robolectric.RobolectricTestRunner 27 | import org.robolectric.annotation.Config 28 | 29 | @Config(sdk = [21]) 30 | @RunWith(RobolectricTestRunner::class) 31 | class BundlerTest { 32 | 33 | private val poster = Poster.create() 34 | private val userInfo = UserInfo.create() 35 | 36 | @Test 37 | fun putExtraWithKeyValueArgumentsTest() { 38 | val bundler: Bundler = Bundler().apply { 39 | putExtra("id", userInfo.id) 40 | putExtra("name", userInfo.nickname) 41 | putExtra("position", userInfo.position) 42 | putExtra("poster", poster) 43 | } 44 | 45 | val intent = bundler.intent 46 | assertThat(intent.getLongExtra("id", -1), `is`(1000L)) 47 | assertThat(intent.getStringExtra("name"), `is`("skydoves")) 48 | assertThat(intent.getStringExtra("position"), `is`("Android")) 49 | assertThat(intent.getParcelableExtra("poster"), `is`(poster)) 50 | } 51 | 52 | @Test 53 | fun putExtraWithKeyValuePairTest() { 54 | val bundler: Bundler = Bundler().apply { 55 | putExtra("id" to userInfo.id) 56 | putExtra("name" to userInfo.nickname) 57 | putExtra("position" to userInfo.position) 58 | putExtra("poster" to poster) 59 | } 60 | 61 | val intent = bundler.intent 62 | assertThat(intent.getLongExtra("id", -1), `is`(1000L)) 63 | assertThat(intent.getStringExtra("name"), `is`("skydoves")) 64 | assertThat(intent.getStringExtra("position"), `is`("Android")) 65 | assertThat(intent.getParcelableExtra("poster"), `is`(poster)) 66 | } 67 | 68 | @Test 69 | fun putExtraWithUnaryPlusTest() { 70 | val bundler: Bundler = Bundler().apply { 71 | +("id" to userInfo.id) 72 | +("name" to userInfo.nickname) 73 | +("position" to userInfo.position) 74 | +("poster" to poster) 75 | } 76 | 77 | val intent = bundler.intent 78 | assertThat(intent.getLongExtra("id", -1), `is`(1000L)) 79 | assertThat(intent.getStringExtra("name"), `is`("skydoves")) 80 | assertThat(intent.getStringExtra("position"), `is`("Android")) 81 | assertThat(intent.getParcelableExtra("poster"), `is`(poster)) 82 | } 83 | 84 | @Test 85 | fun removeExtraWithUnaryMinusTest() { 86 | val bundler: Bundler = Bundler().apply { 87 | +("id" to userInfo.id) 88 | -"id" 89 | +("name" to userInfo.nickname) 90 | -"name" 91 | +("position" to userInfo.position) 92 | -"position" 93 | +("poster" to poster) 94 | -"poster" 95 | } 96 | 97 | val intent = bundler.intent 98 | assertThat(intent.hasExtra("id"), `is`(false)) 99 | assertThat(intent.hasExtra("name"), `is`(false)) 100 | assertThat(intent.hasExtra("position"), `is`(false)) 101 | assertThat(intent.hasExtra("poster"), `is`(false)) 102 | } 103 | 104 | @Test 105 | fun putExtraWithInfixExtensionTest() { 106 | val bundler: Bundler = Bundler().apply { 107 | "id" eq userInfo.id 108 | "name" eq userInfo.nickname 109 | "position" eq userInfo.position 110 | "poster" eq poster 111 | } 112 | 113 | val intent = bundler.intent 114 | assertThat(intent.getLongExtra("id", -1), `is`(1000L)) 115 | assertThat(intent.getStringExtra("name"), `is`("skydoves")) 116 | assertThat(intent.getStringExtra("position"), `is`("Android")) 117 | assertThat(intent.getParcelableExtra("poster"), `is`(poster)) 118 | } 119 | 120 | @Test 121 | fun putExtraWithBundleOfTest() { 122 | val bundler: Bundler = Bundler().apply { 123 | bundleOf( 124 | ("id" to userInfo.id), 125 | ("name" to userInfo.nickname), 126 | ("position" to userInfo.position), 127 | ("poster" to poster) 128 | ) 129 | } 130 | 131 | val intent = bundler.intent 132 | assertThat(intent.getLongExtra("id", -1), `is`(1000L)) 133 | assertThat(intent.getStringExtra("name"), `is`("skydoves")) 134 | assertThat(intent.getStringExtra("position"), `is`("Android")) 135 | assertThat(intent.getParcelableExtra("poster"), `is`(poster)) 136 | } 137 | 138 | @Test 139 | fun setIntentOptionsTest() { 140 | val bundler: Bundler = Bundler().apply { 141 | setAction(Intent.ACTION_MAIN) 142 | addCategory(Intent.CATEGORY_APP_MUSIC) 143 | setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 144 | } 145 | 146 | val intent = bundler.intent 147 | assertThat(intent.action, `is`(Intent.ACTION_MAIN)) 148 | assertThat(intent.hasCategory(Intent.CATEGORY_APP_MUSIC), `is`(true)) 149 | assertThat(intent.flags, `is`(Intent.FLAG_ACTIVITY_NEW_TASK)) 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /bundler/src/test/java/com/skydoves/bundler/ActivityBundleObserveLazyTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Designed and developed by 2020 skydoves (Jaewoong Eum) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.skydoves.bundler 18 | 19 | import android.content.Intent 20 | import androidx.lifecycle.Observer 21 | import com.nhaarman.mockitokotlin2.mock 22 | import com.nhaarman.mockitokotlin2.verify 23 | import com.nhaarman.mockitokotlin2.verifyNoMoreInteractions 24 | import com.skydoves.bundler.data.Poster 25 | import org.hamcrest.CoreMatchers 26 | import org.hamcrest.MatcherAssert 27 | import org.junit.Test 28 | import org.junit.runner.RunWith 29 | import org.robolectric.RobolectricTestRunner 30 | import org.robolectric.annotation.Config 31 | 32 | @Config(sdk = [21]) 33 | @RunWith(RobolectricTestRunner::class) 34 | class ActivityBundleObserveLazyTest { 35 | 36 | @Test 37 | fun observeBundleLazyTest() { 38 | val activity = TestActivity() 39 | activity.intent = intentOf { 40 | putExtra("int", 123) 41 | } 42 | 43 | val intLiveData by activity.observeBundle("int", 0) 44 | 45 | val intObserver = mock>() 46 | intLiveData.observeForever(intObserver) 47 | 48 | verify(intObserver).onChanged(123) 49 | } 50 | 51 | @Test 52 | fun observeBundleLazyTwiceTest() { 53 | val activity = TestActivity() 54 | activity.intent = intentOf { 55 | putExtra("int", 123) 56 | } 57 | 58 | val intLiveData by activity.observeBundle("int", 0) 59 | 60 | val intObserver0 = mock>() 61 | intLiveData.observeForever(intObserver0) 62 | 63 | verify(intObserver0).onChanged(123) 64 | 65 | val intObserver1 = mock>() 66 | intLiveData.observeForever(intObserver1) 67 | 68 | verifyNoMoreInteractions(intObserver1) 69 | } 70 | 71 | @Test 72 | fun observeBundleLazyDefaultValueTest() { 73 | val activity = TestActivity() 74 | activity.intent = Intent() 75 | 76 | val intLiveData by activity.observeBundle("int", 123) 77 | 78 | val observer = mock>() 79 | intLiveData.observeForever(observer) 80 | 81 | verify(observer).onChanged(123) 82 | } 83 | 84 | fun observeBundleReferenceLazyTest() { 85 | val activity = TestActivity() 86 | activity.intent = intentOf { 87 | putExtra("poster", Poster.create()) 88 | } 89 | 90 | val posterLiveData by activity.observeBundle("poster") 91 | 92 | val posterObserver = mock>() 93 | posterLiveData.observeForever(posterObserver) 94 | 95 | verify(posterObserver).onChanged(Poster.create()) 96 | } 97 | 98 | @Test 99 | fun observeBundleLazyNullTest() { 100 | val activity = TestActivity() 101 | activity.intent = Intent() 102 | 103 | val posterLiveData by activity.observeBundle("poster") 104 | 105 | val posterObserver = mock>() 106 | posterLiveData.observeForever(posterObserver) 107 | 108 | verify(posterObserver).onChanged(null) 109 | } 110 | 111 | @Test 112 | fun observeBundleArrayLazyTest() { 113 | val activity = TestActivity() 114 | activity.intent = intentOf { 115 | putExtra("posterArray", arrayOf(Poster.create(), Poster.create())) 116 | } 117 | val posterArrayLiveData by activity.observeBundleArray("posterArray") 118 | 119 | MatcherAssert.assertThat(posterArrayLiveData.value?.size, CoreMatchers.`is`(2)) 120 | 121 | val observer = mock>>() 122 | posterArrayLiveData.observeForever(observer) 123 | 124 | verify(observer).onChanged(arrayOf(Poster.create(), Poster.create())) 125 | } 126 | 127 | @Test 128 | fun observeBundleArrayLazyNullTest() { 129 | val activity = TestActivity() 130 | activity.intent = Intent() 131 | 132 | val posterArrayLiveData by activity.observeBundleArray("posterArray") 133 | 134 | val observer = mock>>() 135 | posterArrayLiveData.observeForever(observer) 136 | 137 | verify(observer).onChanged(null) 138 | } 139 | 140 | @Test 141 | fun observeBundleArrayListLazyTest() { 142 | val activity = TestActivity() 143 | activity.intent = intentOf { 144 | putExtra("posterArrayList", arrayListOf(Poster.create(), Poster.create())) 145 | } 146 | val posterArrayListLiveData by activity.observeBundleArrayList("posterArrayList") 147 | 148 | MatcherAssert.assertThat(posterArrayListLiveData.value?.size, CoreMatchers.`is`(2)) 149 | 150 | val observer = mock>>() 151 | posterArrayListLiveData.observeForever(observer) 152 | 153 | verify(observer).onChanged(arrayListOf(Poster.create(), Poster.create())) 154 | } 155 | 156 | @Test 157 | fun observeBundleArrayListLazyNullTest() { 158 | val activity = TestActivity() 159 | activity.intent = Intent() 160 | 161 | val posterArrayListLiveData by activity.observeBundleArrayList("posterArrayList") 162 | 163 | val observer = mock>>() 164 | posterArrayListLiveData.observeForever(observer) 165 | 166 | verify(observer).onChanged(null) 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /bundler/src/test/java/com/skydoves/bundler/IntentOfTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Designed and developed by 2020 skydoves (Jaewoong Eum) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.skydoves.bundler 18 | 19 | import android.content.ComponentName 20 | import android.content.Context 21 | import android.content.Intent 22 | import android.net.Uri 23 | import androidx.test.core.app.ApplicationProvider 24 | import com.skydoves.bundler.data.Poster 25 | import com.skydoves.bundler.data.UserInfo 26 | import org.hamcrest.MatcherAssert.assertThat 27 | import org.hamcrest.core.Is.`is` 28 | import org.junit.Test 29 | import org.junit.runner.RunWith 30 | import org.robolectric.RobolectricTestRunner 31 | import org.robolectric.annotation.Config 32 | 33 | @Config(sdk = [21]) 34 | @RunWith(RobolectricTestRunner::class) 35 | class IntentOfTest { 36 | 37 | private val poster = Poster.create() 38 | private val userInfo = UserInfo.create() 39 | 40 | @Test 41 | fun intentOfTest() { 42 | val intent = intentOf { 43 | putExtra("id", userInfo.id) 44 | putExtra("name", userInfo.nickname) 45 | putExtra("position", userInfo.position) 46 | putExtra("poster", poster) 47 | } 48 | 49 | assertThat(intent.getLongExtra("id", -1), `is`(1000L)) 50 | assertThat(intent.getStringExtra("name"), `is`("skydoves")) 51 | assertThat(intent.getStringExtra("position"), `is`("Android")) 52 | assertThat(intent.getParcelableExtra("poster"), `is`(poster)) 53 | } 54 | 55 | @Test 56 | fun intentOfFromIntentTest() { 57 | val initialIntent = Intent().apply { 58 | putExtra("id", userInfo.id) 59 | } 60 | 61 | val intent = initialIntent.intentOf { 62 | putExtra("name", userInfo.nickname) 63 | putExtra("position", userInfo.position) 64 | putExtra("poster", poster) 65 | } 66 | 67 | assertThat(intent.getLongExtra("id", -1), `is`(1000L)) 68 | assertThat(intent.getStringExtra("name"), `is`("skydoves")) 69 | assertThat(intent.getStringExtra("position"), `is`("Android")) 70 | assertThat(intent.getParcelableExtra("poster"), `is`(poster)) 71 | } 72 | 73 | @Test 74 | fun intentOfFromActionTest() { 75 | val intent = Intent.ACTION_MAIN.intentOf { 76 | putExtra("id", userInfo.id) 77 | putExtra("name", userInfo.nickname) 78 | putExtra("position", userInfo.position) 79 | putExtra("poster", poster) 80 | } 81 | 82 | assertThat(intent.action, `is`(Intent.ACTION_MAIN)) 83 | assertThat(intent.getLongExtra("id", -1), `is`(1000L)) 84 | 85 | assertThat(intent.getStringExtra("name"), `is`("skydoves")) 86 | assertThat(intent.getStringExtra("position"), `is`("Android")) 87 | assertThat(intent.getParcelableExtra("poster"), `is`(poster)) 88 | } 89 | 90 | @Test 91 | fun intentOfFromActionWithDataTest() { 92 | val intent = Intent.ACTION_MAIN.intentOf(Uri.parse("skydoves")) { 93 | putExtra("id", userInfo.id) 94 | putExtra("name", userInfo.nickname) 95 | putExtra("position", userInfo.position) 96 | putExtra("poster", poster) 97 | } 98 | 99 | assertThat(intent.action, `is`(Intent.ACTION_MAIN)) 100 | assertThat(intent.data, `is`(Uri.parse("skydoves"))) 101 | 102 | assertThat(intent.getLongExtra("id", -1), `is`(1000L)) 103 | assertThat(intent.getStringExtra("name"), `is`("skydoves")) 104 | assertThat(intent.getStringExtra("position"), `is`("Android")) 105 | assertThat(intent.getParcelableExtra("poster"), `is`(poster)) 106 | } 107 | 108 | @Test 109 | fun intentOfFromContextTest() { 110 | val context = ApplicationProvider.getApplicationContext() 111 | val intent = context.intentOf { 112 | putExtra("id", userInfo.id) 113 | putExtra("name", userInfo.nickname) 114 | putExtra("position", userInfo.position) 115 | putExtra("poster", poster) 116 | } 117 | 118 | val componentName = ComponentName(context, TestActivity::class.java) 119 | assertThat(intent.component?.className, `is`(componentName.className)) 120 | assertThat(intent.component?.packageName, `is`(componentName.packageName)) 121 | 122 | assertThat(intent.getLongExtra("id", -1), `is`(1000L)) 123 | assertThat(intent.getStringExtra("name"), `is`("skydoves")) 124 | assertThat(intent.getStringExtra("position"), `is`("Android")) 125 | assertThat(intent.getParcelableExtra("poster"), `is`(poster)) 126 | } 127 | 128 | @Test 129 | fun intentOfFromContextWithActionAndUriTest() { 130 | val context = ApplicationProvider.getApplicationContext() 131 | val intent = context.intentOf( 132 | action = Intent.ACTION_MAIN, 133 | uri = Uri.parse("skydoves") 134 | ) { 135 | putExtra("id", userInfo.id) 136 | putExtra("name", userInfo.nickname) 137 | putExtra("position", userInfo.position) 138 | putExtra("poster", poster) 139 | } 140 | 141 | val componentName = ComponentName(context, TestActivity::class.java) 142 | assertThat(intent.component?.className, `is`(componentName.className)) 143 | assertThat(intent.component?.packageName, `is`(componentName.packageName)) 144 | 145 | assertThat(intent.action, `is`(Intent.ACTION_MAIN)) 146 | assertThat(intent.data, `is`(Uri.parse("skydoves"))) 147 | 148 | assertThat(intent.getLongExtra("id", -1), `is`(1000L)) 149 | assertThat(intent.getStringExtra("name"), `is`("skydoves")) 150 | assertThat(intent.getStringExtra("position"), `is`("Android")) 151 | assertThat(intent.getParcelableExtra("poster"), `is`(poster)) 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /bundler/src/test/java/com/skydoves/bundler/ActivityBundlerTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Designed and developed by 2020 skydoves (Jaewoong Eum) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.skydoves.bundler 18 | 19 | import android.content.Intent 20 | import com.skydoves.bundler.data.Poster 21 | import org.hamcrest.MatcherAssert.assertThat 22 | import org.hamcrest.core.Is.`is` 23 | import org.junit.Test 24 | import org.junit.runner.RunWith 25 | import org.robolectric.RobolectricTestRunner 26 | import org.robolectric.annotation.Config 27 | 28 | @Config(sdk = [21]) 29 | @RunWith(RobolectricTestRunner::class) 30 | class ActivityBundlerTest { 31 | 32 | @Test 33 | fun activityBundlerTest() { 34 | val activity = TestActivity() 35 | activity.intent = Intent() 36 | 37 | val bundler: Bundler = activity.activityBundler() 38 | bundler.putExtra("name", "skydoves") 39 | 40 | assertThat(activity.intent.getStringExtra("name"), `is`("skydoves")) 41 | } 42 | 43 | @Test 44 | fun activityVariableBundlerTest() { 45 | val activity = TestActivity() 46 | activity.intent = intentOf { 47 | putExtra("name", "skydoves") 48 | } 49 | 50 | val name by activity.activityVariableBundler("skydoves") { 51 | intent.getStringExtra("name") 52 | } 53 | 54 | assertThat(name, `is`("skydoves")) 55 | } 56 | 57 | @Test 58 | fun activityVariableBundlerValueTest() { 59 | val activity = TestActivity() 60 | activity.intent = intentOf { 61 | putExtra("name", "skydoves") 62 | } 63 | 64 | val name = activity.activityVariableBundlerValue("skydoves") { 65 | intent.getStringExtra("name") 66 | } 67 | 68 | assertThat(name, `is`("skydoves")) 69 | } 70 | 71 | @Test 72 | fun activityTypedBundlerTest() { 73 | val activity = TestActivity() 74 | activity.intent = intentOf { 75 | putExtra("poster", Poster.create()) 76 | } 77 | 78 | val poster by activity.activityTypedBundler { 79 | intent.getParcelableExtra("poster") as? Poster 80 | } 81 | 82 | assertThat(poster, `is`(Poster.create())) 83 | } 84 | 85 | @Test 86 | fun activityTypedBundlerValueTest() { 87 | val activity = TestActivity() 88 | activity.intent = intentOf { 89 | putExtra("poster", Poster.create()) 90 | } 91 | 92 | val poster = activity.activityTypedBundlerValue { 93 | intent.getParcelableExtra("poster") as? Poster 94 | } 95 | 96 | assertThat(poster, `is`(Poster.create())) 97 | } 98 | 99 | @Test 100 | fun activityNonNullTypedBundlerTest() { 101 | val activity = TestActivity() 102 | activity.intent = intentOf { 103 | putExtra("poster", Poster.create()) 104 | } 105 | 106 | val poster by activity.activityNonNullTypedBundler { 107 | intent.getParcelableExtra("poster")!! 108 | } 109 | 110 | assertThat(poster, `is`(Poster.create())) 111 | } 112 | 113 | @Test 114 | fun activityNonNullTypedBundlerValueTest() { 115 | val activity = TestActivity() 116 | activity.intent = intentOf { 117 | putExtra("poster", Poster.create()) 118 | } 119 | 120 | val poster = activity.activityNonNullTypedBundlerValue { 121 | intent.getParcelableExtra("poster")!! 122 | } 123 | 124 | assertThat(poster, `is`(Poster.create())) 125 | } 126 | 127 | @Test 128 | @Suppress("UNCHECKED_CAST") 129 | fun activityArrayBundlerTest() { 130 | val activity = TestActivity() 131 | val poster = Poster.create() 132 | 133 | activity.intent = intentOf { 134 | putExtra("posterArray", arrayOf(poster, poster, poster)) 135 | } 136 | 137 | val posterArray by activity.activityArrayBundler { 138 | intent.getParcelableArrayExtra("posterArray") as? Array 139 | } 140 | 141 | assertThat(posterArray?.size, `is`(3)) 142 | assertThat(posterArray?.get(0), `is`(poster)) 143 | } 144 | 145 | @Test 146 | @Suppress("UNCHECKED_CAST") 147 | fun activityArrayBundlerValueTest() { 148 | val activity = TestActivity() 149 | val poster = Poster.create() 150 | 151 | activity.intent = intentOf { 152 | putExtra("posterArray", arrayOf(poster, poster, poster)) 153 | } 154 | 155 | val posterArray = activity.activityArrayBundlerValue { 156 | intent.getParcelableArrayExtra("posterArray") as? Array 157 | } 158 | 159 | assertThat(posterArray?.size, `is`(3)) 160 | assertThat(posterArray?.get(0), `is`(poster)) 161 | } 162 | 163 | @Test 164 | fun activityArrayListBundlerTest() { 165 | val activity = TestActivity() 166 | val poster = Poster.create() 167 | 168 | activity.intent = intentOf { 169 | putExtra("posterArrayList", arrayListOf(poster, poster, poster)) 170 | } 171 | 172 | val posterArrayList by activity.activityArrayListBundler { 173 | intent.getParcelableArrayListExtra("posterArrayList") 174 | } 175 | 176 | assertThat(posterArrayList?.size, `is`(3)) 177 | assertThat(posterArrayList?.get(0), `is`(poster)) 178 | } 179 | 180 | @Test 181 | fun activityArrayListBundlerValueTest() { 182 | val activity = TestActivity() 183 | val poster = Poster.create() 184 | 185 | activity.intent = intentOf { 186 | putExtra("posterArrayList", arrayListOf(poster, poster, poster)) 187 | } 188 | 189 | val posterArrayList = activity.activityArrayListBundlerValue { 190 | intent.getParcelableArrayListExtra("posterArrayList") 191 | } 192 | 193 | assertThat(posterArrayList?.size, `is`(3)) 194 | assertThat(posterArrayList?.get(0), `is`(poster)) 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /bundler/src/test/java/com/skydoves/bundler/FragmentBundlerTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Designed and developed by 2020 skydoves (Jaewoong Eum) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.skydoves.bundler 18 | 19 | import com.skydoves.bundler.data.Poster 20 | import org.hamcrest.MatcherAssert.assertThat 21 | import org.hamcrest.core.Is.`is` 22 | import org.junit.Test 23 | import org.junit.runner.RunWith 24 | import org.robolectric.RobolectricTestRunner 25 | import org.robolectric.annotation.Config 26 | 27 | @Config(sdk = [21]) 28 | @RunWith(RobolectricTestRunner::class) 29 | class FragmentBundlerTest { 30 | 31 | @Test 32 | fun fragmentBundlerTest() { 33 | val fragment = TestFragment() 34 | fragment.arguments = intentOf { 35 | putExtra("name", "skydoves") 36 | }.extras 37 | 38 | val bundler: Bundler = fragment.fragmentBundler() 39 | assertThat(bundler.intent.getStringExtra("name"), `is`("skydoves")) 40 | } 41 | 42 | @Test 43 | fun fragmentVariableBundlerTest() { 44 | val fragment = TestFragment() 45 | fragment.arguments = intentOf { 46 | putExtra("name", "skydoves") 47 | }.extras 48 | 49 | val name by fragment.fragmentVariableBundler("skydoves") { 50 | intent.getStringExtra("name") 51 | } 52 | 53 | assertThat(name, `is`("skydoves")) 54 | } 55 | 56 | @Test 57 | fun fragmentVariableBundlerValueTest() { 58 | val fragment = TestFragment() 59 | fragment.arguments = intentOf { 60 | putExtra("name", "skydoves") 61 | }.extras 62 | 63 | val name = fragment.fragmentVariableBundlerValue("skydoves") { 64 | intent.getStringExtra("name") 65 | } 66 | 67 | assertThat(name, `is`("skydoves")) 68 | } 69 | 70 | @Test 71 | fun fragmentTypedBundlerTest() { 72 | val fragment = TestFragment() 73 | fragment.arguments = intentOf { 74 | putExtra("poster", Poster.create()) 75 | }.extras 76 | 77 | val poster by fragment.fragmentTypedBundler { 78 | intent.getParcelableExtra("poster") as? Poster 79 | } 80 | 81 | assertThat(poster, `is`(Poster.create())) 82 | } 83 | 84 | @Test 85 | fun fragmentTypedBundlerValueTest() { 86 | val fragment = TestFragment() 87 | fragment.arguments = intentOf { 88 | putExtra("poster", Poster.create()) 89 | }.extras 90 | 91 | val poster = fragment.fragmentTypedBundlerValue { 92 | intent.getParcelableExtra("poster") as? Poster 93 | } 94 | 95 | assertThat(poster, `is`(Poster.create())) 96 | } 97 | 98 | @Test 99 | fun fragmentNonNullTypedBundlerTest() { 100 | val fragment = TestFragment() 101 | fragment.arguments = intentOf { 102 | putExtra("poster", Poster.create()) 103 | }.extras 104 | 105 | val poster by fragment.fragmentNonNullTypedBundler { 106 | intent.getParcelableExtra("poster")!! 107 | } 108 | 109 | assertThat(poster, `is`(Poster.create())) 110 | } 111 | 112 | @Test 113 | fun fragmentNonNullTypedBundlerValueTest() { 114 | val fragment = TestFragment() 115 | fragment.arguments = intentOf { 116 | putExtra("poster", Poster.create()) 117 | }.extras 118 | 119 | val poster = fragment.fragmentNonNullTypedBundlerValue { 120 | intent.getParcelableExtra("poster")!! 121 | } 122 | 123 | assertThat(poster, `is`(Poster.create())) 124 | } 125 | 126 | @Test 127 | @Suppress("UNCHECKED_CAST") 128 | fun fragmentArrayBundlerTest() { 129 | val fragment = TestFragment() 130 | val poster = Poster.create() 131 | 132 | fragment.arguments = intentOf { 133 | putExtra("posterArray", arrayOf(poster, poster, poster)) 134 | }.extras 135 | 136 | val posterArray by fragment.fragmentArrayBundler { 137 | intent.getParcelableArrayExtra("posterArray") as Array 138 | } 139 | 140 | assertThat(posterArray?.size, `is`(3)) 141 | assertThat(posterArray?.get(0), `is`(poster)) 142 | } 143 | 144 | @Test 145 | @Suppress("UNCHECKED_CAST") 146 | fun fragmentArrayBundlerValueTest() { 147 | val fragment = TestFragment() 148 | val poster = Poster.create() 149 | 150 | fragment.arguments = intentOf { 151 | putExtra("posterArray", arrayOf(poster, poster, poster)) 152 | }.extras 153 | 154 | val posterArray = fragment.fragmentArrayBundlerValue { 155 | intent.getParcelableArrayExtra("posterArray") as Array 156 | } 157 | 158 | assertThat(posterArray?.size, `is`(3)) 159 | assertThat(posterArray?.get(0), `is`(poster)) 160 | } 161 | 162 | @Test 163 | fun activityArrayListBundlerTest() { 164 | val fragment = TestFragment() 165 | val poster = Poster.create() 166 | 167 | fragment.arguments = intentOf { 168 | putExtra("posterArrayList", arrayListOf(poster, poster, poster)) 169 | }.extras 170 | 171 | val posterArrayList by fragment.fragmentArrayListBundler { 172 | intent.getParcelableArrayListExtra("posterArrayList") 173 | } 174 | 175 | assertThat(posterArrayList?.size, `is`(3)) 176 | assertThat(posterArrayList?.get(0), `is`(poster)) 177 | } 178 | 179 | @Test 180 | fun activityArrayListBundlerValueTest() { 181 | val fragment = TestFragment() 182 | val poster = Poster.create() 183 | 184 | fragment.arguments = intentOf { 185 | putExtra("posterArrayList", arrayListOf(poster, poster, poster)) 186 | }.extras 187 | 188 | val posterArrayList = fragment.fragmentArrayListBundlerValue { 189 | intent.getParcelableArrayListExtra("posterArrayList") 190 | } 191 | 192 | assertThat(posterArrayList?.size, `is`(3)) 193 | assertThat(posterArrayList?.get(0), `is`(poster)) 194 | } 195 | } 196 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | 86 | # Determine the Java command to use to start the JVM. 87 | if [ -n "$JAVA_HOME" ] ; then 88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 89 | # IBM's JDK on AIX uses strange locations for the executables 90 | JAVACMD="$JAVA_HOME/jre/sh/java" 91 | else 92 | JAVACMD="$JAVA_HOME/bin/java" 93 | fi 94 | if [ ! -x "$JAVACMD" ] ; then 95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 96 | 97 | Please set the JAVA_HOME variable in your environment to match the 98 | location of your Java installation." 99 | fi 100 | else 101 | JAVACMD="java" 102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 103 | 104 | Please set the JAVA_HOME variable in your environment to match the 105 | location of your Java installation." 106 | fi 107 | 108 | # Increase the maximum file descriptors if we can. 109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 110 | MAX_FD_LIMIT=`ulimit -H -n` 111 | if [ $? -eq 0 ] ; then 112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 113 | MAX_FD="$MAX_FD_LIMIT" 114 | fi 115 | ulimit -n $MAX_FD 116 | if [ $? -ne 0 ] ; then 117 | warn "Could not set maximum file descriptor limit: $MAX_FD" 118 | fi 119 | else 120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 121 | fi 122 | fi 123 | 124 | # For Darwin, add options to specify how the application appears in the dock 125 | if $darwin; then 126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 127 | fi 128 | 129 | # For Cygwin or MSYS, switch paths to Windows format before running java 130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 133 | 134 | JAVACMD=`cygpath --unix "$JAVACMD"` 135 | 136 | # We build the pattern for arguments to be converted via cygpath 137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 138 | SEP="" 139 | for dir in $ROOTDIRSRAW ; do 140 | ROOTDIRS="$ROOTDIRS$SEP$dir" 141 | SEP="|" 142 | done 143 | OURCYGPATTERN="(^($ROOTDIRS))" 144 | # Add a user-defined pattern to the cygpath arguments 145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 147 | fi 148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 149 | i=0 150 | for arg in "$@" ; do 151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 153 | 154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 156 | else 157 | eval `echo args$i`="\"$arg\"" 158 | fi 159 | i=`expr $i + 1` 160 | done 161 | case $i in 162 | 0) set -- ;; 163 | 1) set -- "$args0" ;; 164 | 2) set -- "$args0" "$args1" ;; 165 | 3) set -- "$args0" "$args1" "$args2" ;; 166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;; 167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 172 | esac 173 | fi 174 | 175 | # Escape application args 176 | save () { 177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 178 | echo " " 179 | } 180 | APP_ARGS=`save "$@"` 181 | 182 | # Collect all arguments for the java command, following the shell quoting and substitution rules 183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 184 | 185 | exec "$JAVACMD" "$@" 186 | -------------------------------------------------------------------------------- /bundler/src/main/java/com/skydoves/bundler/IntentOf.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Designed and developed by 2020 skydoves (Jaewoong Eum) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | @file:Suppress("unused") 18 | 19 | package com.skydoves.bundler 20 | 21 | import android.content.Context 22 | import android.content.Intent 23 | import android.net.Uri 24 | import kotlin.reflect.KClass 25 | 26 | @DslMarker 27 | internal annotation class InlineIntentOnly 28 | 29 | /** 30 | * @author skydoves (Jaewoong Eum) 31 | * 32 | * Creates an instance of the intent. 33 | * 34 | * @param block A lambda domain scope of the [Bundler]. 35 | */ 36 | @JvmSynthetic 37 | @InlineIntentOnly 38 | inline fun intentOf(crossinline block: Bundler.() -> Unit): Intent { 39 | return Bundler().apply(block).intent 40 | } 41 | 42 | /** 43 | * Creates an instance of the intent from an intent. 44 | * 45 | * @param block A lambda domain scope of the [Bundler]. 46 | */ 47 | @JvmSynthetic 48 | @InlineIntentOnly 49 | inline fun Intent.intentOf(crossinline block: Bundler.() -> Unit): Intent { 50 | return Bundler(Intent(this)).apply(block).intent 51 | } 52 | 53 | /** 54 | * Creates an instance of the intent with an action. 55 | * 56 | * @param block A lambda domain scope of the [Bundler]. 57 | */ 58 | @JvmSynthetic 59 | @InlineIntentOnly 60 | inline fun String.intentOf(crossinline block: Bundler.() -> Unit): Intent { 61 | return Bundler(Intent(this)).apply(block).intent 62 | } 63 | 64 | /** 65 | * Creates an instance of the intent with action and URI. 66 | * 67 | * @param uri The Intent data URI. 68 | * @param block A lambda domain scope of the [Bundler]. 69 | */ 70 | @JvmSynthetic 71 | @InlineIntentOnly 72 | inline fun String.intentOf(uri: Uri, crossinline block: Bundler.() -> Unit): Intent { 73 | return Bundler(Intent(this, uri)).apply(block).intent 74 | } 75 | 76 | /** 77 | * Creates an instance of the intent with packageContext and a target class. 78 | * 79 | * @param block A lambda domain scope of the [Bundler]. 80 | */ 81 | @JvmSynthetic 82 | @InlineIntentOnly 83 | inline fun Context.intentOf( 84 | crossinline block: Bundler.() -> Unit 85 | ): Intent { 86 | return Bundler(Intent(this, T::class.java)).apply(block).intent 87 | } 88 | 89 | /** 90 | * Creates an instance of the intent with packageContext, a target class, an action and URI. 91 | * 92 | * @param action The Intent action, such as ACTION_VIEW. 93 | * @param uri The Intent data URI. 94 | * @param block A lambda domain scope of the [Bundler]. 95 | */ 96 | @JvmSynthetic 97 | @InlineIntentOnly 98 | inline fun Context.intentOf( 99 | action: String, 100 | uri: Uri, 101 | crossinline block: Bundler.() -> Unit 102 | ): Intent { 103 | return Bundler(Intent(action, uri, this, T::class.java)).apply(block).intent 104 | } 105 | 106 | /** 107 | * Creates an instance of the intent. 108 | * 109 | * @param block A lambda domain scope of the [Bundler]. 110 | */ 111 | @Deprecated( 112 | message = "use intentOf() instead", 113 | replaceWith = ReplaceWith( 114 | "intentOf(block)", 115 | imports = ["com.skydoves.bundler.intentOf"] 116 | ) 117 | ) 118 | @JvmSynthetic 119 | @InlineIntentOnly 120 | inline fun intent(crossinline block: Bundler.() -> Unit): Intent { 121 | return Bundler().apply(block).intent 122 | } 123 | 124 | /** 125 | * Creates an instance of the intent from an intent. 126 | * 127 | * @param block A lambda domain scope of the [Bundler]. 128 | */ 129 | @Deprecated( 130 | message = "use intentOf() instead", 131 | replaceWith = ReplaceWith( 132 | "intentOf(block)", 133 | imports = ["com.skydoves.bundler.intentOf"] 134 | ) 135 | ) 136 | @JvmSynthetic 137 | @InlineIntentOnly 138 | inline fun Intent.intent(crossinline block: Bundler.() -> Unit): Intent { 139 | return Bundler(Intent(this)).apply(block).intent 140 | } 141 | 142 | /** 143 | * Creates an instance of the intent with action and URI. 144 | * 145 | * @param uri The Intent data URI. 146 | * @param block A lambda domain scope of the [Bundler]. 147 | */ 148 | @Deprecated( 149 | message = "use intentOf() instead", 150 | replaceWith = ReplaceWith( 151 | "intentOf(uri, block)", 152 | imports = ["com.skydoves.bundler.intentOf"] 153 | ) 154 | ) 155 | @JvmSynthetic 156 | @InlineIntentOnly 157 | inline fun String.intent(uri: Uri, crossinline block: Bundler.() -> Unit): Intent { 158 | return Bundler(Intent(this, uri)).apply(block).intent 159 | } 160 | 161 | /** 162 | * Creates an instance of the intent with an action. 163 | * 164 | * @param block A lambda domain scope of the [Bundler]. 165 | */ 166 | @Deprecated( 167 | message = "use intentOf() instead", 168 | replaceWith = ReplaceWith( 169 | "intentOf(block)", 170 | imports = ["com.skydoves.bundler.intentOf"] 171 | ) 172 | ) 173 | @JvmSynthetic 174 | @InlineIntentOnly 175 | inline fun String.intent(crossinline block: Bundler.() -> Unit): Intent { 176 | return Bundler(Intent(this)).apply(block).intent 177 | } 178 | 179 | /** 180 | * Creates an instance of the intent with packageContext and a target class. 181 | * 182 | * @param block A lambda domain scope of the [Bundler]. 183 | */ 184 | @Deprecated( 185 | message = "use intentOf() instead", 186 | replaceWith = ReplaceWith( 187 | "intentOf(block)", 188 | imports = ["com.skydoves.bundler.intentOf"] 189 | ) 190 | ) 191 | @JvmSynthetic 192 | @InlineIntentOnly 193 | inline fun Context.intent( 194 | clazz: KClass, 195 | crossinline block: Bundler.() -> Unit 196 | ): Intent { 197 | return Bundler(Intent(this, clazz.java)).apply(block).intent 198 | } 199 | 200 | /** 201 | * Creates an instance of the intent with packageContext, a target class, an action and URI. 202 | * 203 | * @param clazz The component class that is to be used for the intent. 204 | * @param action The Intent action, such as ACTION_VIEW. 205 | * @param uri The Intent data URI. 206 | * @param block A lambda domain scope of the [Bundler]. 207 | */ 208 | @Deprecated( 209 | message = "use intentOf() instead", 210 | replaceWith = ReplaceWith( 211 | "intentOf(action, uri, block)", 212 | imports = ["com.skydoves.bundler.intentOf"] 213 | ) 214 | ) 215 | @JvmSynthetic 216 | @InlineIntentOnly 217 | inline fun Context.intent( 218 | clazz: KClass, 219 | action: String, 220 | uri: Uri, 221 | crossinline block: Bundler.() -> Unit 222 | ): Intent { 223 | return Bundler(Intent(action, uri, this, clazz.java)).apply(block).intent 224 | } 225 | 226 | /** 227 | * Creates a new bundle and put it into the [intent] with the given key/value pairs as elements. 228 | * 229 | * @param pairs key/value pairs. 230 | */ 231 | @JvmSynthetic 232 | @InlineIntentOnly 233 | fun Intent.bundleOf(vararg pairs: Pair) = apply { 234 | putExtras(com.skydoves.bundler.bundleOf(*pairs)) 235 | } 236 | -------------------------------------------------------------------------------- /bundler/src/main/java/com/skydoves/bundler/FragmentBundler.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Designed and developed by 2020 skydoves (Jaewoong Eum) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.skydoves.bundler 18 | 19 | import androidx.fragment.app.Fragment 20 | 21 | /** 22 | * @author skydoves (Jaewoong Eum) 23 | * 24 | * Returns an instance of a bundler that has the arguments of a fragment. 25 | */ 26 | fun Fragment.fragmentBundler(): Bundler = Bundler().replaceExtras(arguments) 27 | 28 | /** 29 | * @author skydoves (Jaewoong Eum) 30 | * 31 | * Retrieves a primitive type of extended data from arguments lazily. 32 | * 33 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 34 | * @param initializer The initializer for providing an instance of the type parameter. 35 | */ 36 | @PublishedApi 37 | @JvmSynthetic 38 | @InlineBundleDsl 39 | internal inline fun Fragment.fragmentVariableBundler( 40 | defaultValue: T, 41 | crossinline initializer: Bundler.() -> T? 42 | ): Lazy = 43 | lazy(LazyThreadSafetyMode.NONE) { 44 | fragmentBundler().initializer() ?: defaultValue 45 | } 46 | 47 | /** 48 | * @author skydoves (Jaewoong Eum) 49 | * 50 | * Retrieves a primitive type of extended data from arguments immediately. 51 | * 52 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 53 | * @param initializer The initializer for providing an instance of the type parameter. 54 | */ 55 | @PublishedApi 56 | @JvmSynthetic 57 | @InlineBundleDsl 58 | internal inline fun Fragment.fragmentVariableBundlerValue( 59 | defaultValue: T, 60 | crossinline initializer: Bundler.() -> T? 61 | ): T = fragmentBundler().initializer() ?: defaultValue 62 | 63 | /** 64 | * @author skydoves (Jaewoong Eum) 65 | * 66 | * Retrieves a primitive type of extended data from arguments lazily. 67 | * 68 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 69 | * @param initializer The initializer for providing an instance of the type parameter. 70 | */ 71 | @PublishedApi 72 | @JvmSynthetic 73 | @InlineBundleDsl 74 | internal inline fun Fragment.fragmentTypedBundler( 75 | crossinline defaultValue: () -> T? = { null }, 76 | crossinline initializer: Bundler.() -> T? 77 | ): Lazy = 78 | lazy(LazyThreadSafetyMode.NONE) { 79 | fragmentBundler().initializer() ?: defaultValue() 80 | } 81 | 82 | /** 83 | * @author skydoves (Jaewoong Eum) 84 | * 85 | * Retrieves a primitive type of extended data from arguments immediately. 86 | * 87 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 88 | * @param initializer The initializer for providing an instance of the type parameter. 89 | */ 90 | @PublishedApi 91 | @JvmSynthetic 92 | @InlineBundleDsl 93 | internal inline fun Fragment.fragmentTypedBundlerValue( 94 | crossinline defaultValue: () -> T? = { null }, 95 | crossinline initializer: Bundler.() -> T? 96 | ): T? = fragmentBundler().initializer() ?: defaultValue() 97 | 98 | /** 99 | * @author skydoves (Jaewoong Eum) 100 | * 101 | * Retrieves a primitive type of extended data from arguments lazily. 102 | * 103 | * @param initializer The initializer for providing an instance of the type parameter. 104 | */ 105 | @PublishedApi 106 | @JvmSynthetic 107 | @InlineBundleDsl 108 | internal inline fun Fragment.fragmentNonNullTypedBundler( 109 | crossinline initializer: Bundler.() -> T 110 | ): Lazy = 111 | lazy(LazyThreadSafetyMode.NONE) { 112 | fragmentBundler().initializer() 113 | } 114 | 115 | /** 116 | * @author skydoves (Jaewoong Eum) 117 | * 118 | * Retrieves a primitive type of extended data from arguments immediately. 119 | * 120 | * @param initializer The initializer for providing an instance of the type parameter. 121 | */ 122 | @PublishedApi 123 | @JvmSynthetic 124 | @InlineBundleDsl 125 | internal inline fun Fragment.fragmentNonNullTypedBundlerValue( 126 | crossinline initializer: Bundler.() -> T 127 | ): T = fragmentBundler().initializer() 128 | 129 | /** 130 | * @author skydoves (Jaewoong Eum) 131 | * 132 | * Retrieves a primitive type of extended data from arguments lazily. 133 | * 134 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 135 | * @param initializer The initializer for providing an instance of the type parameter. 136 | */ 137 | @PublishedApi 138 | @JvmSynthetic 139 | @InlineBundleDsl 140 | internal inline fun Fragment.fragmentArrayBundler( 141 | crossinline defaultValue: () -> Array? = { null }, 142 | crossinline initializer: Bundler.() -> Array? 143 | ): Lazy?> = 144 | lazy(LazyThreadSafetyMode.NONE) { 145 | fragmentBundler().initializer() ?: defaultValue() 146 | } 147 | 148 | /** 149 | * @author skydoves (Jaewoong Eum) 150 | * 151 | * Retrieves a primitive type of extended data from arguments immediately. 152 | * 153 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 154 | * @param initializer The initializer for providing an instance of the type parameter. 155 | */ 156 | @PublishedApi 157 | @JvmSynthetic 158 | @InlineBundleDsl 159 | internal inline fun Fragment.fragmentArrayBundlerValue( 160 | crossinline defaultValue: () -> Array? = { null }, 161 | crossinline initializer: Bundler.() -> Array? 162 | ): Array? = fragmentBundler().initializer() ?: defaultValue() 163 | 164 | /** 165 | * @author skydoves (Jaewoong Eum) 166 | * 167 | * Retrieves a primitive type of extended data from arguments lazily. 168 | * 169 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 170 | * @param initializer The initializer for providing an instance of the type parameter. 171 | */ 172 | @PublishedApi 173 | @JvmSynthetic 174 | @InlineBundleDsl 175 | internal inline fun Fragment.fragmentArrayListBundler( 176 | crossinline defaultValue: () -> ArrayList? = { null }, 177 | crossinline initializer: Bundler.() -> ArrayList? 178 | ): Lazy?> = 179 | lazy(LazyThreadSafetyMode.NONE) { 180 | fragmentBundler().initializer() ?: defaultValue() 181 | } 182 | 183 | /** 184 | * @author skydoves (Jaewoong Eum) 185 | * 186 | * Retrieves a primitive type of extended data from arguments immediately. 187 | * 188 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 189 | * @param initializer The initializer for providing an instance of the type parameter. 190 | */ 191 | @PublishedApi 192 | @JvmSynthetic 193 | @InlineBundleDsl 194 | internal inline fun Fragment.fragmentArrayListBundlerValue( 195 | crossinline defaultValue: () -> ArrayList? = { null }, 196 | crossinline initializer: Bundler.() -> ArrayList? 197 | ): ArrayList? = fragmentBundler().initializer() ?: defaultValue() 198 | -------------------------------------------------------------------------------- /bundler/src/main/java/com/skydoves/bundler/ActivityBundler.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Designed and developed by 2020 skydoves (Jaewoong Eum) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.skydoves.bundler 18 | 19 | import android.app.Activity 20 | 21 | /** 22 | * @author skydoves (Jaewoong Eum) 23 | * 24 | * Returns an instance of a bundler that has the the Intent of an Activity. 25 | * 26 | * @throws NullPointerException when the Activity does not contain any Intent. 27 | */ 28 | fun Activity.activityBundler(): Bundler = Bundler(intent) 29 | 30 | /** 31 | * @author skydoves (Jaewoong Eum) 32 | * 33 | * Retrieves a primitive type of extended data from the Intent lazily. 34 | * 35 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 36 | * @param initializer The initializer for providing an instance of the type parameter. 37 | */ 38 | @PublishedApi 39 | @JvmSynthetic 40 | @InlineBundleDsl 41 | internal inline fun Activity.activityVariableBundler( 42 | defaultValue: T, 43 | crossinline initializer: Bundler.() -> T? 44 | ): Lazy = 45 | lazy(LazyThreadSafetyMode.NONE) { 46 | activityBundler().initializer() ?: defaultValue 47 | } 48 | 49 | /** 50 | * @author skydoves (Jaewoong Eum) 51 | * 52 | * Retrieves a primitive type of extended data from the Intent immediately. 53 | * 54 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 55 | * @param initializer The initializer for providing an instance of the type parameter. 56 | */ 57 | @PublishedApi 58 | @JvmSynthetic 59 | @InlineBundleDsl 60 | internal inline fun Activity.activityVariableBundlerValue( 61 | defaultValue: T, 62 | crossinline initializer: Bundler.() -> T? 63 | ): T = activityBundler().initializer() ?: defaultValue 64 | 65 | /** 66 | * @author skydoves (Jaewoong Eum) 67 | * 68 | * Retrieves a references type of extended data from the Intent lazily. 69 | * 70 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 71 | * @param initializer The initializer for providing an instance of the type parameter. 72 | */ 73 | @PublishedApi 74 | @JvmSynthetic 75 | @InlineBundleDsl 76 | internal inline fun Activity.activityTypedBundler( 77 | crossinline defaultValue: () -> T? = { null }, 78 | crossinline initializer: Bundler.() -> T? 79 | ): Lazy = 80 | lazy(LazyThreadSafetyMode.NONE) { 81 | activityBundler().initializer() ?: defaultValue() 82 | } 83 | 84 | /** 85 | * @author skydoves (Jaewoong Eum) 86 | * 87 | * Retrieves a references type of extended data from the Intent immediately. 88 | * 89 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 90 | * @param initializer The initializer for providing an instance of the type parameter. 91 | */ 92 | @PublishedApi 93 | @JvmSynthetic 94 | @InlineBundleDsl 95 | internal inline fun Activity.activityTypedBundlerValue( 96 | crossinline defaultValue: () -> T? = { null }, 97 | crossinline initializer: Bundler.() -> T? 98 | ): T? = activityBundler().initializer() ?: defaultValue() 99 | 100 | /** 101 | * @author skydoves (Jaewoong Eum) 102 | * 103 | * Retrieves a references type of extended data from the Intent lazily. 104 | * 105 | * @param initializer The initializer for providing a non-null instance of the type parameter. 106 | */ 107 | @PublishedApi 108 | @JvmSynthetic 109 | @InlineBundleDsl 110 | internal inline fun Activity.activityNonNullTypedBundler( 111 | crossinline initializer: Bundler.() -> T 112 | ): Lazy = 113 | lazy(LazyThreadSafetyMode.NONE) { 114 | activityBundler().initializer() 115 | } 116 | 117 | /** 118 | * @author skydoves (Jaewoong Eum) 119 | * 120 | * Retrieves a references type of extended data from the Intent immediately. 121 | * 122 | * @param initializer The initializer for providing a non-null instance of the type parameter. 123 | */ 124 | @PublishedApi 125 | @JvmSynthetic 126 | @InlineBundleDsl 127 | internal inline fun Activity.activityNonNullTypedBundlerValue( 128 | crossinline initializer: Bundler.() -> T 129 | ): T = activityBundler().initializer() 130 | 131 | /** 132 | * @author skydoves (Jaewoong Eum) 133 | * 134 | * Retrieves a references array type of extended data from the Intent lazily. 135 | * 136 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 137 | * @param initializer The initializer for providing an instance of the type parameter. 138 | */ 139 | @PublishedApi 140 | @JvmSynthetic 141 | @InlineBundleDsl 142 | internal inline fun Activity.activityArrayBundler( 143 | crossinline defaultValue: () -> Array? = { null }, 144 | crossinline initializer: Bundler.() -> Array? 145 | ): Lazy?> = 146 | lazy(LazyThreadSafetyMode.NONE) { 147 | activityBundler().initializer() ?: defaultValue() 148 | } 149 | 150 | /** 151 | * @author skydoves (Jaewoong Eum) 152 | * 153 | * Retrieves a references array type of extended data from the Intent immediately. 154 | * 155 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 156 | * @param initializer The initializer for providing an instance of the type parameter. 157 | */ 158 | @PublishedApi 159 | @JvmSynthetic 160 | @InlineBundleDsl 161 | internal inline fun Activity.activityArrayBundlerValue( 162 | crossinline defaultValue: () -> Array? = { null }, 163 | crossinline initializer: Bundler.() -> Array? 164 | ): Array? = activityBundler().initializer() ?: defaultValue() 165 | 166 | /** 167 | * @author skydoves (Jaewoong Eum) 168 | * 169 | * Retrieves a references array list type of extended data from the Intent lazily. 170 | * 171 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 172 | * @param initializer The initializer for providing an instance of the type parameter. 173 | */ 174 | @PublishedApi 175 | @JvmSynthetic 176 | @InlineBundleDsl 177 | internal inline fun Activity.activityArrayListBundler( 178 | crossinline defaultValue: () -> ArrayList? = { null }, 179 | crossinline initializer: Bundler.() -> ArrayList? 180 | ): Lazy?> = 181 | lazy(LazyThreadSafetyMode.NONE) { 182 | activityBundler().initializer() ?: defaultValue() 183 | } 184 | 185 | /** 186 | * @author skydoves (Jaewoong Eum) 187 | * 188 | * Retrieves a references array list type of extended data from the Intent lazily. 189 | * 190 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 191 | * @param initializer The initializer for providing an instance of the type parameter. 192 | */ 193 | @PublishedApi 194 | @JvmSynthetic 195 | @InlineBundleDsl 196 | internal inline fun Activity.activityArrayListBundlerValue( 197 | crossinline defaultValue: () -> ArrayList? = { null }, 198 | crossinline initializer: Bundler.() -> ArrayList? 199 | ): ArrayList? = activityBundler().initializer() ?: defaultValue() 200 | -------------------------------------------------------------------------------- /bundler/src/main/java/com/skydoves/bundler/Bundler.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Designed and developed by 2020 skydoves (Jaewoong Eum) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | @file:Suppress("unused") 18 | 19 | package com.skydoves.bundler 20 | 21 | import android.app.Activity 22 | import android.content.Context 23 | import android.content.Intent 24 | import android.net.Uri 25 | import android.os.Bundle 26 | 27 | @DslMarker 28 | internal annotation class InlineBundleDsl 29 | 30 | /** create a new instance of the [Bundler] using kotlin dsl. */ 31 | @JvmSynthetic 32 | @InlineBundleDsl 33 | inline fun bundler(crossinline block: Bundler.() -> Unit) = Bundler(Intent()).apply(block) 34 | 35 | /** Bundler is a wrapper class of the [Intent] for putting intent data elegantly. */ 36 | inline class Bundler(val intent: Intent = Intent()) { 37 | 38 | /** Add a new category to the intent. */ 39 | fun addCategory(category: String) = apply { 40 | intent.addCategory(category) 41 | } 42 | 43 | /** Remove a category from an intent. */ 44 | fun removeCategory(category: String) = apply { 45 | intent.removeCategory(category) 46 | } 47 | 48 | /** Add additional flags to the intent (or with existing flags value). */ 49 | fun addFlags(flags: Int) = apply { 50 | intent.addFlags(flags) 51 | } 52 | 53 | /** Copy the contents of other in to this object, but only where fields are not defined by this object. */ 54 | fun fillIn(other: Intent, flags: Int) = apply { 55 | intent.fillIn(other, flags) 56 | } 57 | 58 | /** Determine if two intents are the same for the purposes of intent resolution (filtering). */ 59 | fun filterEquals(other: Intent) = apply { 60 | intent.filterEquals(other) 61 | } 62 | 63 | /** Completely replace the extras in the Intent with the extras in the given Intent. */ 64 | fun replaceExtras(src: Intent) = apply { 65 | intent.replaceExtras(src) 66 | } 67 | 68 | /** Completely replace the extras in the Intent with the given Bundle of extras. */ 69 | fun replaceExtras(extras: Bundle?) = apply { 70 | intent.replaceExtras(extras) 71 | } 72 | 73 | /** Set the general action to be performed. */ 74 | fun setAction(action: String) = apply { 75 | intent.action = action 76 | } 77 | 78 | /** Set the data this intent is operating on. */ 79 | fun setData(data: Uri) = apply { 80 | intent.data = data 81 | } 82 | 83 | /** Set special flags controlling how this intent is handled. */ 84 | fun setFlags(flags: Int) = apply { 85 | intent.flags = flags 86 | } 87 | 88 | /** 89 | * Launch a new activity with no options specified. 90 | * 91 | * @param context A context for launching an activity. 92 | * 93 | * @throws android.content.ActivityNotFoundException 94 | */ 95 | fun startActivity(context: Context) { 96 | context.startActivity(intent) 97 | } 98 | 99 | /** 100 | * Launch a new activity with options. 101 | * 102 | * @param context A context for launching an activity. 103 | * @param options Additional options for how the Activity should be started. 104 | * 105 | * @throws android.content.ActivityNotFoundException 106 | */ 107 | fun startActivity(context: Context, options: Bundle) { 108 | context.startActivity(intent, options) 109 | } 110 | 111 | /** 112 | * Launch an activity for which you would like a result when it finished. 113 | * 114 | * @param activity An activity for receiving the result. 115 | * @param requestCode If >= 0, this code will be returned in 116 | * onActivityResult() when the activity exits. 117 | * 118 | * @throws android.content.ActivityNotFoundException 119 | */ 120 | fun startActivityForResult(activity: Activity, requestCode: Int) { 121 | activity.startActivityForResult(intent, requestCode) 122 | } 123 | 124 | /** 125 | * Launch an activity for which you would like a result when it finished. 126 | * 127 | * @param activity An activity for receiving the result. 128 | * @param requestCode If >= 0, this code will be returned in 129 | * onActivityResult() when the activity exits. 130 | * @param options Additional options for how the Activity should be started. 131 | * See {@link android.content.Context#startActivity(Intent, Bundle)} 132 | * Context.startActivity(Intent, Bundle)} for more details. 133 | * 134 | * @throws android.content.ActivityNotFoundException 135 | */ 136 | 137 | fun startActivityForResult(activity: Activity, requestCode: Int, options: Bundle) { 138 | activity.startActivityForResult(intent, requestCode, options) 139 | } 140 | 141 | /** 142 | * A special variation to launch an activity only if a new activity instance is needed to handle the given Intent. 143 | * 144 | * @param activity An activity. 145 | * @param requestCode If >= 0, this code will be returned in 146 | * onActivityResult() when the activity exits. 147 | */ 148 | fun startActivityIfNeeded(activity: Activity, requestCode: Int): Boolean { 149 | return activity.startActivityIfNeeded(intent, requestCode) 150 | } 151 | 152 | /** 153 | * Special version of starting an activity, for use when you are replacing other activity components. 154 | * 155 | * @param activity An activity. 156 | */ 157 | fun startNextMatchingActivity(activity: Activity): Boolean { 158 | return activity.startNextMatchingActivity(intent) 159 | } 160 | 161 | /** 162 | * Creates a new bundle and put it into the [intent] with the given key/value pairs as elements. 163 | * 164 | * @param pairs key/value pairs. 165 | */ 166 | @JvmSynthetic 167 | @InlineBundleDsl 168 | fun bundleOf(vararg pairs: Pair) = apply { 169 | intent.putExtras(com.skydoves.bundler.bundleOf(*pairs)) 170 | } 171 | 172 | /** 173 | * Inserts a new extra data with the given key/value pairs as elements. 174 | * 175 | * @param pair A key/value pair. (key to value) A value that is supported type of [Bundle]. 176 | * 177 | * ``` 178 | * putExtra(key to value) 179 | * ``` 180 | */ 181 | @InlineBundleDsl 182 | fun putExtra(pair: Pair) = apply { 183 | bundleOf(pair) 184 | } 185 | 186 | /** 187 | * Inserts a new extra data with the given key/value pair as an element. 188 | * 189 | * @param key A key String 190 | * @param value A value that is supported type of [Bundle]. 191 | * 192 | * @throws IllegalArgumentException When a value is not a supported type of [Bundle]. 193 | */ 194 | @InlineBundleDsl 195 | fun putExtra(key: String, value: Any?) = apply { 196 | intent.putExtras(com.skydoves.bundler.bundleOf(key to value)) 197 | } 198 | 199 | /** 200 | * Inserts a key/value pair as an extra element. 201 | * 202 | * ``` 203 | * key eq value 204 | * ``` 205 | */ 206 | infix fun String.eq(value: Any?) = intent.putExtras( 207 | com.skydoves.bundler.bundleOf(this to value) 208 | ) 209 | 210 | /** 211 | * Inserts a key/value pair as an extra element. 212 | * 213 | * ``` 214 | * +(key to value) 215 | * ``` 216 | */ 217 | operator fun Pair.unaryPlus() = intent.putExtras( 218 | com.skydoves.bundler.bundleOf(this) 219 | ) 220 | 221 | /** 222 | * Removes a previous extra. 223 | * 224 | * ``` 225 | * -key 226 | * ``` 227 | **/ 228 | operator fun String.unaryMinus() = intent.removeExtra(this) 229 | } 230 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 |

Bundler


3 |

4 | License 5 | API 6 | Build Status 7 | Android Weekly 8 | KotlinWeekly 9 | Medium 10 | Javadoc 11 |

12 | 13 |

14 | 🎁 Android Intent & Bundle extensions that insert and retrieve values elegantly. 15 |

16 | 17 |

18 | 19 |

20 | 21 | ## Including in your project 22 | [![Maven Central](https://img.shields.io/maven-central/v/com.github.skydoves/bundler.svg?label=Maven%20Central)](https://search.maven.org/search?q=g:%22com.github.skydoves%22%20AND%20a:%22bundler%22) [![Jitpack](https://jitpack.io/v/skydoves/bundler.svg)](https://jitpack.io/#skydoves/bundler) 23 | ### Gradle 24 | Add below codes to your **root** `build.gradle` file (not your module build.gradle file). 25 | ```gradle 26 | allprojects { 27 | repositories { 28 | mavenCentral() 29 | } 30 | } 31 | ``` 32 | And add a dependency code to your **module**'s `build.gradle` file. 33 | ```gradle 34 | dependencies { 35 | implementation "com.github.skydoves:bundler:1.0.4" 36 | } 37 | ``` 38 | ## SNAPSHOT 39 | [![Bundler](https://img.shields.io/static/v1?label=snapshot&message=bundler&logo=apache%20maven&color=C71A36)](https://oss.sonatype.org/content/repositories/snapshots/com/github/skydoves/bundler/)
40 | Snapshots of the current development version of Bundler are available, which track [the latest versions](https://oss.sonatype.org/content/repositories/snapshots/com/github/skydoves/bundler/). 41 | ```Gradle 42 | repositories { 43 | maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } 44 | } 45 | ``` 46 | 47 | ## Usage 48 | ### Intent 49 | `intentOf` is an expression for creating an Intent using Kotlin DSL style and we can put extras using the `putExtra` method. Also, we can put extras using the `+` keyword in front of a key/value pair. 50 | ```kotlin 51 | val intent = intentOf { 52 | putExtra("posterId", poster.id) // put a Long type 'posterId' value. 53 | putExtra("posterName" to poster.name) // put a String type 'posterName' value. 54 | putExtra("poster", poster) // put a Parcelable type 'poster' value. 55 | 56 | +("id" to userInfo.id) // put a Long type 'id' value. 57 | +("name" to userInfo.nickname) // put a String type 'name' value. 58 | 59 | -"name" // remove a String type 'name' value. 60 | } 61 | ``` 62 | ### StartActivity 63 | We can start activities using the `intentOf` expression like below. 64 | ```kotlin 65 | intentOf { 66 | putExtra("id" to userInfo.id) 67 | putExtra("name" to userInfo.nickname) 68 | putExtra("poster", poster) 69 | startActivity(this@MainActivity) 70 | } 71 | ``` 72 | We can also use other options for creating an intent. 73 | ```kotlin 74 | intentOf { 75 | setAction(Intent.ACTION_MAIN) 76 | addCategory(Intent.CATEGORY_APP_MUSIC) 77 | setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) 78 | startActivity(this@MainActivity) 79 | } 80 | ``` 81 | ### bundle 82 | `bundle` is an expression for initializing lazily extra values from the intent. 83 | ```kotlin 84 | class SecondActivity : AppCompatActivity() { 85 | 86 | private val id: Long by bundle("id", -1) // initializes a Long extra value lazily. 87 | private val name: String by bundle("name", "") // initializes a String extra value lazily. 88 | private val poster: Poster? by bundle("poster") // initializes a Parcelable extra value lazily. 89 | 90 | // -- stubs -- // 91 | ``` 92 | We can initialize a Parcelable value with a defaut value. 93 | ```kotlin 94 | private val poster: Poster? by bundle("poster") { Poster.create() } 95 | ``` 96 | Also, we can initialize type of Array and ArrayList using `bundleArray` and `bundleArrayList` expression. 97 | ```kotlin 98 | // initialize lazily without default values. 99 | private val posterArray by bundleArray("posterArray") 100 | private val posterListArray by bundleArrayList("posterArrayList") 101 | 102 | or 103 | 104 | // initialize lazily with default values. 105 | private val posterArray by bundleArray("posterArray") { arrayOf() } 106 | private val posterListArray by bundleArrayList("posterArrayList") { arrayListOf() } 107 | ``` 108 | ### bundle in Fragment 109 | The below example shows setting arguments using the `intentOf` expression. 110 | ```kotlin 111 | arguments = intentOf { 112 | +("id" to userInfo.id) 113 | +("name" to userInfo.nickname) 114 | +("poster" to poster) 115 | }.extras 116 | ``` 117 | We can initialize argument values lazily in Fragments using the `bundle` expression like below. 118 | ```diff 119 | - val id: Long = arguments?.getLong("id", -1) ?: -1 120 | + val id: Long by bundle("id", -1) 121 | - val poster: Poster? = arguments?.getParcelable("poster") 122 | + val poster: Poster? by bundle("poster") 123 | ``` 124 | 125 | ### bundleNonNull 126 | The `bundle` expression for initializing objects (e.g. Bundle, CharSequence, Parcelable, Serializable, Arrays), the property type must be null-able. But If we want to initialize them non-nullable type, we can initialize them to non-nullable type using the `bundleNonNull` expression. 127 | ```diff 128 | - val poster: Poster? by bundle("poster") 129 | + val poster: Poster by bundleNotNull("poster") 130 | ``` 131 | 132 | ### observeBundle 133 | We can observe the bundle data as `LiveData` using the `observeBundle` expression. If there are no extra & arguments in the Activity or Fragment, `null` will be passed to the observers. The `observeBundle` emits data only a single time to a single observer. So We can observe only once using one observer. And the observer will be unregistered from the LiveData after observing data at once. 134 | ```kotlin 135 | private val id: LiveData by observeBundle("id", -1L) 136 | private val poster: LiveData by observeBundle("poster") 137 | 138 | id.observe(this) { 139 | vm.id = it 140 | } 141 | 142 | poster.observe(this) { 143 | binding.name = it.name 144 | } 145 | ``` 146 | 147 | ### bundleValue 148 | We can also retrieve intent & arguments extra values from Activity and Fragment immediately. We can use `bundleValue`, `bundleNonNullValue`, `bundleArrayValue`, `bundleArrayListValue`. 149 | 150 | ```kotlin 151 | val id = bundleValue("id", 100L) 152 | val name = bundleValue("name", "") 153 | val poster = bundleValue("poster") 154 | ``` 155 | 156 | ## Find this library useful? :heart: 157 | Support it by joining __[stargazers](https://github.com/skydoves/bundler/stargazers)__ for this repository. :star:
158 | And __[follow](https://github.com/skydoves)__ me for my next creations! 🤩 159 | 160 | # License 161 | ```xml 162 | Copyright 2020 skydoves (Jaewoong Eum) 163 | 164 | Licensed under the Apache License, Version 2.0 (the "License"); 165 | you may not use this file except in compliance with the License. 166 | You may obtain a copy of the License at 167 | 168 | http://www.apache.org/licenses/LICENSE-2.0 169 | 170 | Unless required by applicable law or agreed to in writing, software 171 | distributed under the License is distributed on an "AS IS" BASIS, 172 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 173 | See the License for the specific language governing permissions and 174 | limitations under the License. 175 | ``` 176 | -------------------------------------------------------------------------------- /bundler/src/main/java/com/skydoves/bundler/FragmentBundleLazy.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Designed and developed by 2020 skydoves (Jaewoong Eum) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | @file:Suppress("UNCHECKED_CAST", "unused") 18 | 19 | package com.skydoves.bundler 20 | 21 | import android.os.Bundle 22 | import android.os.Parcelable 23 | import androidx.fragment.app.Fragment 24 | import java.io.Serializable 25 | 26 | /** 27 | * @author skydoves (Jaewoong Eum) 28 | * 29 | * Retrieves a primitive type of extended data from arguments lazily. 30 | * 31 | * @param key The name of the desired item. 32 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 33 | * 34 | * @throws IllegalArgumentException When a value is not a supported type of [Bundle]. 35 | */ 36 | @JvmSynthetic 37 | @InlineBundleDsl 38 | inline fun Fragment.bundle(key: String, defaultValue: T): Lazy { 39 | return fragmentVariableBundler(defaultValue) { 40 | when (defaultValue) { 41 | is Boolean -> intent.getBooleanExtra(key, defaultValue) 42 | is Byte -> intent.getByteExtra(key, defaultValue) 43 | is Char -> intent.getCharExtra(key, defaultValue) 44 | is Double -> intent.getDoubleExtra(key, defaultValue) 45 | is Float -> intent.getFloatExtra(key, defaultValue) 46 | is Int -> intent.getIntExtra(key, defaultValue) 47 | is Long -> intent.getLongExtra(key, defaultValue) 48 | is Short -> intent.getShortExtra(key, defaultValue) 49 | is CharSequence -> intent.getStringExtra(key) 50 | 51 | else -> throw IllegalArgumentException( 52 | "Illegal value type ${defaultValue.javaClass} for key \"$key\"" 53 | ) 54 | } as? T 55 | } 56 | } 57 | 58 | /** 59 | * @author skydoves (Jaewoong Eum) 60 | * 61 | * Retrieves a references type of extended data from arguments lazily. 62 | * 63 | * @param key The name of the desired item. 64 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 65 | * 66 | * @throws IllegalArgumentException When a value is not a supported type of [Bundle]. 67 | */ 68 | @JvmSynthetic 69 | @InlineBundleDsl 70 | inline fun Fragment.bundle( 71 | key: String, 72 | crossinline defaultValue: () -> T? = { null } 73 | ): Lazy { 74 | val objectType = T::class.javaObjectType 75 | return fragmentTypedBundler(defaultValue) { 76 | when { 77 | // references 78 | Bundle::class.java.isAssignableFrom(objectType) -> intent.getBundleExtra(key) as? T 79 | CharSequence::class.java.isAssignableFrom(objectType) -> intent.getCharSequenceExtra(key) as? T 80 | Parcelable::class.java.isAssignableFrom(objectType) -> intent.getParcelableExtra( 81 | key 82 | ) as? T 83 | Serializable::class.java.isAssignableFrom(objectType) -> intent.getSerializableExtra( 84 | key 85 | ) as? T 86 | 87 | // scalar arrays 88 | BooleanArray::class.java.isAssignableFrom(objectType) -> intent.getBooleanArrayExtra( 89 | key 90 | ) as? T 91 | ByteArray::class.java.isAssignableFrom(objectType) -> intent.getByteArrayExtra(key) as? T 92 | CharArray::class.java.isAssignableFrom(objectType) -> intent.getCharArrayExtra(key) as? T 93 | DoubleArray::class.java.isAssignableFrom(objectType) -> intent.getDoubleArrayExtra(key) as? T 94 | FloatArray::class.java.isAssignableFrom(objectType) -> intent.getFloatArrayExtra(key) as? T 95 | IntArray::class.java.isAssignableFrom(objectType) -> intent.getIntArrayExtra(key) as? T 96 | LongArray::class.java.isAssignableFrom(objectType) -> intent.getLongArrayExtra(key) as? T 97 | ShortArray::class.java.isAssignableFrom(objectType) -> intent.getShortArrayExtra(key) as? T 98 | 99 | else -> throw IllegalArgumentException("Illegal value type $objectType for key \"$key\"") 100 | } 101 | } 102 | } 103 | 104 | /** 105 | * @author skydoves (Jaewoong Eum) 106 | * 107 | * Retrieves a references type of extended data from arguments lazily. 108 | * 109 | * @param key The name of the desired item. 110 | * 111 | * @throws IllegalArgumentException When a value is not a supported type of [Bundle]. 112 | * @exception NullPointerException When there is no desired value from the arguments. 113 | */ 114 | @JvmSynthetic 115 | @InlineBundleDsl 116 | inline fun Fragment.bundleNonNull( 117 | key: String 118 | ): Lazy { 119 | val objectType = T::class.javaObjectType 120 | return fragmentNonNullTypedBundler { 121 | when { 122 | // references 123 | Bundle::class.java.isAssignableFrom(objectType) -> intent.getBundleExtra(key) as T 124 | CharSequence::class.java.isAssignableFrom(objectType) -> intent.getCharSequenceExtra(key) as T 125 | Parcelable::class.java.isAssignableFrom(objectType) -> intent.getParcelableExtra( 126 | key 127 | ) as T 128 | Serializable::class.java.isAssignableFrom(objectType) -> intent.getSerializableExtra( 129 | key 130 | ) as T 131 | 132 | // scalar arrays 133 | BooleanArray::class.java.isAssignableFrom(objectType) -> intent.getBooleanArrayExtra( 134 | key 135 | ) as T 136 | ByteArray::class.java.isAssignableFrom(objectType) -> intent.getByteArrayExtra(key) as T 137 | CharArray::class.java.isAssignableFrom(objectType) -> intent.getCharArrayExtra(key) as T 138 | DoubleArray::class.java.isAssignableFrom(objectType) -> intent.getDoubleArrayExtra(key) as T 139 | FloatArray::class.java.isAssignableFrom(objectType) -> intent.getFloatArrayExtra(key) as T 140 | IntArray::class.java.isAssignableFrom(objectType) -> intent.getIntArrayExtra(key) as T 141 | LongArray::class.java.isAssignableFrom(objectType) -> intent.getLongArrayExtra(key) as T 142 | ShortArray::class.java.isAssignableFrom(objectType) -> intent.getShortArrayExtra(key) as T 143 | 144 | else -> throw IllegalArgumentException("Illegal value type $objectType for key \"$key\"") 145 | } 146 | } 147 | } 148 | 149 | /** 150 | * @author skydoves (Jaewoong Eum) 151 | * 152 | * Retrieves a references array type of extended data from arguments lazily. 153 | * 154 | * @param key The name of the desired item. 155 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 156 | * 157 | * @throws IllegalArgumentException When a value is not a supported type of [Bundle]. 158 | */ 159 | @JvmSynthetic 160 | @InlineBundleDsl 161 | inline fun Fragment.bundleArray( 162 | key: String, 163 | crossinline defaultValue: () -> Array? = { null } 164 | ): Lazy?> { 165 | val javaObjectType = T::class.javaObjectType 166 | return fragmentArrayBundler(defaultValue) { 167 | ( 168 | when { 169 | String::class.java.isAssignableFrom(javaObjectType) -> intent.getStringArrayExtra(key) 170 | CharSequence::class.java.isAssignableFrom(javaObjectType) -> intent.getCharSequenceArrayExtra(key) 171 | Parcelable::class.java.isAssignableFrom(javaObjectType) -> intent.getParcelableArrayExtra(key) 172 | 173 | else -> throw IllegalArgumentException("Illegal value type $javaObjectType for key \"$key\"") 174 | } 175 | )?.filterIsInstance()?.toTypedArray() 176 | } 177 | } 178 | 179 | /** 180 | * @author skydoves (Jaewoong Eum) 181 | * 182 | * Retrieves a references array list type of extended data from arguments lazily. 183 | * 184 | * @param key The name of the desired item. 185 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 186 | * 187 | * @throws IllegalArgumentException When a value is not a supported type of [Bundle]. 188 | */ 189 | @JvmSynthetic 190 | @InlineBundleDsl 191 | inline fun Fragment.bundleArrayList( 192 | key: String, 193 | crossinline defaultValue: () -> ArrayList? = { null } 194 | ): Lazy?> { 195 | val javaObjectType = T::class.javaObjectType 196 | return fragmentArrayListBundler(defaultValue) { 197 | when { 198 | String::class.java.isAssignableFrom(javaObjectType) -> intent.getStringArrayListExtra(key) 199 | CharSequence::class.java.isAssignableFrom( 200 | javaObjectType 201 | ) -> intent.getCharSequenceArrayListExtra(key) 202 | Parcelable::class.java.isAssignableFrom( 203 | javaObjectType 204 | ) -> intent.getParcelableArrayListExtra(key) 205 | 206 | else -> throw IllegalArgumentException("Illegal value type $javaObjectType for key \"$key\"") 207 | } as? ArrayList 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /bundler/src/main/java/com/skydoves/bundler/ActivityBundleLazy.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Designed and developed by 2020 skydoves (Jaewoong Eum) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | @file:Suppress("UNCHECKED_CAST", "unused") 18 | 19 | package com.skydoves.bundler 20 | 21 | import android.app.Activity 22 | import android.os.Bundle 23 | import android.os.Parcelable 24 | import java.io.Serializable 25 | 26 | /** 27 | * @author skydoves (Jaewoong Eum) 28 | * 29 | * Retrieves a primitive type of extended data from the Intent lazily. 30 | * 31 | * @param key The name of the desired item. 32 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 33 | * 34 | * @throws IllegalArgumentException When a value is not a supported type of [Bundle]. 35 | */ 36 | @JvmSynthetic 37 | @InlineBundleDsl 38 | inline fun Activity.bundle(key: String, defaultValue: T): Lazy { 39 | return activityVariableBundler(defaultValue) { 40 | when (defaultValue) { 41 | is Boolean -> intent.getBooleanExtra(key, defaultValue) 42 | is Byte -> intent.getByteExtra(key, defaultValue) 43 | is Char -> intent.getCharExtra(key, defaultValue) 44 | is Double -> intent.getDoubleExtra(key, defaultValue) 45 | is Float -> intent.getFloatExtra(key, defaultValue) 46 | is Int -> intent.getIntExtra(key, defaultValue) 47 | is Long -> intent.getLongExtra(key, defaultValue) 48 | is Short -> intent.getShortExtra(key, defaultValue) 49 | is CharSequence -> intent.getStringExtra(key) 50 | 51 | else -> throw IllegalArgumentException( 52 | "Illegal value type ${defaultValue.javaClass} for key \"$key\"" 53 | ) 54 | } as? T 55 | } 56 | } 57 | 58 | /** 59 | * @author skydoves (Jaewoong Eum) 60 | * 61 | * Retrieves a references type of extended data from the Intent lazily. 62 | * 63 | * @param key The name of the desired item. 64 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 65 | * 66 | * @throws IllegalArgumentException When a value is not a supported type of [Bundle]. 67 | */ 68 | @JvmSynthetic 69 | @InlineBundleDsl 70 | inline fun Activity.bundle( 71 | key: String, 72 | crossinline defaultValue: () -> T? = { null } 73 | ): Lazy { 74 | val objectType = T::class.javaObjectType 75 | return activityTypedBundler(defaultValue) { 76 | when { 77 | // references 78 | Bundle::class.java.isAssignableFrom(objectType) -> intent.getBundleExtra(key) as? T 79 | CharSequence::class.java.isAssignableFrom(objectType) -> intent.getCharSequenceExtra(key) as? T 80 | Parcelable::class.java.isAssignableFrom(objectType) -> intent.getParcelableExtra( 81 | key 82 | ) as? T 83 | Serializable::class.java.isAssignableFrom(objectType) -> intent.getSerializableExtra( 84 | key 85 | ) as? T 86 | 87 | // scalar arrays 88 | BooleanArray::class.java.isAssignableFrom(objectType) -> intent.getBooleanArrayExtra( 89 | key 90 | ) as? T 91 | ByteArray::class.java.isAssignableFrom(objectType) -> intent.getByteArrayExtra(key) as? T 92 | CharArray::class.java.isAssignableFrom(objectType) -> intent.getCharArrayExtra(key) as? T 93 | DoubleArray::class.java.isAssignableFrom(objectType) -> intent.getDoubleArrayExtra(key) as? T 94 | FloatArray::class.java.isAssignableFrom(objectType) -> intent.getFloatArrayExtra(key) as? T 95 | IntArray::class.java.isAssignableFrom(objectType) -> intent.getIntArrayExtra(key) as? T 96 | LongArray::class.java.isAssignableFrom(objectType) -> intent.getLongArrayExtra(key) as? T 97 | ShortArray::class.java.isAssignableFrom(objectType) -> intent.getShortArrayExtra(key) as? T 98 | 99 | else -> throw IllegalArgumentException("Illegal value type $objectType for key \"$key\"") 100 | } 101 | } 102 | } 103 | 104 | /** 105 | * @author skydoves (Jaewoong Eum) 106 | * 107 | * Retrieves a non-null references type of extended data from the Intent lazily. 108 | * 109 | * @param key The name of the desired item. 110 | * 111 | * @throws IllegalArgumentException When a value is not a supported type of [Bundle] or null. 112 | * @exception NullPointerException When there is no desired value from the Intent. 113 | */ 114 | @JvmSynthetic 115 | @InlineBundleDsl 116 | inline fun Activity.bundleNonNull( 117 | key: String 118 | ): Lazy { 119 | val objectType = T::class.javaObjectType 120 | return activityNonNullTypedBundler { 121 | when { 122 | // references 123 | Bundle::class.java.isAssignableFrom(objectType) -> intent.getBundleExtra(key) as T 124 | CharSequence::class.java.isAssignableFrom(objectType) -> intent.getCharSequenceExtra(key) as T 125 | Parcelable::class.java.isAssignableFrom(objectType) -> intent.getParcelableExtra( 126 | key 127 | ) as T 128 | Serializable::class.java.isAssignableFrom(objectType) -> intent.getSerializableExtra( 129 | key 130 | ) as T 131 | 132 | // scalar arrays 133 | BooleanArray::class.java.isAssignableFrom(objectType) -> intent.getBooleanArrayExtra( 134 | key 135 | ) as T 136 | ByteArray::class.java.isAssignableFrom(objectType) -> intent.getByteArrayExtra(key) as T 137 | CharArray::class.java.isAssignableFrom(objectType) -> intent.getCharArrayExtra(key) as T 138 | DoubleArray::class.java.isAssignableFrom(objectType) -> intent.getDoubleArrayExtra(key) as T 139 | FloatArray::class.java.isAssignableFrom(objectType) -> intent.getFloatArrayExtra(key) as T 140 | IntArray::class.java.isAssignableFrom(objectType) -> intent.getIntArrayExtra(key) as T 141 | LongArray::class.java.isAssignableFrom(objectType) -> intent.getLongArrayExtra(key) as T 142 | ShortArray::class.java.isAssignableFrom(objectType) -> intent.getShortArrayExtra(key) as T 143 | 144 | else -> throw IllegalArgumentException("Illegal value type $objectType for key \"$key\"") 145 | } 146 | } 147 | } 148 | 149 | /** 150 | * @author skydoves (Jaewoong Eum) 151 | * 152 | * Retrieves a references array type of extended data from the Intent lazily. 153 | * 154 | * @param key The name of the desired item. 155 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 156 | * 157 | * @throws IllegalArgumentException When a value is not a supported type of [Bundle]. 158 | */ 159 | @JvmSynthetic 160 | @InlineBundleDsl 161 | inline fun Activity.bundleArray( 162 | key: String, 163 | crossinline defaultValue: () -> Array? = { null } 164 | ): Lazy?> { 165 | val javaObjectType = T::class.javaObjectType 166 | return activityArrayBundler(defaultValue) { 167 | ( 168 | when { 169 | String::class.java.isAssignableFrom(javaObjectType) -> intent.getStringArrayExtra(key) 170 | CharSequence::class.java.isAssignableFrom(javaObjectType) -> intent.getCharSequenceArrayExtra(key) 171 | Parcelable::class.java.isAssignableFrom(javaObjectType) -> intent.getParcelableArrayExtra(key) 172 | 173 | else -> throw IllegalArgumentException("Illegal value type $javaObjectType for key \"$key\"") 174 | } as? Array<*> 175 | )?.filterIsInstance()?.toTypedArray() 176 | } 177 | } 178 | 179 | /** 180 | * @author skydoves (Jaewoong Eum) 181 | * 182 | * Retrieves a references array list type of extended data from the Intent lazily. 183 | * 184 | * @param key The name of the desired item. 185 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 186 | * 187 | * @throws IllegalArgumentException When a value is not a supported type of [Bundle]. 188 | */ 189 | @JvmSynthetic 190 | @InlineBundleDsl 191 | inline fun Activity.bundleArrayList( 192 | key: String, 193 | crossinline defaultValue: () -> ArrayList? = { null } 194 | ): Lazy?> { 195 | val javaObjectType = T::class.javaObjectType 196 | return activityArrayListBundler(defaultValue) { 197 | when { 198 | String::class.java.isAssignableFrom(javaObjectType) -> intent.getStringArrayListExtra(key) 199 | CharSequence::class.java.isAssignableFrom( 200 | javaObjectType 201 | ) -> intent.getCharSequenceArrayListExtra(key) 202 | Parcelable::class.java.isAssignableFrom( 203 | javaObjectType 204 | ) -> intent.getParcelableArrayListExtra(key) 205 | 206 | else -> throw IllegalArgumentException("Illegal value type $javaObjectType for key \"$key\"") 207 | } as ArrayList? 208 | } 209 | } 210 | -------------------------------------------------------------------------------- /bundler/src/main/java/com/skydoves/bundler/FragmentBundleValue.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Designed and developed by 2020 skydoves (Jaewoong Eum) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | @file:Suppress("UNCHECKED_CAST", "unused") 18 | 19 | package com.skydoves.bundler 20 | 21 | import android.os.Bundle 22 | import android.os.Parcelable 23 | import androidx.fragment.app.Fragment 24 | import java.io.Serializable 25 | 26 | /** 27 | * @author skydoves (Jaewoong Eum) 28 | * 29 | * Retrieves a primitive type of extended data from arguments immediately. 30 | * 31 | * @param key The name of the desired item. 32 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 33 | * 34 | * @throws IllegalArgumentException When a value is not a supported type of [Bundle]. 35 | */ 36 | @JvmSynthetic 37 | @InlineBundleDsl 38 | inline fun Fragment.bundleValue(key: String, defaultValue: T): T { 39 | return fragmentVariableBundlerValue(defaultValue) { 40 | when (defaultValue) { 41 | is Boolean -> intent.getBooleanExtra(key, defaultValue) 42 | is Byte -> intent.getByteExtra(key, defaultValue) 43 | is Char -> intent.getCharExtra(key, defaultValue) 44 | is Double -> intent.getDoubleExtra(key, defaultValue) 45 | is Float -> intent.getFloatExtra(key, defaultValue) 46 | is Int -> intent.getIntExtra(key, defaultValue) 47 | is Long -> intent.getLongExtra(key, defaultValue) 48 | is Short -> intent.getShortExtra(key, defaultValue) 49 | is CharSequence -> intent.getStringExtra(key) 50 | 51 | else -> throw IllegalArgumentException( 52 | "Illegal value type ${defaultValue.javaClass} for key \"$key\"" 53 | ) 54 | } as? T 55 | } 56 | } 57 | 58 | /** 59 | * @author skydoves (Jaewoong Eum) 60 | * 61 | * Retrieves a references type of extended data from arguments immediately. 62 | * 63 | * @param key The name of the desired item. 64 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 65 | * 66 | * @throws IllegalArgumentException When a value is not a supported type of [Bundle]. 67 | */ 68 | @JvmSynthetic 69 | @InlineBundleDsl 70 | inline fun Fragment.bundleValue( 71 | key: String, 72 | crossinline defaultValue: () -> T? = { null } 73 | ): T? { 74 | val objectType = T::class.javaObjectType 75 | return fragmentTypedBundlerValue(defaultValue) { 76 | when { 77 | // references 78 | Bundle::class.java.isAssignableFrom(objectType) -> intent.getBundleExtra(key) as? T 79 | CharSequence::class.java.isAssignableFrom(objectType) -> intent.getCharSequenceExtra( 80 | key 81 | ) as? T 82 | Parcelable::class.java.isAssignableFrom(objectType) -> intent.getParcelableExtra( 83 | key 84 | ) as? T 85 | Serializable::class.java.isAssignableFrom(objectType) -> intent.getSerializableExtra( 86 | key 87 | ) as? T 88 | 89 | // scalar arrays 90 | BooleanArray::class.java.isAssignableFrom(objectType) -> intent.getBooleanArrayExtra( 91 | key 92 | ) as? T 93 | ByteArray::class.java.isAssignableFrom(objectType) -> intent.getByteArrayExtra(key) as? T 94 | CharArray::class.java.isAssignableFrom(objectType) -> intent.getCharArrayExtra(key) as? T 95 | DoubleArray::class.java.isAssignableFrom(objectType) -> intent.getDoubleArrayExtra(key) as? T 96 | FloatArray::class.java.isAssignableFrom(objectType) -> intent.getFloatArrayExtra(key) as? T 97 | IntArray::class.java.isAssignableFrom(objectType) -> intent.getIntArrayExtra(key) as? T 98 | LongArray::class.java.isAssignableFrom(objectType) -> intent.getLongArrayExtra(key) as? T 99 | ShortArray::class.java.isAssignableFrom(objectType) -> intent.getShortArrayExtra(key) as? T 100 | 101 | else -> throw IllegalArgumentException("Illegal value type $objectType for key \"$key\"") 102 | } 103 | } 104 | } 105 | 106 | /** 107 | * @author skydoves (Jaewoong Eum) 108 | * 109 | * Retrieves a references type of extended data from arguments immediately. 110 | * 111 | * @param key The name of the desired item. 112 | * 113 | * @throws IllegalArgumentException When a value is not a supported type of [Bundle]. 114 | * @exception NullPointerException When there is no desired value from the arguments. 115 | */ 116 | @JvmSynthetic 117 | @InlineBundleDsl 118 | inline fun Fragment.bundleNonNullValue( 119 | key: String 120 | ): T { 121 | val objectType = T::class.javaObjectType 122 | return fragmentNonNullTypedBundlerValue { 123 | when { 124 | // references 125 | Bundle::class.java.isAssignableFrom(objectType) -> intent.getBundleExtra(key) as T 126 | CharSequence::class.java.isAssignableFrom(objectType) -> intent.getCharSequenceExtra(key) as T 127 | Parcelable::class.java.isAssignableFrom(objectType) -> intent.getParcelableExtra( 128 | key 129 | ) as T 130 | Serializable::class.java.isAssignableFrom(objectType) -> intent.getSerializableExtra( 131 | key 132 | ) as T 133 | 134 | // scalar arrays 135 | BooleanArray::class.java.isAssignableFrom(objectType) -> intent.getBooleanArrayExtra( 136 | key 137 | ) as T 138 | ByteArray::class.java.isAssignableFrom(objectType) -> intent.getByteArrayExtra(key) as T 139 | CharArray::class.java.isAssignableFrom(objectType) -> intent.getCharArrayExtra(key) as T 140 | DoubleArray::class.java.isAssignableFrom(objectType) -> intent.getDoubleArrayExtra(key) as T 141 | FloatArray::class.java.isAssignableFrom(objectType) -> intent.getFloatArrayExtra(key) as T 142 | IntArray::class.java.isAssignableFrom(objectType) -> intent.getIntArrayExtra(key) as T 143 | LongArray::class.java.isAssignableFrom(objectType) -> intent.getLongArrayExtra(key) as T 144 | ShortArray::class.java.isAssignableFrom(objectType) -> intent.getShortArrayExtra(key) as T 145 | 146 | else -> throw IllegalArgumentException("Illegal value type $objectType for key \"$key\"") 147 | } 148 | } 149 | } 150 | 151 | /** 152 | * @author skydoves (Jaewoong Eum) 153 | * 154 | * Retrieves a references array type of extended data from arguments immediately. 155 | * 156 | * @param key The name of the desired item. 157 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 158 | * 159 | * @throws IllegalArgumentException When a value is not a supported type of [Bundle]. 160 | */ 161 | @JvmSynthetic 162 | @InlineBundleDsl 163 | inline fun Fragment.bundleArrayValue( 164 | key: String, 165 | crossinline defaultValue: () -> Array? = { null } 166 | ): Array? { 167 | val javaObjectType = T::class.javaObjectType 168 | return fragmentArrayBundlerValue(defaultValue) { 169 | ( 170 | when { 171 | String::class.java.isAssignableFrom(javaObjectType) -> intent.getStringArrayExtra(key) 172 | CharSequence::class.java.isAssignableFrom( 173 | javaObjectType 174 | ) -> intent.getCharSequenceArrayExtra(key) 175 | Parcelable::class.java.isAssignableFrom(javaObjectType) -> intent.getParcelableArrayExtra( 176 | key 177 | ) 178 | 179 | else -> throw IllegalArgumentException( 180 | "Illegal value type $javaObjectType for key \"$key\"" 181 | ) 182 | } 183 | )?.filterIsInstance()?.toTypedArray() 184 | } 185 | } 186 | 187 | /** 188 | * @author skydoves (Jaewoong Eum) 189 | * 190 | * Retrieves a references array list type of extended data from arguments immediately. 191 | * 192 | * @param key The name of the desired item. 193 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 194 | * 195 | * @throws IllegalArgumentException When a value is not a supported type of [Bundle]. 196 | */ 197 | @JvmSynthetic 198 | @InlineBundleDsl 199 | inline fun Fragment.bundleArrayListValue( 200 | key: String, 201 | crossinline defaultValue: () -> ArrayList? = { null } 202 | ): ArrayList? { 203 | val javaObjectType = T::class.javaObjectType 204 | return fragmentArrayListBundlerValue(defaultValue) { 205 | when { 206 | String::class.java.isAssignableFrom(javaObjectType) -> intent.getStringArrayListExtra(key) 207 | CharSequence::class.java.isAssignableFrom( 208 | javaObjectType 209 | ) -> intent.getCharSequenceArrayListExtra(key) 210 | Parcelable::class.java.isAssignableFrom( 211 | javaObjectType 212 | ) -> intent.getParcelableArrayListExtra(key) 213 | 214 | else -> throw IllegalArgumentException("Illegal value type $javaObjectType for key \"$key\"") 215 | } as? ArrayList 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /bundler/src/main/java/com/skydoves/bundler/ActivityBundleValue.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Designed and developed by 2020 skydoves (Jaewoong Eum) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | @file:Suppress("UNCHECKED_CAST") 18 | 19 | package com.skydoves.bundler 20 | 21 | import android.app.Activity 22 | import android.os.Bundle 23 | import android.os.Parcelable 24 | import java.io.Serializable 25 | 26 | /** 27 | * @author skydoves (Jaewoong Eum) 28 | * 29 | * Retrieves a primitive type of extended data from the Intent immediately. 30 | * 31 | * @param key The name of the desired item. 32 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 33 | * 34 | * @throws IllegalArgumentException When a value is not a supported type of [Bundle]. 35 | */ 36 | @JvmSynthetic 37 | @InlineBundleDsl 38 | inline fun Activity.bundleValue(key: String, defaultValue: T): T { 39 | return activityVariableBundlerValue(defaultValue) { 40 | when (defaultValue) { 41 | is Boolean -> intent.getBooleanExtra(key, defaultValue) 42 | is Byte -> intent.getByteExtra(key, defaultValue) 43 | is Char -> intent.getCharExtra(key, defaultValue) 44 | is Double -> intent.getDoubleExtra(key, defaultValue) 45 | is Float -> intent.getFloatExtra(key, defaultValue) 46 | is Int -> intent.getIntExtra(key, defaultValue) 47 | is Long -> intent.getLongExtra(key, defaultValue) 48 | is Short -> intent.getShortExtra(key, defaultValue) 49 | is CharSequence -> intent.getStringExtra(key) 50 | 51 | else -> throw IllegalArgumentException( 52 | "Illegal value type ${defaultValue.javaClass} for key \"$key\"" 53 | ) 54 | } as T? 55 | } 56 | } 57 | 58 | /** 59 | * @author skydoves (Jaewoong Eum) 60 | * 61 | * Retrieves a references type of extended data from the Intent immediately. 62 | * 63 | * @param key The name of the desired item. 64 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 65 | * 66 | * @throws IllegalArgumentException When a value is not a supported type of [Bundle]. 67 | */ 68 | @JvmSynthetic 69 | @InlineBundleDsl 70 | inline fun Activity.bundleValue( 71 | key: String, 72 | crossinline defaultValue: () -> T? = { null } 73 | ): T? { 74 | val objectType = T::class.javaObjectType 75 | return activityTypedBundlerValue(defaultValue) { 76 | when { 77 | // references 78 | Bundle::class.java.isAssignableFrom(objectType) -> intent.getBundleExtra(key) as? T 79 | CharSequence::class.java.isAssignableFrom(objectType) -> intent.getCharSequenceExtra( 80 | key 81 | ) as? T 82 | Parcelable::class.java.isAssignableFrom(objectType) -> intent.getParcelableExtra( 83 | key 84 | ) as? T 85 | Serializable::class.java.isAssignableFrom(objectType) -> intent.getSerializableExtra( 86 | key 87 | ) as? T 88 | 89 | // scalar arrays 90 | BooleanArray::class.java.isAssignableFrom(objectType) -> intent.getBooleanArrayExtra( 91 | key 92 | ) as? T 93 | ByteArray::class.java.isAssignableFrom(objectType) -> intent.getByteArrayExtra(key) as? T 94 | CharArray::class.java.isAssignableFrom(objectType) -> intent.getCharArrayExtra(key) as? T 95 | DoubleArray::class.java.isAssignableFrom(objectType) -> intent.getDoubleArrayExtra(key) as? T 96 | FloatArray::class.java.isAssignableFrom(objectType) -> intent.getFloatArrayExtra(key) as? T 97 | IntArray::class.java.isAssignableFrom(objectType) -> intent.getIntArrayExtra(key) as? T 98 | LongArray::class.java.isAssignableFrom(objectType) -> intent.getLongArrayExtra(key) as? T 99 | ShortArray::class.java.isAssignableFrom(objectType) -> intent.getShortArrayExtra(key) as? T 100 | 101 | else -> throw IllegalArgumentException("Illegal value type $objectType for key \"$key\"") 102 | } 103 | } 104 | } 105 | 106 | /** 107 | * @author skydoves (Jaewoong Eum) 108 | * 109 | * Retrieves a non-null references type of extended data from the Intent immediately. 110 | * 111 | * @param key The name of the desired item. 112 | * 113 | * @throws IllegalArgumentException When a value is not a supported type of [Bundle] or null. 114 | * @exception NullPointerException When there is no desired value from the Intent. 115 | */ 116 | @JvmSynthetic 117 | @InlineBundleDsl 118 | inline fun Activity.bundleNonNullValue( 119 | key: String 120 | ): T { 121 | val objectType = T::class.javaObjectType 122 | return activityNonNullTypedBundlerValue { 123 | when { 124 | // references 125 | Bundle::class.java.isAssignableFrom(objectType) -> intent.getBundleExtra(key) as T 126 | CharSequence::class.java.isAssignableFrom(objectType) -> intent.getCharSequenceExtra(key) as T 127 | Parcelable::class.java.isAssignableFrom(objectType) -> intent.getParcelableExtra( 128 | key 129 | ) as T 130 | Serializable::class.java.isAssignableFrom(objectType) -> intent.getSerializableExtra( 131 | key 132 | ) as T 133 | 134 | // scalar arrays 135 | BooleanArray::class.java.isAssignableFrom(objectType) -> intent.getBooleanArrayExtra( 136 | key 137 | ) as T 138 | ByteArray::class.java.isAssignableFrom(objectType) -> intent.getByteArrayExtra(key) as T 139 | CharArray::class.java.isAssignableFrom(objectType) -> intent.getCharArrayExtra(key) as T 140 | DoubleArray::class.java.isAssignableFrom(objectType) -> intent.getDoubleArrayExtra(key) as T 141 | FloatArray::class.java.isAssignableFrom(objectType) -> intent.getFloatArrayExtra(key) as T 142 | IntArray::class.java.isAssignableFrom(objectType) -> intent.getIntArrayExtra(key) as T 143 | LongArray::class.java.isAssignableFrom(objectType) -> intent.getLongArrayExtra(key) as T 144 | ShortArray::class.java.isAssignableFrom(objectType) -> intent.getShortArrayExtra(key) as T 145 | 146 | else -> throw IllegalArgumentException("Illegal value type $objectType for key \"$key\"") 147 | } 148 | } 149 | } 150 | 151 | /** 152 | * @author skydoves (Jaewoong Eum) 153 | * 154 | * Retrieves a references array type of extended data from the Intent immediately. 155 | * 156 | * @param key The name of the desired item. 157 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 158 | * 159 | * @throws IllegalArgumentException When a value is not a supported type of [Bundle]. 160 | */ 161 | @JvmSynthetic 162 | @InlineBundleDsl 163 | inline fun Activity.bundleArrayValue( 164 | key: String, 165 | crossinline defaultValue: () -> Array? = { null } 166 | ): Array? { 167 | val javaObjectType = T::class.javaObjectType 168 | return activityArrayBundlerValue(defaultValue) { 169 | ( 170 | when { 171 | String::class.java.isAssignableFrom(javaObjectType) -> intent.getStringArrayExtra(key) 172 | CharSequence::class.java.isAssignableFrom( 173 | javaObjectType 174 | ) -> intent.getCharSequenceArrayExtra(key) 175 | Parcelable::class.java.isAssignableFrom(javaObjectType) -> intent.getParcelableArrayExtra( 176 | key 177 | ) 178 | 179 | else -> throw IllegalArgumentException( 180 | "Illegal value type $javaObjectType for key \"$key\"" 181 | ) 182 | } as? Array<*> 183 | )?.filterIsInstance()?.toTypedArray() 184 | } 185 | } 186 | 187 | /** 188 | * @author skydoves (Jaewoong Eum) 189 | * 190 | * Retrieves a references array list type of extended data from the Intent immediately. 191 | * 192 | * @param key The name of the desired item. 193 | * @param defaultValue The value to be returned if no value of the desired type is stored with the given name. 194 | * 195 | * @throws IllegalArgumentException When a value is not a supported type of [Bundle]. 196 | */ 197 | @JvmSynthetic 198 | @InlineBundleDsl 199 | inline fun Activity.bundleArrayListValue( 200 | key: String, 201 | crossinline defaultValue: () -> ArrayList? = { null } 202 | ): ArrayList? { 203 | val javaObjectType = T::class.javaObjectType 204 | return activityArrayListBundlerValue(defaultValue) { 205 | when { 206 | String::class.java.isAssignableFrom(javaObjectType) -> intent.getStringArrayListExtra(key) 207 | CharSequence::class.java.isAssignableFrom( 208 | javaObjectType 209 | ) -> intent.getCharSequenceArrayListExtra(key) 210 | Parcelable::class.java.isAssignableFrom( 211 | javaObjectType 212 | ) -> intent.getParcelableArrayListExtra(key) 213 | 214 | else -> throw IllegalArgumentException("Illegal value type $javaObjectType for key \"$key\"") 215 | } as ArrayList? 216 | } 217 | } 218 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /bundler/src/test/java/com/skydoves/bundler/FragmentBundleLazyTest.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Designed and developed by 2020 skydoves (Jaewoong Eum) 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.skydoves.bundler 18 | 19 | import android.os.Bundle 20 | import com.skydoves.bundler.data.Poster 21 | import com.skydoves.bundler.data.PosterSerializable 22 | import com.skydoves.bundler.data.UserInfo 23 | import org.hamcrest.MatcherAssert.assertThat 24 | import org.hamcrest.core.Is.`is` 25 | import org.junit.Test 26 | import org.junit.runner.RunWith 27 | import org.robolectric.RobolectricTestRunner 28 | import org.robolectric.annotation.Config 29 | 30 | @Config(sdk = [21]) 31 | @RunWith(RobolectricTestRunner::class) 32 | class FragmentBundleLazyTest { 33 | 34 | @Test 35 | fun bundleLazyTest() { 36 | val fragment = TestFragment() 37 | fragment.arguments = intentOf { 38 | putExtra("boolean", true) 39 | putExtra("byte", Byte.MAX_VALUE) 40 | putExtra("char", 'a') 41 | putExtra("double", 1.23) 42 | putExtra("float", 1.23f) 43 | putExtra("int", 123) 44 | putExtra("long", 123L) 45 | putExtra("short", 123.toShort()) 46 | putExtra("charSequence", "skydoves") 47 | }.extras 48 | 49 | val boolean by fragment.bundle("boolean", false) 50 | assertThat(boolean, `is`(true)) 51 | 52 | val byte: Byte by fragment.bundle("byte", 0.toByte()) 53 | assertThat(byte, `is`(Byte.MAX_VALUE)) 54 | 55 | val char: Char by fragment.bundle("char", 'b') 56 | assertThat(char, `is`('a')) 57 | 58 | val double: Double by fragment.bundle("double", 0.0) 59 | assertThat(double, `is`(1.23)) 60 | 61 | val float: Float by fragment.bundle("float", 0.0f) 62 | assertThat(float, `is`(1.23f)) 63 | 64 | val int: Int by fragment.bundle("int", 0) 65 | assertThat(int, `is`(123)) 66 | 67 | val long: Long by fragment.bundle("long", 0L) 68 | assertThat(long, `is`(123L)) 69 | 70 | val short: Short by fragment.bundle("short", 0.toShort()) 71 | assertThat(short, `is`(123.toShort())) 72 | 73 | val charSequence: String by fragment.bundle("charSequence", "") 74 | assertThat(charSequence, `is`("skydoves")) 75 | } 76 | 77 | @Test 78 | fun bundleLazyDefaultValueTest() { 79 | val fragment = TestFragment() 80 | 81 | val boolean by fragment.bundle("boolean", true) 82 | assertThat(boolean, `is`(true)) 83 | 84 | val byte: Byte by fragment.bundle("byte", Byte.MAX_VALUE) 85 | assertThat(byte, `is`(Byte.MAX_VALUE)) 86 | 87 | val char: Char by fragment.bundle("char", 'a') 88 | assertThat(char, `is`('a')) 89 | 90 | val double: Double by fragment.bundle("double", 1.23) 91 | assertThat(double, `is`(1.23)) 92 | 93 | val float: Float by fragment.bundle("float", 1.23f) 94 | assertThat(float, `is`(1.23f)) 95 | 96 | val int: Int by fragment.bundle("int", 123) 97 | assertThat(int, `is`(123)) 98 | 99 | val long: Long by fragment.bundle("long", 123L) 100 | assertThat(long, `is`(123L)) 101 | 102 | val short: Short by fragment.bundle("short", 123.toShort()) 103 | assertThat(short, `is`(123.toShort())) 104 | 105 | val charSequence: String by fragment.bundle("charSequence", "skydoves") 106 | assertThat(charSequence, `is`("skydoves")) 107 | } 108 | 109 | @Test(expected = IllegalArgumentException::class) 110 | fun bundleLazyWrongTypeExceptionTest() { 111 | val mock = Poster.create() 112 | val fragment = TestFragment() 113 | fragment.arguments = intentOf { 114 | putExtra("poster", mock) 115 | }.extras 116 | 117 | val poster: Poster by fragment.bundle("poster", mock) 118 | poster.id 119 | } 120 | 121 | @Test 122 | fun bundleReferenceLazyTest() { 123 | val fragment = TestFragment() 124 | fragment.arguments = intentOf { 125 | val poster = Poster.create() 126 | val serializablePoster = PosterSerializable.create() 127 | 128 | putExtra("bundle", Bundle().apply { putString("bundleString", "skydoves") }) 129 | putExtra("charSequence", "skydoves") 130 | putExtra("parcelable", poster) 131 | putExtra("serializable", serializablePoster) 132 | putExtra("booleanArray", booleanArrayOf(true, false, true)) 133 | putExtra("byteArray", byteArrayOf(0.toByte(), 1.toByte(), 2.toByte())) 134 | putExtra("doubleArray", doubleArrayOf(0.0, 1.0, 2.0)) 135 | putExtra("floatArray", floatArrayOf(0f, 1f, 2f)) 136 | putExtra("intArray", intArrayOf(0, 1, 2)) 137 | putExtra("longArray", longArrayOf(0L, 1L, 2L)) 138 | putExtra("shortArray", shortArrayOf(0, 1, 2)) 139 | }.extras 140 | 141 | val bundle: Bundle? by fragment.bundle("bundle") 142 | assertThat(bundle?.getString("bundleString"), `is`("skydoves")) 143 | 144 | val charSequence: CharSequence? by fragment.bundle("charSequence") 145 | assertThat(charSequence, `is`("skydoves")) 146 | 147 | val parcelable: Poster? by fragment.bundle("parcelable") 148 | assertThat(parcelable, `is`(Poster.create())) 149 | 150 | val serializable: PosterSerializable? by fragment.bundle("serializable") 151 | assertThat(serializable, `is`(PosterSerializable.create())) 152 | 153 | val booleanArray: BooleanArray? by fragment.bundle("booleanArray") 154 | assertThat(booleanArray, `is`(booleanArrayOf(true, false, true))) 155 | 156 | val byteArray: ByteArray? by fragment.bundle("byteArray") 157 | assertThat(byteArray, `is`(byteArrayOf(0.toByte(), 1.toByte(), 2.toByte()))) 158 | 159 | val doubleArray: DoubleArray? by fragment.bundle("doubleArray") 160 | assertThat(doubleArray, `is`(doubleArrayOf(0.0, 1.0, 2.0))) 161 | 162 | val floatArray: FloatArray? by fragment.bundle("floatArray") 163 | assertThat(floatArray, `is`(floatArrayOf(0f, 1f, 2f))) 164 | 165 | val intArray: IntArray? by fragment.bundle("intArray") 166 | assertThat(intArray, `is`(intArrayOf(0, 1, 2))) 167 | 168 | val longArray: LongArray? by fragment.bundle("longArray") 169 | assertThat(longArray, `is`(longArrayOf(0L, 1L, 2L))) 170 | 171 | val shortArray: ShortArray? by fragment.bundle("shortArray") 172 | assertThat(shortArray, `is`(shortArrayOf(0, 1, 2))) 173 | } 174 | 175 | @Test 176 | fun bundleReferenceLazyDefaultValueTest() { 177 | val fragment = TestFragment() 178 | val poster = Poster.create() 179 | val serializablePoster = PosterSerializable.create() 180 | 181 | val bundle: Bundle? by fragment.bundle("bundle") { Bundle().apply { putString("bundleString", "skydoves") } } 182 | assertThat(bundle?.getString("bundleString"), `is`("skydoves")) 183 | 184 | val charSequence: CharSequence? by fragment.bundle("charSequence") { "skydoves" } 185 | assertThat(charSequence, `is`("skydoves")) 186 | 187 | val parcelable: Poster? by fragment.bundle("parcelable") { poster } 188 | assertThat(parcelable, `is`(Poster.create())) 189 | 190 | val serializable: PosterSerializable? by fragment.bundle("serializable") { serializablePoster } 191 | assertThat(serializable, `is`(PosterSerializable.create())) 192 | 193 | val booleanArray: BooleanArray? by fragment.bundle("booleanArray") { booleanArrayOf(true, false, true) } 194 | assertThat(booleanArray, `is`(booleanArrayOf(true, false, true))) 195 | 196 | val byteArray: ByteArray? by fragment.bundle("byteArray") { byteArrayOf(0.toByte(), 1.toByte(), 2.toByte()) } 197 | assertThat(byteArray, `is`(byteArrayOf(0.toByte(), 1.toByte(), 2.toByte()))) 198 | 199 | val doubleArray: DoubleArray? by fragment.bundle("doubleArray") { doubleArrayOf(0.0, 1.0, 2.0) } 200 | assertThat(doubleArray, `is`(doubleArrayOf(0.0, 1.0, 2.0))) 201 | 202 | val floatArray: FloatArray? by fragment.bundle("floatArray") { floatArrayOf(0f, 1f, 2f) } 203 | assertThat(floatArray, `is`(floatArrayOf(0f, 1f, 2f))) 204 | 205 | val intArray: IntArray? by fragment.bundle("intArray") { intArrayOf(0, 1, 2) } 206 | assertThat(intArray, `is`(intArrayOf(0, 1, 2))) 207 | 208 | val longArray: LongArray? by fragment.bundle("longArray") { longArrayOf(0L, 1L, 2L) } 209 | assertThat(longArray, `is`(longArrayOf(0L, 1L, 2L))) 210 | 211 | val shortArray: ShortArray? by fragment.bundle("shortArray") { shortArrayOf(0, 1, 2) } 212 | assertThat(shortArray, `is`(shortArrayOf(0, 1, 2))) 213 | } 214 | 215 | @Test(expected = IllegalArgumentException::class) 216 | fun bundleReferenceLazyWrongTypeExceptionTest() { 217 | val fragment = TestFragment() 218 | 219 | val userInfo: UserInfo? by fragment.bundle("userInfo") { UserInfo.create() } 220 | userInfo?.nickname 221 | } 222 | 223 | @Test 224 | fun bundleNonNullReferenceLazyTest() { 225 | val fragment = TestFragment() 226 | fragment.arguments = intentOf { 227 | val poster = Poster.create() 228 | val serializablePoster = PosterSerializable.create() 229 | 230 | putExtra("bundle", Bundle().apply { putString("bundleString", "skydoves") }) 231 | putExtra("charSequence", "skydoves") 232 | putExtra("parcelable", poster) 233 | putExtra("serializable", serializablePoster) 234 | putExtra("booleanArray", booleanArrayOf(true, false, true)) 235 | putExtra("byteArray", byteArrayOf(0.toByte(), 1.toByte(), 2.toByte())) 236 | putExtra("doubleArray", doubleArrayOf(0.0, 1.0, 2.0)) 237 | putExtra("floatArray", floatArrayOf(0f, 1f, 2f)) 238 | putExtra("intArray", intArrayOf(0, 1, 2)) 239 | putExtra("longArray", longArrayOf(0L, 1L, 2L)) 240 | putExtra("shortArray", shortArrayOf(0, 1, 2)) 241 | }.extras 242 | 243 | val bundle: Bundle by fragment.bundleNonNull("bundle") 244 | assertThat(bundle.getString("bundleString"), `is`("skydoves")) 245 | 246 | val charSequence: CharSequence by fragment.bundleNonNull("charSequence") 247 | assertThat(charSequence, `is`("skydoves")) 248 | 249 | val parcelable: Poster by fragment.bundleNonNull("parcelable") 250 | assertThat(parcelable, `is`(Poster.create())) 251 | 252 | val serializable: PosterSerializable by fragment.bundleNonNull("serializable") 253 | assertThat(serializable, `is`(PosterSerializable.create())) 254 | 255 | val booleanArray: BooleanArray by fragment.bundleNonNull("booleanArray") 256 | assertThat(booleanArray, `is`(booleanArrayOf(true, false, true))) 257 | 258 | val byteArray: ByteArray by fragment.bundleNonNull("byteArray") 259 | assertThat(byteArray, `is`(byteArrayOf(0.toByte(), 1.toByte(), 2.toByte()))) 260 | 261 | val doubleArray: DoubleArray by fragment.bundleNonNull("doubleArray") 262 | assertThat(doubleArray, `is`(doubleArrayOf(0.0, 1.0, 2.0))) 263 | 264 | val floatArray: FloatArray by fragment.bundleNonNull("floatArray") 265 | assertThat(floatArray, `is`(floatArrayOf(0f, 1f, 2f))) 266 | 267 | val intArray: IntArray by fragment.bundleNonNull("intArray") 268 | assertThat(intArray, `is`(intArrayOf(0, 1, 2))) 269 | 270 | val longArray: LongArray by fragment.bundleNonNull("longArray") 271 | assertThat(longArray, `is`(longArrayOf(0L, 1L, 2L))) 272 | 273 | val shortArray: ShortArray by fragment.bundleNonNull("shortArray") 274 | assertThat(shortArray, `is`(shortArrayOf(0, 1, 2))) 275 | } 276 | 277 | @Test(expected = java.lang.IllegalArgumentException::class) 278 | fun bundleNonNullReferenceLazyWrongTypeExceptionTest() { 279 | val fragment = TestFragment() 280 | 281 | val userInfo: UserInfo by fragment.bundleNonNull("userInfo") 282 | userInfo.nickname 283 | } 284 | 285 | @Test(expected = NullPointerException::class) 286 | fun bundleNonNullReferenceLazyNoValueIncludedExceptionTest() { 287 | val fragment = TestFragment() 288 | 289 | val poster: Poster by fragment.bundleNonNull("poster") 290 | poster.name 291 | } 292 | 293 | @Test 294 | fun bundleArrayLazyTest() { 295 | val fragment = TestFragment() 296 | val poster = Poster.create() 297 | fragment.arguments = intentOf { 298 | putExtra("stringArray", arrayOf("skydoves0", "skydoves1", "skydoves2")) 299 | putExtra("charSequenceArray", arrayOf("skydoves0", "skydoves1", "skydoves2")) 300 | putExtra("parcelableArray", arrayOf(poster, poster, poster)) 301 | }.extras 302 | 303 | val stringArray by fragment.bundleArray("stringArray") 304 | assertThat(stringArray?.size, `is`(3)) 305 | assertThat(stringArray?.get(0), `is`("skydoves0")) 306 | 307 | val charSequenceArray by fragment.bundleArray("charSequenceArray") 308 | assertThat(charSequenceArray?.size, `is`(3)) 309 | assertThat(charSequenceArray?.get(0), `is`("skydoves0")) 310 | 311 | val parcelableArray by fragment.bundleArray("parcelableArray") 312 | assertThat(parcelableArray?.size, `is`(3)) 313 | assertThat(parcelableArray?.get(0), `is`(poster)) 314 | } 315 | 316 | @Test 317 | fun bundleArrayLazyDefaultValueTest() { 318 | val fragment = TestFragment() 319 | val poster = Poster.create() 320 | 321 | val stringArray by fragment.bundleArray("stringArray") { 322 | arrayOf("skydoves0", "skydoves1", "skydoves2") 323 | } 324 | assertThat(stringArray?.size, `is`(3)) 325 | assertThat(stringArray?.get(0), `is`("skydoves0")) 326 | 327 | val charSequenceArray by fragment.bundleArray("charSequenceArray") { 328 | arrayOf("skydoves0", "skydoves1", "skydoves2") 329 | } 330 | assertThat(charSequenceArray?.size, `is`(3)) 331 | assertThat(charSequenceArray?.get(0), `is`("skydoves0")) 332 | 333 | val parcelableArray by fragment.bundleArray("parcelableArray") { 334 | arrayOf(poster, poster, poster) 335 | } 336 | assertThat(parcelableArray?.size, `is`(3)) 337 | assertThat(parcelableArray?.get(0), `is`(poster)) 338 | } 339 | 340 | @Test(expected = IllegalArgumentException::class) 341 | fun bundleArrayLazyWrongTypeExceptionTest() { 342 | val fragment = TestFragment() 343 | 344 | val userInfo by fragment.bundleArray("userInfo") { arrayOf(UserInfo.create()) } 345 | userInfo?.get(0) 346 | } 347 | 348 | @Test 349 | fun bundleArrayListLazyTest() { 350 | val fragment = TestFragment() 351 | val poster = Poster.create() 352 | fragment.arguments = intentOf { 353 | putExtra("stringArrayList", arrayListOf("skydoves0", "skydoves1", "skydoves2")) 354 | putExtra("charSequenceArrayList", arrayListOf("skydoves0", "skydoves1", "skydoves2")) 355 | putExtra("parcelableArrayList", arrayListOf(poster, poster, poster)) 356 | }.extras 357 | 358 | val stringArrayList by fragment.bundleArrayList("stringArrayList") 359 | assertThat(stringArrayList?.size, `is`(3)) 360 | assertThat(stringArrayList?.get(0), `is`("skydoves0")) 361 | 362 | val charSequenceArrayList by fragment.bundleArrayList("charSequenceArrayList") 363 | assertThat(charSequenceArrayList?.size, `is`(3)) 364 | assertThat(charSequenceArrayList?.get(0), `is`("skydoves0")) 365 | 366 | val parcelableArrayList by fragment.bundleArrayList("parcelableArrayList") 367 | assertThat(parcelableArrayList?.size, `is`(3)) 368 | assertThat(parcelableArrayList?.get(0), `is`(poster)) 369 | } 370 | 371 | @Test 372 | fun bundleArrayLsitLazyDefaultValueTest() { 373 | val fragment = TestFragment() 374 | val poster = Poster.create() 375 | 376 | val stringArrayList by fragment.bundleArrayList("stringArrayList") { 377 | arrayListOf("skydoves0", "skydoves1", "skydoves2") 378 | } 379 | assertThat(stringArrayList?.size, `is`(3)) 380 | assertThat(stringArrayList?.get(0), `is`("skydoves0")) 381 | 382 | val charSequenceArrayList by fragment.bundleArrayList("charSequenceArrayList") { 383 | arrayListOf("skydoves0", "skydoves1", "skydoves2") 384 | } 385 | assertThat(charSequenceArrayList?.size, `is`(3)) 386 | assertThat(charSequenceArrayList?.get(0), `is`("skydoves0")) 387 | 388 | val parcelableArrayList by fragment.bundleArrayList("parcelableArrayList") { 389 | arrayListOf(poster, poster, poster) 390 | } 391 | assertThat(parcelableArrayList?.size, `is`(3)) 392 | assertThat(parcelableArrayList?.get(0), `is`(poster)) 393 | } 394 | 395 | @Test(expected = IllegalArgumentException::class) 396 | fun bundleArrayListLazyWrongTypeExceptionTest() { 397 | val fragment = TestFragment() 398 | 399 | val userInfo by fragment.bundleArrayList("userInfo") { arrayListOf(UserInfo.create()) } 400 | userInfo?.get(0) 401 | } 402 | } 403 | --------------------------------------------------------------------------------