├── .github ├── FUNDING.yml └── workflows │ ├── codacy-analysis.yml │ └── publish.yml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── _config.yml ├── app ├── .gitignore ├── build.gradle ├── detekt-baseline.xml ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── techpaliyal │ │ └── androidkotlinmvvm │ │ ├── CustomFailureHandler.kt │ │ ├── ExampleInstrumentedTest.kt │ │ └── ui │ │ └── activity │ │ └── MainActivityTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── techpaliyal │ │ │ └── androidkotlinmvvm │ │ │ ├── extensions │ │ │ ├── ImageViewExtensions.kt │ │ │ └── RecyclerViewPagination.kt │ │ │ ├── listeners │ │ │ ├── BasicListener.kt │ │ │ └── UsersListener.kt │ │ │ ├── model │ │ │ ├── BasicModel.kt │ │ │ ├── MultiSelectModel.kt │ │ │ └── UserModel.kt │ │ │ ├── ui │ │ │ ├── activity │ │ │ │ ├── BasicListingActivity.kt │ │ │ │ ├── BindingAdapterTestActivity.kt │ │ │ │ ├── LoadingListingActivity.kt │ │ │ │ ├── MainActivity.kt │ │ │ │ ├── MultiSelectListingActivity.kt │ │ │ │ ├── PaginationListingActivity.kt │ │ │ │ ├── SelectMultipleViewTypeExampleActivity.kt │ │ │ │ ├── ShimmerListingActivity.kt │ │ │ │ └── UserListingActivity.kt │ │ │ ├── multiple_view │ │ │ │ ├── HeadingModel.kt │ │ │ │ ├── ListItemModel.kt │ │ │ │ ├── MultipleViewTypeActivity.kt │ │ │ │ ├── MultipleViewTypeViewModel.kt │ │ │ │ └── SchoolListing.kt │ │ │ ├── multiple_view_example_2 │ │ │ │ ├── ChatListing.kt │ │ │ │ ├── HeadingModel.kt │ │ │ │ ├── ListItems.kt │ │ │ │ ├── MultipleViewChatViewModel.kt │ │ │ │ └── MultipleViewTypeChat.kt │ │ │ └── view_model │ │ │ │ ├── BasicListingActivityViewModel.kt │ │ │ │ ├── BindingTestViewModel.kt │ │ │ │ ├── LoadingListingViewModel.kt │ │ │ │ ├── MultiSelectListingActivityViewModel.kt │ │ │ │ ├── UserListingActivityViewModel.kt │ │ │ │ └── ViewModelFactory.kt │ │ │ └── utils │ │ │ └── StringHelper.kt │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── ic_launcher_background.xml │ │ ├── ic_round_thumb_up_24.xml │ │ ├── ic_round_thumb_up_24_red.xml │ │ └── ic_thumb.xml │ │ ├── layout │ │ ├── activity_binding_adapter_test.xml │ │ ├── activity_listing.xml │ │ ├── activity_main.xml │ │ ├── activity_multiple_view_type.xml │ │ ├── activity_multiple_view_type_example_2.xml │ │ ├── activity_select_multiple_view_type_example_activity.xml │ │ ├── item_chat_header.xml │ │ ├── item_error.xml │ │ ├── item_heading.xml │ │ ├── item_list.xml │ │ ├── item_loading_more.xml │ │ ├── item_multi_select.xml │ │ ├── item_row_message_received.xml │ │ ├── item_row_message_sent.xml │ │ ├── item_simple.xml │ │ ├── item_user.xml │ │ ├── item_user_shimmer.xml │ │ └── layout_loading_full_page.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.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 │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── techpaliyal │ └── androidkotlinmvvm │ └── ExampleUnitTest.kt ├── build.gradle ├── docs ├── _config.yml └── index.md ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── images ├── Screenshot_20201019-224331.jpg ├── Screenshot_20201019-224335.jpg ├── Screenshot_20201019-224339.jpg ├── Screenshot_20201019-224344.jpg ├── Universal Recycler View.jpg ├── universal_recycler_view_multiple_view_type.png ├── user-list-pagination.gif ├── user-list-progress.gif └── user-list-shimmer.gif ├── multiple_view_type_example_2.jpg ├── renovate.json ├── scripts ├── publish-module.gradle └── publish-root.gradle ├── settings.gradle ├── universal_adapter ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── gradle.properties ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── yogeshpaliyal │ │ └── universalAdapter │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── yogeshpaliyal │ │ │ └── universalAdapter │ │ │ ├── adapter │ │ │ ├── ContentListAdapter.kt │ │ │ ├── ErrorAdapter.kt │ │ │ ├── LoadingAdapter.kt │ │ │ ├── LoadingFooterAdapter.kt │ │ │ ├── NoDataAdapter.kt │ │ │ ├── SectionAdapter.kt │ │ │ ├── SectionUniversalRecyclerAdapterBuilder.kt │ │ │ ├── UniversalAdapterViewType.kt │ │ │ └── UniversalRecyclerAdapter.kt │ │ │ ├── extensions │ │ │ └── BindingAdaptersUtils.kt │ │ │ ├── listener │ │ │ └── UniversalViewType.kt │ │ │ ├── model │ │ │ └── BaseDiffUtil.kt │ │ │ └── utils │ │ │ ├── Constans.kt │ │ │ ├── Resource.kt │ │ │ ├── Status.kt │ │ │ └── StringHelper.kt │ └── res │ │ └── layout │ │ └── item_simple.xml │ └── test │ └── java │ └── com │ └── yogeshpaliyal │ └── universalAdapter │ └── ExampleUnitTest.kt └── universal_recycler_view_multiple_view_type.png /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: yogeshpaliyal # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: yogeshpaliyal 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: yogeshpaliyal 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.github/workflows/codacy-analysis.yml: -------------------------------------------------------------------------------- 1 | # This workflow checks out code, performs a Codacy security scan 2 | # and integrates the results with the 3 | # GitHub Advanced Security code scanning feature. For more information on 4 | # the Codacy security scan action usage and parameters, see 5 | # https://github.com/codacy/codacy-analysis-cli-action. 6 | # For more information on Codacy Analysis CLI in general, see 7 | # https://github.com/codacy/codacy-analysis-cli. 8 | 9 | name: Codacy Security Scan 10 | 11 | on: 12 | push: 13 | branches: [ master ] 14 | pull_request: 15 | # The branches below must be a subset of the branches above 16 | branches: [ master ] 17 | schedule: 18 | - cron: '20 15 * * 3' 19 | 20 | jobs: 21 | codacy-security-scan: 22 | name: Codacy Security Scan 23 | runs-on: ubuntu-latest 24 | steps: 25 | # Checkout the repository to the GitHub Actions runner 26 | - name: Checkout code 27 | uses: actions/checkout@v2 28 | 29 | # Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis 30 | - name: Run Codacy Analysis CLI 31 | uses: codacy/codacy-analysis-cli-action@1.1.0 32 | with: 33 | # Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository 34 | # You can also omit the token and run the tools that support default configurations 35 | project-token: ${{ secrets.CODACY_PROJECT_TOKEN }} 36 | verbose: true 37 | output: results.sarif 38 | format: sarif 39 | # Adjust severity of non-security issues 40 | gh-code-scanning-compat: true 41 | # Force 0 exit code to allow SARIF file generation 42 | # This will handover control about PR rejection to the GitHub side 43 | max-allowed-issues: 2147483647 44 | 45 | # Upload the SARIF file generated in the previous step 46 | - name: Upload SARIF results file 47 | uses: github/codeql-action/upload-sarif@v1 48 | with: 49 | sarif_file: results.sarif 50 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | 3 | on: 4 | release: 5 | # We'll run this workflow when a new GitHub release is created 6 | types: [released] 7 | 8 | jobs: 9 | publish: 10 | name: Release build and publish 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Check out code 14 | uses: actions/checkout@v2 15 | - name: Set up JDK 11 16 | uses: actions/setup-java@v2 17 | with: 18 | distribution: adopt 19 | java-version: 11 20 | 21 | - name: Grant Gradlew rights 22 | run: chmod +x gradlew 23 | 24 | # Builds the release artifacts of the library 25 | - name: Release build 26 | run: ./gradlew :speld:assembleRelease 27 | 28 | - name: Publish Library 29 | run: | 30 | echo "Publishing library🚀" 31 | ./gradlew publish --no-daemon --no-parallel 32 | echo "Published✅" 33 | echo "Releasing repository...🚀" 34 | ./gradlew closeAndReleaseRepository 35 | echo "Released✅" 36 | env: 37 | ORG_GRADLE_PROJECT_VERSION_NAME: ${{ github.event.release.tag_name }} 38 | ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.SIGNING_KEY }} 39 | ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.SIGNING_PASSWORD }} 40 | ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.OSSRH_USERNAME }} 41 | ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.OSSRH_PASSWORD }} 42 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/gradle.xml 10 | /.idea/assetWizardSettings.xml 11 | .DS_Store 12 | /build 13 | /captures 14 | .externalNativeBuild 15 | .cxx 16 | /github.properties -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at paliyalyogesh@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Yogesh Choudhary Paliyal 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ![Maven metadata URL](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Frepo1.maven.org%2Fmaven2%2Fcom%2Fyogeshpaliyal%2Funiversal-adapter%2Fmaven-metadata.xml) 3 | 4 | [![GitHub issues](https://img.shields.io/github/issues/yogeshpaliyal/Android-Universal-Recycler-View-Adapter?style=for-the-badge)](https://github.com/yogeshpaliyal/Android-Universal-Recycler-View-Adapter/issues) 5 | [![GitHub forks](https://img.shields.io/github/forks/yogeshpaliyal/Android-Universal-Recycler-View-Adapter?style=for-the-badge)](https://github.com/yogeshpaliyal/Android-Universal-Recycler-View-Adapter/network) 6 | [![GitHub stars](https://img.shields.io/github/stars/yogeshpaliyal/Android-Universal-Recycler-View-Adapter?style=for-the-badge)](https://github.com/yogeshpaliyal/Android-Universal-Recycler-View-Adapter/stargazers) 7 | [![GitHub license](https://img.shields.io/github/license/yogeshpaliyal/Android-Universal-Recycler-View-Adapter?style=for-the-badge)](https://github.com/yogeshpaliyal/Android-Universal-Recycler-View-Adapter/blob/master/LICENSE) 8 | [![Twitter](https://img.shields.io/twitter/url?style=for-the-badge&url=https%3A%2F%2Ftwitter.com%2Fyogeshpaliyal)](https://twitter.com/intent/tweet?text=Wow:&url=https%3A%2F%2Fgithub.com%2Fyogeshpaliyal%2FAndroid-Universal-Recycler-View-Adapter) 9 | 10 | # Android Universal Recycler Adapter 11 | 12 | Tired of creating 100s of Adapters and View Models. 13 | This Library will make it easy, No need to create a Adapter, ViewHolder for every list 14 | 15 | ![Cover Image](https://raw.githubusercontent.com/yogeshpaliyal/Android-Universal-Recycler-View-Adapter/master/images/Universal%20Recycler%20View.jpg) 16 | 17 | ## 🤔 How? 18 | Using Resource Pattern to find the status of the list and show view types according to that. 19 | 20 | 21 | ### Step #1. Add the `mavenCentral()` to your root buuld.gradle: 22 | ```gradle 23 | allprojects { 24 | repositories { 25 | ... 26 | mavenCentral() 27 | } 28 | } 29 | ``` 30 | 31 | ### 2. Add Dependency repository to your build file: 32 | ![Maven metadata URL](https://img.shields.io/maven-metadata/v?metadataUrl=https%3A%2F%2Frepo1.maven.org%2Fmaven2%2Fcom%2Fyogeshpaliyal%2Funiversal-adapter%2Fmaven-metadata.xml) 33 | 34 | ```groovy 35 | dependencies { 36 | implementation 'com.yogeshpaliyal:universal-adapter:3.0.0' 37 | } 38 | ``` 39 | 40 | ## 🛠️ Used in this Project 41 | 42 | * [List Adapter](https://developer.android.com/reference/androidx/recyclerview/widget/ListAdapter) 43 | * [Async DiffUtil](https://developer.android.com/reference/androidx/recyclerview/widget/DiffUtil) 44 | * [Resource & Status Util Classes](https://blog.mindorks.com/mvvm-architecture-android-tutorial-for-beginners-step-by-step-guide) 45 | 46 | 47 | ## 🤩 Features 48 | 49 | - Content Listing (Supports Multiple View Types) 50 | - Loading + Listing (Showing shimmer items for Loading then showing the actual Listing) 51 | - Loading + LoadMore (Showing loading items and add a item at bottom to create infinite Listing) 52 | - No Data Found 53 | - Error Page 54 | - Async DiffUtils for better performance 55 | 56 | 57 | 58 | 59 | ### When to show which item? 60 | 61 | Status| List Size| Result Behaviour 62 | ---|---|--- 63 | LOADING |0 |Show Loading Cells (default 5 items) 64 | SUCCESS |0 |No Record Found Layout will be displayed 65 | ERROR |0| Error Layout Shown 66 | LOADING |more than 0| Data Cells + load more at end 67 | SUCCESS |more than 0| Data Cells 68 | ERROR |more than 0| Data Cells + error cell at end 69 | 70 | 71 | 72 | ## 📚 For more info Check [Wiki](https://github.com/yogeshpaliyal/Android-Universal-Recycler-View-Adapter/wiki) 73 | ### General 74 | - [Intro](https://github.com/yogeshpaliyal/Android-Universal-Recycler-View-Adapter/wiki/Intro) 75 | - [Features & Logic Table](https://github.com/yogeshpaliyal/Android-Universal-Recycler-View-Adapter/wiki/Features-&-Logic-Table) 76 | - [Implementation](https://github.com/yogeshpaliyal/Android-Universal-Recycler-View-Adapter/wiki/Implement) 77 | - [Getting started](https://github.com/yogeshpaliyal/Android-Universal-Recycler-View-Adapter/wiki/Getting-Started) 78 | - [XML Variables](https://github.com/yogeshpaliyal/Android-Universal-Recycler-View-Adapter/wiki/XML-Variables) 79 | 80 | 81 | ### Examples 82 | - [Simple List](https://github.com/yogeshpaliyal/Android-Universal-Recycler-View-Adapter/wiki/Simple-List) 83 | - [Loading, Content , Error](https://github.com/yogeshpaliyal/Android-Universal-Recycler-View-Adapter/wiki/Loading,-Content,-Error) 84 | 85 | - [Multiple View Types](https://github.com/yogeshpaliyal/Android-Universal-Recycler-View-Adapter/wiki/Multiple-View-Types) 86 | - [Example 1](https://github.com/yogeshpaliyal/Android-Universal-Recycler-View-Adapter/wiki/Multiple-View-Types#example-1) 87 | - [Example 2](https://github.com/yogeshpaliyal/Android-Universal-Recycler-View-Adapter/wiki/Multiple-View-Types#example-2) 88 | 89 | ## Feedback 90 | 91 | 92 | Having any issue to get you are looking for, feel free to put your question in [Discussion Section](https://github.com/yogeshpaliyal/Android-Universal-Recycler-View-Adapter/discussions) and help us Improving this library and Documentation. 93 | 94 | **Happy Coding 😁** 95 | 96 | 97 | ``` 98 | MIT License 99 | 100 | Copyright (c) 2021 Yogesh Choudhary Paliyal 101 | 102 | Permission is hereby granted, free of charge, to any person obtaining a copy 103 | of this software and associated documentation files (the "Software"), to deal 104 | in the Software without restriction, including without limitation the rights 105 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 106 | copies of the Software, and to permit persons to whom the Software is 107 | furnished to do so, subject to the following conditions: 108 | 109 | The above copyright notice and this permission notice shall be included in all 110 | copies or substantial portions of the Software. 111 | 112 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 113 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 114 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 115 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 116 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 117 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 118 | SOFTWARE. 119 | ``` 120 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | remote_theme: pages-themes/cayman@v0.2.0 2 | plugins: 3 | - jekyll-remote-theme # add this line to the plugins list if you already have one 4 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | apply plugin: 'kotlin-android' 4 | apply plugin: 'kotlin-kapt' 5 | apply plugin: "io.gitlab.arturbosch.detekt" 6 | 7 | 8 | android { 9 | compileSdkVersion 29 10 | buildToolsVersion "29.0.2" 11 | defaultConfig { 12 | applicationId "com.techpaliyal.androidkotlinmvvm" 13 | minSdkVersion 16 14 | targetSdkVersion 29 15 | versionCode 1 16 | versionName "1.0" 17 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 18 | } 19 | buildTypes { 20 | release { 21 | minifyEnabled false 22 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 23 | } 24 | } 25 | 26 | // todo step1 27 | dataBinding { 28 | enabled = true 29 | } 30 | compileOptions { 31 | sourceCompatibility JavaVersion.VERSION_1_8 32 | targetCompatibility JavaVersion.VERSION_1_8 33 | } 34 | } 35 | 36 | dependencies { 37 | def lifecycle_version = "2.3.1" 38 | implementation fileTree(dir: 'libs', include: ['*.jar']) 39 | 40 | implementation project(':universal_adapter') 41 | 42 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 43 | implementation 'androidx.appcompat:appcompat:1.3.1' 44 | implementation 'androidx.core:core-ktx:1.6.0' 45 | implementation 'androidx.constraintlayout:constraintlayout:2.1.1' 46 | 47 | testImplementation 'junit:junit:4.13.2' 48 | androidTestImplementation 'androidx.test:core-ktx:1.4.0' 49 | androidTestImplementation 'androidx.test.ext:junit-ktx:1.1.3' 50 | androidTestImplementation 'androidx.test.ext:junit:1.1.3' 51 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' 52 | 53 | androidTestImplementation 'androidx.test:runner:1.4.0' 54 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' 55 | 56 | 57 | //todo step 2 58 | implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' 59 | implementation 'com.google.android.material:material:1.4.0' 60 | implementation 'com.makeramen:roundedimageview:2.3.0' 61 | // ViewModel 62 | implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version" 63 | // LiveData 64 | implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version" 65 | 66 | // shimmer animation 67 | implementation 'com.facebook.shimmer:shimmer:0.5.0' 68 | 69 | 70 | implementation 'com.github.bumptech.glide:glide:4.12.0' 71 | annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0' 72 | 73 | implementation 'com.google.android.flexbox:flexbox:3.0.0' 74 | // implementation "androidx.paging:paging-runtime-ktx:3.0.0-alpha11" 75 | 76 | } 77 | -------------------------------------------------------------------------------- /app/detekt-baseline.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | EmptyClassBlock:SchoolListing.kt$SchoolListing${ } 6 | EmptyDefaultConstructor:BindingTestViewModel.kt$BindingTestViewModel$() 7 | MagicNumber:BindingTestViewModel.kt$BindingTestViewModel$3000 8 | MagicNumber:LoadingListingViewModel.kt$LoadingListingViewModel$10 9 | MagicNumber:LoadingListingViewModel.kt$LoadingListingViewModel$3000 10 | MaxLineLength:BindingTestViewModel.kt$BindingTestViewModel$tempArr.add(UserModel(name = "Yogesh",image = "https://randomuser.me/api/portraits/men/52.jpg", address = "Jodhpur")) 11 | MaxLineLength:UserListingActivityViewModel.kt$UserListingActivityViewModel$tempArr.add(UserModel(name = "Yogesh",image = "https://randomuser.me/api/portraits/men/52.jpg", address = "Jodhpur")) 12 | MaxLineLength:UserModel.kt$UserModel$data 13 | NewLineAtEndOfFile:BasicListener.kt$com.techpaliyal.androidkotlinmvvm.listeners.BasicListener.kt 14 | NewLineAtEndOfFile:BasicListingActivityViewModel.kt$com.techpaliyal.androidkotlinmvvm.ui.view_model.BasicListingActivityViewModel.kt 15 | NewLineAtEndOfFile:BasicModel.kt$com.techpaliyal.androidkotlinmvvm.model.BasicModel.kt 16 | NewLineAtEndOfFile:BindingAdapterTestActivity.kt$com.techpaliyal.androidkotlinmvvm.ui.activity.BindingAdapterTestActivity.kt 17 | NewLineAtEndOfFile:BindingTestViewModel.kt$com.techpaliyal.androidkotlinmvvm.ui.view_model.BindingTestViewModel.kt 18 | NewLineAtEndOfFile:HeadingModel.kt$com.techpaliyal.androidkotlinmvvm.ui.multiple_view.HeadingModel.kt 19 | NewLineAtEndOfFile:ImageViewExtensions.kt$com.techpaliyal.androidkotlinmvvm.extensions.ImageViewExtensions.kt 20 | NewLineAtEndOfFile:ListItemModel.kt$com.techpaliyal.androidkotlinmvvm.ui.multiple_view.ListItemModel.kt 21 | NewLineAtEndOfFile:LoadingListingActivity.kt$com.techpaliyal.androidkotlinmvvm.ui.activity.LoadingListingActivity.kt 22 | NewLineAtEndOfFile:LoadingListingViewModel.kt$com.techpaliyal.androidkotlinmvvm.ui.view_model.LoadingListingViewModel.kt 23 | NewLineAtEndOfFile:MultiSelectListingActivityViewModel.kt$com.techpaliyal.androidkotlinmvvm.ui.view_model.MultiSelectListingActivityViewModel.kt 24 | NewLineAtEndOfFile:MultiSelectModel.kt$com.techpaliyal.androidkotlinmvvm.model.MultiSelectModel.kt 25 | NewLineAtEndOfFile:MultipleViewTypeActivity.kt$com.techpaliyal.androidkotlinmvvm.ui.multiple_view.MultipleViewTypeActivity.kt 26 | NewLineAtEndOfFile:MultipleViewTypeViewModel.kt$com.techpaliyal.androidkotlinmvvm.ui.multiple_view.MultipleViewTypeViewModel.kt 27 | NewLineAtEndOfFile:PaginationListingActivity.kt$com.techpaliyal.androidkotlinmvvm.ui.activity.PaginationListingActivity.kt 28 | NewLineAtEndOfFile:RecyclerViewPagination.kt$com.techpaliyal.androidkotlinmvvm.extensions.RecyclerViewPagination.kt 29 | NewLineAtEndOfFile:SchoolListing.kt$com.techpaliyal.androidkotlinmvvm.ui.multiple_view.SchoolListing.kt 30 | NewLineAtEndOfFile:ShimmerListingActivity.kt$com.techpaliyal.androidkotlinmvvm.ui.activity.ShimmerListingActivity.kt 31 | NewLineAtEndOfFile:StringHelper.kt$com.techpaliyal.androidkotlinmvvm.utils.StringHelper.kt 32 | NewLineAtEndOfFile:UserListingActivityViewModel.kt$com.techpaliyal.androidkotlinmvvm.ui.view_model.UserListingActivityViewModel.kt 33 | NewLineAtEndOfFile:UserModel.kt$com.techpaliyal.androidkotlinmvvm.model.UserModel.kt 34 | NewLineAtEndOfFile:UsersListener.kt$com.techpaliyal.androidkotlinmvvm.listeners.UsersListener.kt 35 | NewLineAtEndOfFile:ViewModelFactory.kt$com.techpaliyal.androidkotlinmvvm.ui.view_model.ViewModelFactory.kt 36 | PackageNaming:BasicListingActivityViewModel.kt$package com.techpaliyal.androidkotlinmvvm.ui.view_model 37 | PackageNaming:BindingTestViewModel.kt$package com.techpaliyal.androidkotlinmvvm.ui.view_model 38 | PackageNaming:HeadingModel.kt$package com.techpaliyal.androidkotlinmvvm.ui.multiple_view 39 | PackageNaming:ListItemModel.kt$package com.techpaliyal.androidkotlinmvvm.ui.multiple_view 40 | PackageNaming:LoadingListingViewModel.kt$package com.techpaliyal.androidkotlinmvvm.ui.view_model 41 | PackageNaming:MultiSelectListingActivityViewModel.kt$package com.techpaliyal.androidkotlinmvvm.ui.view_model 42 | PackageNaming:MultipleViewTypeActivity.kt$package com.techpaliyal.androidkotlinmvvm.ui.multiple_view 43 | PackageNaming:MultipleViewTypeViewModel.kt$package com.techpaliyal.androidkotlinmvvm.ui.multiple_view 44 | PackageNaming:SchoolListing.kt$package com.techpaliyal.androidkotlinmvvm.ui.multiple_view 45 | PackageNaming:UserListingActivityViewModel.kt$package com.techpaliyal.androidkotlinmvvm.ui.view_model 46 | PackageNaming:ViewModelFactory.kt$package com.techpaliyal.androidkotlinmvvm.ui.view_model 47 | UnusedPrivateMember:LoadingListingViewModel.kt$LoadingListingViewModel$i 48 | VariableNaming:RecyclerViewPagination.kt$val VISIBLE_THRESHOLD: Int = RECYCLER_PAGING_THRESHOLD 49 | WildcardImport:BindingTestViewModel.kt$import androidx.lifecycle.* 50 | 51 | 52 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/techpaliyal/androidkotlinmvvm/CustomFailureHandler.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm 2 | 3 | import android.view.View 4 | import androidx.test.espresso.FailureHandler 5 | import org.hamcrest.Matcher 6 | 7 | class CustomFailureHandler: FailureHandler { 8 | override fun handle(error: Throwable?, viewMatcher: Matcher?) { 9 | assert(false) 10 | } 11 | } -------------------------------------------------------------------------------- /app/src/androidTest/java/com/techpaliyal/androidkotlinmvvm/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm 2 | 3 | import androidx.test.platform.app.InstrumentationRegistry 4 | import androidx.test.ext.junit.runners.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getInstrumentation().targetContext 22 | assertEquals("com.techpaliyal.androidkotlinmvvm", appContext.packageName) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/techpaliyal/androidkotlinmvvm/ui/activity/MainActivityTest.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.ui.activity 2 | 3 | import androidx.test.espresso.Espresso.* 4 | import androidx.test.espresso.FailureHandler 5 | import androidx.test.espresso.action.ViewActions.click 6 | import androidx.test.espresso.matcher.ViewMatchers.withId 7 | import androidx.test.ext.junit.rules.ActivityScenarioRule 8 | import androidx.test.ext.junit.runners.AndroidJUnit4 9 | import com.techpaliyal.androidkotlinmvvm.R 10 | import org.junit.Assert.* 11 | import org.junit.Before 12 | import org.junit.Rule 13 | import org.junit.Test 14 | import org.junit.runner.RunWith 15 | 16 | @RunWith(AndroidJUnit4::class) 17 | class MainActivityTest(){ 18 | 19 | @Rule 20 | @JvmField 21 | public var activityScenarioRule = ActivityScenarioRule(MainActivity::class.java) 22 | 23 | @Before 24 | fun before(){ 25 | /* setFailureHandler(FailureHandler { error, viewMatcher -> 26 | 27 | })*/ 28 | } 29 | 30 | @Test 31 | fun launchBasicActivity(){ 32 | onView(withId(R.id.btnBasicListing)).perform(click()).withFailureHandler { error, viewMatcher -> } 33 | 34 | 35 | } 36 | 37 | @Test 38 | fun launchMultiSelectActivity(){ 39 | onView(withId(R.id.btnMultiSelect)).perform(click()).withFailureHandler { error, viewMatcher -> } 40 | 41 | 42 | } 43 | 44 | @Test 45 | fun launchLoadingActivity(){ 46 | onView(withId(R.id.btnLoadingListing)).perform(click()).withFailureHandler { error, viewMatcher -> } 47 | } 48 | 49 | @Test 50 | fun launchShimmerActivity(){ 51 | onView(withId(R.id.btnShimmerListing)).perform(click()).withFailureHandler { error, viewMatcher -> } 52 | } 53 | 54 | 55 | @Test 56 | fun launchPaginationActivity(){ 57 | onView(withId(R.id.btnPaginationListing)).perform(click()).withFailureHandler { error, viewMatcher -> } 58 | } 59 | 60 | @Test 61 | fun launchBindingAdapterActivity(){ 62 | onView(withId(R.id.btnBindingAdapter)).perform(click()).withFailureHandler { error, viewMatcher -> } 63 | } 64 | 65 | @Test 66 | fun launchMultipleViewsActivity(){ 67 | onView(withId(R.id.btnMultipleViews)).perform(click()).withFailureHandler { error, viewMatcher -> } 68 | onView(withId(R.id.btnSchoolListing)).perform(click()).withFailureHandler { error, viewMatcher -> } 69 | pressBack() 70 | onView(withId(R.id.btnChatListing)).perform(click()).withFailureHandler { error, viewMatcher -> } 71 | pressBack() 72 | } 73 | 74 | } -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 14 | 17 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/techpaliyal/androidkotlinmvvm/extensions/ImageViewExtensions.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.extensions 2 | 3 | import android.widget.ImageView 4 | import androidx.databinding.BindingAdapter 5 | import com.bumptech.glide.Glide 6 | 7 | 8 | /** 9 | * @author Yogesh Paliyal 10 | * yogeshpaliyal.foss@gmail.com 11 | * https://techpaliyal.com 12 | * https://yogeshpaliyal.com 13 | * Created Date : 9 January 2020 14 | */ 15 | @BindingAdapter("tool:loadUrl") 16 | fun loadUrl(imageView: ImageView?, loadUrl: String?) { 17 | imageView?.let { 18 | 19 | Glide.with(imageView).load(loadUrl).into(imageView) 20 | } 21 | } -------------------------------------------------------------------------------- /app/src/main/java/com/techpaliyal/androidkotlinmvvm/extensions/RecyclerViewPagination.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.extensions 2 | 3 | import androidx.recyclerview.widget.LinearLayoutManager 4 | import androidx.recyclerview.widget.RecyclerView 5 | 6 | 7 | /** 8 | * @author Yogesh Paliyal 9 | * yogeshpaliyal.foss@gmail.com 10 | * https://techpaliyal.com 11 | * https://yogeshpaliyal.com 12 | * Created Date : 9 January 2020 13 | */ 14 | 15 | const val RECYCLER_PAGING_THRESHOLD = 5 16 | 17 | fun RecyclerView?.setupPagination(onReachThreshold : ()->Unit){ 18 | this?.addOnScrollListener(object : RecyclerView.OnScrollListener() { 19 | override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { 20 | super.onScrolled(recyclerView, dx, dy) 21 | val linearLayoutManager = 22 | recyclerView.layoutManager as LinearLayoutManager? 23 | val totalItemCount = linearLayoutManager?.itemCount ?: 0 24 | val visibleItemCount = linearLayoutManager?.childCount ?: 0 25 | val lastVisibleItem = linearLayoutManager?.findLastVisibleItemPosition() ?: 0 26 | listScrolled(visibleItemCount, lastVisibleItem, totalItemCount,onReachThreshold) 27 | } 28 | }) 29 | } 30 | 31 | private fun RecyclerView.listScrolled( 32 | visibleItemCount: Int, 33 | lastVisibleItemPosition: Int, 34 | totalItemCount: Int 35 | , onReachThreshold : ()->Unit) { 36 | val VISIBLE_THRESHOLD: Int = RECYCLER_PAGING_THRESHOLD 37 | if (visibleItemCount + lastVisibleItemPosition + VISIBLE_THRESHOLD >= totalItemCount) { 38 | onReachThreshold() 39 | } 40 | } -------------------------------------------------------------------------------- /app/src/main/java/com/techpaliyal/androidkotlinmvvm/listeners/BasicListener.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.listeners 2 | 3 | 4 | /** 5 | * @author Yogesh Paliyal 6 | * yogeshpaliyal.foss@gmail.com 7 | * https://techpaliyal.com 8 | * https://yogeshpaliyal.com 9 | * Created Date : 9 January 2020 10 | */ 11 | interface BasicListener{ 12 | fun onClick(model: T) 13 | } -------------------------------------------------------------------------------- /app/src/main/java/com/techpaliyal/androidkotlinmvvm/listeners/UsersListener.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.listeners 2 | 3 | import androidx.databinding.ViewDataBinding 4 | import com.techpaliyal.androidkotlinmvvm.model.UserModel 5 | 6 | interface UsersListener { 7 | fun onLikeClicked(binding: ViewDataBinding,model: UserModel) 8 | fun onClick(model : UserModel) 9 | } -------------------------------------------------------------------------------- /app/src/main/java/com/techpaliyal/androidkotlinmvvm/model/BasicModel.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.model 2 | 3 | import com.yogeshpaliyal.universalAdapter.model.BaseDiffUtil 4 | 5 | /** 6 | * @author Yogesh Paliyal 7 | * yogeshpaliyal.foss@gmail.com 8 | * https://techpaliyal.com 9 | * https://yogeshpaliyal.com 10 | * Created Date : 9 January 2020 11 | */ 12 | data class BasicModel(var id : Int = 0, var name : String) : BaseDiffUtil -------------------------------------------------------------------------------- /app/src/main/java/com/techpaliyal/androidkotlinmvvm/model/MultiSelectModel.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.model 2 | 3 | import com.yogeshpaliyal.universalAdapter.model.BaseDiffUtil 4 | 5 | 6 | /** 7 | * @author Yogesh Paliyal 8 | * yogeshpaliyal.foss@gmail.com 9 | * https://techpaliyal.com 10 | * https://yogeshpaliyal.com 11 | * Created Date : 9 January 2020 12 | */ 13 | data class MultiSelectModel(val name: String, var isChecked: Boolean) : BaseDiffUtil -------------------------------------------------------------------------------- /app/src/main/java/com/techpaliyal/androidkotlinmvvm/model/UserModel.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.model 2 | 3 | import com.yogeshpaliyal.universalAdapter.model.BaseDiffUtil 4 | 5 | 6 | /** 7 | * @author Yogesh Paliyal 8 | * yogeshpaliyal.foss@gmail.com 9 | * https://techpaliyal.com 10 | * https://yogeshpaliyal.com 11 | * Created Date : 9 January 2020 12 | */ 13 | data class UserModel(var name: String, var address: String = "", var image: String, var isLiked: Boolean = false) : BaseDiffUtil { 14 | override fun getDiffId(): Any? { 15 | return name 16 | } 17 | 18 | override fun getDiffBody(): Any? { 19 | return "$name $address $image" 20 | } 21 | } -------------------------------------------------------------------------------- /app/src/main/java/com/techpaliyal/androidkotlinmvvm/ui/activity/BasicListingActivity.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.ui.activity 2 | 3 | import android.content.Context 4 | import android.content.Intent 5 | import android.os.Bundle 6 | import android.widget.Toast 7 | import androidx.appcompat.app.AppCompatActivity 8 | import androidx.lifecycle.Observer 9 | import com.techpaliyal.androidkotlinmvvm.R 10 | import com.techpaliyal.androidkotlinmvvm.databinding.ActivityListingBinding 11 | import com.techpaliyal.androidkotlinmvvm.listeners.BasicListener 12 | import com.techpaliyal.androidkotlinmvvm.model.BasicModel 13 | import com.techpaliyal.androidkotlinmvvm.ui.view_model.BasicListingActivityViewModel 14 | import com.techpaliyal.androidkotlinmvvm.ui.view_model.initViewModel 15 | import com.yogeshpaliyal.universalAdapter.adapter.UniversalAdapterViewType 16 | import com.yogeshpaliyal.universalAdapter.adapter.UniversalRecyclerAdapter 17 | import com.yogeshpaliyal.universalAdapter.utils.Resource 18 | 19 | /** 20 | * @author Yogesh Paliyal 21 | * yogeshpaliyal.foss@gmail.com 22 | * https://techpaliyal.com 23 | * https://yogeshpaliyal.com 24 | * Created Date : 9 January 2020 25 | */ 26 | class BasicListingActivity : AppCompatActivity() { 27 | 28 | lateinit var binding: ActivityListingBinding 29 | 30 | private val mViewModel by lazy { 31 | initViewModel(BasicListingActivityViewModel::class.java) 32 | } 33 | 34 | companion object { 35 | fun start(context: Context) { 36 | val intent = Intent(context, BasicListingActivity::class.java) 37 | context.startActivity(intent) 38 | } 39 | } 40 | 41 | /** 42 | * Old Builder way 43 | */ 44 | /* private val mAdapter by lazy { 45 | UniversalRecyclerAdapter.Builder( 46 | lifecycleOwner = this, 47 | content = UniversalAdapterViewType.Content( 48 | R.layout.item_simple, 49 | listener = object : BasicListener { 50 | override fun onClick(model: BasicModel) { 51 | Toast.makeText(this@BasicListingActivity, model.name, Toast.LENGTH_SHORT) 52 | .show() 53 | } 54 | }) 55 | ).build() 56 | }*/ 57 | 58 | /** 59 | * New Builder Way 60 | */ 61 | private val mAdapter by lazy{ 62 | UniversalRecyclerAdapter.Builder() 63 | .setLifecycleOwner(this) 64 | .setContent(R.layout.item_simple, object : BasicListener { 65 | override fun onClick(model: BasicModel) { 66 | Toast.makeText(this@BasicListingActivity, model.name, Toast.LENGTH_SHORT) 67 | .show() 68 | } 69 | }) 70 | .build() 71 | } 72 | 73 | override fun onCreate(savedInstanceState: Bundle?) { 74 | super.onCreate(savedInstanceState) 75 | binding = ActivityListingBinding.inflate(layoutInflater) 76 | setContentView(binding.root) 77 | 78 | binding.recyclerView.adapter = mAdapter.getAdapter() 79 | 80 | mViewModel.data.observe(this, Observer { 81 | mAdapter.updateData(Resource.success(it)) 82 | }) 83 | 84 | mViewModel.fetchData() 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /app/src/main/java/com/techpaliyal/androidkotlinmvvm/ui/activity/BindingAdapterTestActivity.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.ui.activity 2 | 3 | import androidx.appcompat.app.AppCompatActivity 4 | import android.os.Bundle 5 | import com.techpaliyal.androidkotlinmvvm.R 6 | import com.techpaliyal.androidkotlinmvvm.databinding.ActivityBindingAdapterTestBinding 7 | import com.techpaliyal.androidkotlinmvvm.ui.view_model.BindingTestViewModel 8 | import com.techpaliyal.androidkotlinmvvm.ui.view_model.initViewModel 9 | 10 | class BindingAdapterTestActivity : AppCompatActivity() { 11 | 12 | private lateinit var binding: ActivityBindingAdapterTestBinding 13 | 14 | private val mViewModel by lazy { 15 | initViewModel(BindingTestViewModel::class.java) 16 | } 17 | 18 | override fun onCreate(savedInstanceState: Bundle?) { 19 | super.onCreate(savedInstanceState) 20 | binding = ActivityBindingAdapterTestBinding.inflate(layoutInflater) 21 | setContentView(binding.root) 22 | 23 | binding.lifecycleOwner = this 24 | binding.myLifecycleOwner = this 25 | binding.mViewModel = mViewModel 26 | binding.executePendingBindings() 27 | 28 | } 29 | } -------------------------------------------------------------------------------- /app/src/main/java/com/techpaliyal/androidkotlinmvvm/ui/activity/LoadingListingActivity.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.ui.activity 2 | 3 | import android.content.Context 4 | import android.content.Intent 5 | import android.os.Bundle 6 | import android.widget.Toast 7 | import androidx.appcompat.app.AppCompatActivity 8 | import androidx.databinding.ViewDataBinding 9 | import androidx.lifecycle.Observer 10 | import com.techpaliyal.androidkotlinmvvm.R 11 | import com.techpaliyal.androidkotlinmvvm.databinding.ActivityListingBinding 12 | import com.techpaliyal.androidkotlinmvvm.listeners.BasicListener 13 | import com.techpaliyal.androidkotlinmvvm.listeners.UsersListener 14 | import com.techpaliyal.androidkotlinmvvm.model.UserModel 15 | import com.techpaliyal.androidkotlinmvvm.ui.view_model.LoadingListingViewModel 16 | import com.techpaliyal.androidkotlinmvvm.ui.view_model.initViewModel 17 | import com.yogeshpaliyal.universalAdapter.adapter.UniversalAdapterViewType 18 | import com.yogeshpaliyal.universalAdapter.adapter.UniversalRecyclerAdapter 19 | 20 | /** 21 | * @author Yogesh Paliyal 22 | * yogeshpaliyal.foss@gmail.com 23 | * https://techpaliyal.com 24 | * https://yogeshpaliyal.com 25 | * Created Date : 9 January 2020 26 | */ 27 | class LoadingListingActivity : AppCompatActivity() { 28 | lateinit var binding: ActivityListingBinding 29 | 30 | 31 | companion object { 32 | @JvmStatic 33 | fun start(context: Context) { 34 | val starter = Intent(context, LoadingListingActivity::class.java) 35 | context.startActivity(starter) 36 | } 37 | } 38 | 39 | private val mViewModel by lazy { 40 | initViewModel(LoadingListingViewModel::class.java) 41 | } 42 | 43 | private val mAdapter by lazy { 44 | UniversalRecyclerAdapter.Builder( 45 | lifecycleOwner = this, 46 | content = UniversalAdapterViewType.Content(resource = R.layout.item_user, 47 | object : UsersListener { 48 | override fun onLikeClicked(binding: ViewDataBinding, model: UserModel) { 49 | 50 | } 51 | override fun onClick(model: UserModel) { 52 | Toast.makeText(this@LoadingListingActivity, model.name, Toast.LENGTH_SHORT) 53 | .show() 54 | } 55 | }), 56 | loading = UniversalAdapterViewType.Loading( 57 | resourceLoading = R.layout.layout_loading_full_page, 58 | defaultLoadingItems = 1 59 | ), 60 | error = UniversalAdapterViewType.Error(errorLayout = R.layout.item_error), 61 | loadingFooter = UniversalAdapterViewType.LoadingFooter(loaderFooter = R.layout.item_loading_more) 62 | ).build() 63 | } 64 | 65 | override fun onCreate(savedInstanceState: Bundle?) { 66 | super.onCreate(savedInstanceState) 67 | binding = ActivityListingBinding.inflate(layoutInflater) 68 | setContentView(binding.root) 69 | 70 | binding.recyclerView.adapter = mAdapter.getAdapter() 71 | 72 | mViewModel.data.observe(this, Observer { 73 | mAdapter.updateData(it) 74 | }) 75 | 76 | mViewModel.fetchData() 77 | } 78 | } -------------------------------------------------------------------------------- /app/src/main/java/com/techpaliyal/androidkotlinmvvm/ui/activity/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.ui.activity 2 | 3 | import android.content.Intent 4 | import android.os.Bundle 5 | import androidx.appcompat.app.AppCompatActivity 6 | import androidx.databinding.DataBindingUtil 7 | import com.techpaliyal.androidkotlinmvvm.R 8 | import com.techpaliyal.androidkotlinmvvm.databinding.ActivityMainBinding 9 | import com.techpaliyal.androidkotlinmvvm.ui.multiple_view.MultipleViewTypeActivity 10 | 11 | 12 | /** 13 | * @author Yogesh Paliyal 14 | * yogeshpaliyal.foss@gmail.com 15 | * https://techpaliyal.com 16 | * https://yogeshpaliyal.com 17 | * Created Date : 9 January 2020 18 | */ 19 | class MainActivity : AppCompatActivity() { 20 | 21 | lateinit var binding: ActivityMainBinding 22 | 23 | override fun onCreate(savedInstanceState: Bundle?) { 24 | super.onCreate(savedInstanceState) 25 | binding = DataBindingUtil.setContentView(this, R.layout.activity_main) 26 | 27 | binding.btnBasicListing.setOnClickListener { 28 | BasicListingActivity.start(this) 29 | } 30 | 31 | binding.btnUserListing.setOnClickListener { 32 | UserListingActivity.start(this) 33 | } 34 | 35 | binding.btnMultiSelect.setOnClickListener { 36 | MultiSelectListingActivity.start(this) 37 | } 38 | 39 | binding.btnLoadingListing.setOnClickListener { 40 | LoadingListingActivity.start(this) 41 | } 42 | 43 | binding.btnShimmerListing.setOnClickListener { 44 | ShimmerListingActivity.start(this) 45 | } 46 | 47 | binding.btnBindingAdapter.setOnClickListener { 48 | val intent = Intent(this, BindingAdapterTestActivity::class.java) 49 | startActivity(intent) 50 | } 51 | 52 | binding.btnMultipleViews.setOnClickListener { 53 | SelectMultipleViewTypeExampleActivity.start(this) 54 | } 55 | 56 | binding.btnPaginationListing.setOnClickListener { 57 | PaginationListingActivity.start(this) 58 | } 59 | 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/com/techpaliyal/androidkotlinmvvm/ui/activity/MultiSelectListingActivity.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.ui.activity 2 | 3 | import android.content.Context 4 | import android.content.Intent 5 | import android.os.Bundle 6 | import androidx.appcompat.app.AppCompatActivity 7 | import androidx.lifecycle.Observer 8 | import com.techpaliyal.androidkotlinmvvm.R 9 | import com.techpaliyal.androidkotlinmvvm.databinding.ActivityListingBinding 10 | import com.techpaliyal.androidkotlinmvvm.listeners.BasicListener 11 | import com.techpaliyal.androidkotlinmvvm.model.MultiSelectModel 12 | import com.techpaliyal.androidkotlinmvvm.ui.view_model.MultiSelectListingActivityViewModel 13 | import com.techpaliyal.androidkotlinmvvm.ui.view_model.initViewModel 14 | import com.yogeshpaliyal.universalAdapter.adapter.UniversalAdapterViewType 15 | import com.yogeshpaliyal.universalAdapter.adapter.UniversalRecyclerAdapter 16 | import com.yogeshpaliyal.universalAdapter.utils.Resource 17 | 18 | /** 19 | * @author Yogesh Paliyal 20 | * yogeshpaliyal.foss@gmail.com 21 | * https://techpaliyal.com 22 | * https://yogeshpaliyal.com 23 | * Created Date : 9 January 2020 24 | */ 25 | class MultiSelectListingActivity : AppCompatActivity() { 26 | 27 | lateinit var binding: ActivityListingBinding 28 | 29 | 30 | companion object { 31 | fun start(context: Context) { 32 | val intent = Intent(context, MultiSelectListingActivity::class.java) 33 | context.startActivity(intent) 34 | } 35 | } 36 | 37 | private val mViewModel by lazy { 38 | initViewModel(MultiSelectListingActivityViewModel::class.java) 39 | } 40 | 41 | private val mAdapter by lazy { 42 | UniversalRecyclerAdapter.Builder( 43 | null, 44 | null, 45 | UniversalAdapterViewType.Content(R.layout.item_multi_select, 46 | listener = object : BasicListener { 47 | override fun onClick(model: MultiSelectModel) { 48 | mViewModel.logData() 49 | } 50 | }) 51 | ).build() 52 | } 53 | 54 | override fun onCreate(savedInstanceState: Bundle?) { 55 | super.onCreate(savedInstanceState) 56 | binding = ActivityListingBinding.inflate(layoutInflater) 57 | setContentView(binding.root) 58 | 59 | binding.recyclerView.adapter = mAdapter.getAdapter() 60 | 61 | mViewModel.data.observe(this, Observer { 62 | mAdapter.updateData(Resource.success(it)) 63 | }) 64 | 65 | mViewModel.fetchData() 66 | 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /app/src/main/java/com/techpaliyal/androidkotlinmvvm/ui/activity/PaginationListingActivity.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.ui.activity 2 | 3 | import android.content.Context 4 | import android.content.Intent 5 | import android.os.Bundle 6 | import android.widget.Toast 7 | import androidx.appcompat.app.AppCompatActivity 8 | import androidx.databinding.ViewDataBinding 9 | import androidx.lifecycle.Observer 10 | import com.techpaliyal.androidkotlinmvvm.R 11 | import com.techpaliyal.androidkotlinmvvm.databinding.ActivityListingBinding 12 | import com.techpaliyal.androidkotlinmvvm.extensions.setupPagination 13 | import com.techpaliyal.androidkotlinmvvm.listeners.BasicListener 14 | import com.techpaliyal.androidkotlinmvvm.listeners.UsersListener 15 | import com.techpaliyal.androidkotlinmvvm.model.UserModel 16 | import com.techpaliyal.androidkotlinmvvm.ui.view_model.LoadingListingViewModel 17 | import com.techpaliyal.androidkotlinmvvm.ui.view_model.initViewModel 18 | import com.yogeshpaliyal.universalAdapter.adapter.UniversalRecyclerAdapter 19 | 20 | /** 21 | * @author Yogesh Paliyal 22 | * yogeshpaliyal.foss@gmail.com 23 | * https://techpaliyal.com 24 | * https://yogeshpaliyal.com 25 | * Created Date : 9 January 2020 26 | */ 27 | class PaginationListingActivity : AppCompatActivity() { 28 | lateinit var binding: ActivityListingBinding 29 | 30 | 31 | companion object { 32 | @JvmStatic 33 | fun start(context: Context) { 34 | val starter = Intent(context, PaginationListingActivity::class.java) 35 | context.startActivity(starter) 36 | } 37 | } 38 | 39 | private val mViewModel by lazy { 40 | initViewModel(LoadingListingViewModel::class.java) 41 | } 42 | 43 | private val mAdapter by lazy { 44 | UniversalRecyclerAdapter.Builder( 45 | R.layout.item_user, 46 | resourceLoading = R.layout.item_user_shimmer, 47 | defaultLoadingItems = 5, 48 | loaderFooter = R.layout.item_loading_more, 49 | mListener = object : UsersListener { 50 | override fun onLikeClicked(binding: ViewDataBinding, model: UserModel) { 51 | 52 | } 53 | 54 | override fun onClick(model: UserModel) { 55 | Toast.makeText(this@PaginationListingActivity, model.name, Toast.LENGTH_SHORT) 56 | .show() 57 | } 58 | }).build() 59 | } 60 | 61 | override fun onCreate(savedInstanceState: Bundle?) { 62 | super.onCreate(savedInstanceState) 63 | binding = ActivityListingBinding.inflate(layoutInflater) 64 | setContentView(binding.root) 65 | 66 | binding.recyclerView.adapter = mAdapter.getAdapter() 67 | 68 | binding.recyclerView.setupPagination { 69 | if (mViewModel.fetchJob?.isActive == false) 70 | mViewModel.fetchData() 71 | } 72 | 73 | mViewModel.data.observe(this, Observer { 74 | mAdapter.updateData(it) 75 | 76 | /* when(it.status){ 77 | Status.LOADING -> { 78 | } 79 | Status.SUCCESS -> { 80 | mAdapter.updateData(Resource.success(mViewModel.arrAllUsers)) 81 | } 82 | }*/ 83 | }) 84 | 85 | mViewModel.fetchData() 86 | } 87 | } -------------------------------------------------------------------------------- /app/src/main/java/com/techpaliyal/androidkotlinmvvm/ui/activity/SelectMultipleViewTypeExampleActivity.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.ui.activity 2 | 3 | import android.content.Context 4 | import android.content.Intent 5 | import androidx.appcompat.app.AppCompatActivity 6 | import android.os.Bundle 7 | import androidx.lifecycle.Observer 8 | import com.techpaliyal.androidkotlinmvvm.databinding.ActivityMultipleViewTypeBinding 9 | import com.techpaliyal.androidkotlinmvvm.databinding.ActivitySelectMultipleViewTypeExampleActivityBinding 10 | import com.techpaliyal.androidkotlinmvvm.ui.multiple_view.MultipleViewTypeActivity 11 | import com.techpaliyal.androidkotlinmvvm.ui.multiple_view_example_2.MultipleViewTypeChat 12 | import com.techpaliyal.androidkotlinmvvm.ui.view_model.initViewModel 13 | import com.yogeshpaliyal.universalAdapter.adapter.UniversalAdapterViewType 14 | import com.yogeshpaliyal.universalAdapter.adapter.UniversalRecyclerAdapter 15 | 16 | class SelectMultipleViewTypeExampleActivity : AppCompatActivity() { 17 | 18 | companion object{ 19 | fun start(context: Context?) = context?.startActivity(Intent(context, SelectMultipleViewTypeExampleActivity::class.java)) 20 | } 21 | 22 | lateinit var binding: ActivitySelectMultipleViewTypeExampleActivityBinding 23 | 24 | 25 | override fun onCreate(savedInstanceState: Bundle?) { 26 | super.onCreate(savedInstanceState) 27 | binding = ActivitySelectMultipleViewTypeExampleActivityBinding.inflate(layoutInflater) 28 | setContentView(binding.root) 29 | 30 | binding.btnChatListing.setOnClickListener { 31 | MultipleViewTypeChat.start(this) 32 | } 33 | 34 | binding.btnSchoolListing.setOnClickListener { 35 | MultipleViewTypeActivity.start(this) 36 | } 37 | 38 | } 39 | } -------------------------------------------------------------------------------- /app/src/main/java/com/techpaliyal/androidkotlinmvvm/ui/activity/ShimmerListingActivity.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.ui.activity 2 | 3 | import android.content.Context 4 | import android.content.Intent 5 | import android.os.Bundle 6 | import android.widget.Toast 7 | import androidx.appcompat.app.AppCompatActivity 8 | import androidx.databinding.ViewDataBinding 9 | import androidx.lifecycle.Observer 10 | import com.techpaliyal.androidkotlinmvvm.R 11 | import com.techpaliyal.androidkotlinmvvm.databinding.ActivityListingBinding 12 | import com.techpaliyal.androidkotlinmvvm.listeners.BasicListener 13 | import com.techpaliyal.androidkotlinmvvm.listeners.UsersListener 14 | import com.techpaliyal.androidkotlinmvvm.model.UserModel 15 | import com.techpaliyal.androidkotlinmvvm.ui.view_model.LoadingListingViewModel 16 | import com.techpaliyal.androidkotlinmvvm.ui.view_model.initViewModel 17 | import com.yogeshpaliyal.universalAdapter.adapter.UniversalAdapterViewType 18 | import com.yogeshpaliyal.universalAdapter.adapter.UniversalRecyclerAdapter 19 | 20 | 21 | /** 22 | * @author Yogesh Paliyal 23 | * yogeshpaliyal.foss@gmail.com 24 | * https://techpaliyal.com 25 | * https://yogeshpaliyal.com 26 | * Created Date : 9 January 2020 27 | */ 28 | class ShimmerListingActivity : AppCompatActivity() { 29 | lateinit var binding: ActivityListingBinding 30 | 31 | 32 | companion object { 33 | @JvmStatic 34 | fun start(context: Context) { 35 | val starter = Intent(context, ShimmerListingActivity::class.java) 36 | context.startActivity(starter) 37 | } 38 | } 39 | 40 | private val mViewModel by lazy { 41 | initViewModel(LoadingListingViewModel::class.java) 42 | } 43 | 44 | private val mAdapter by lazy { 45 | UniversalRecyclerAdapter.Builder( 46 | null, 47 | content = UniversalAdapterViewType.Content( 48 | R.layout.item_user, 49 | listener = object : UsersListener { 50 | override fun onLikeClicked(binding: ViewDataBinding, model: UserModel) { 51 | 52 | } 53 | 54 | override fun onClick(model: UserModel) { 55 | Toast.makeText(this@ShimmerListingActivity, model.name, Toast.LENGTH_SHORT) 56 | .show() 57 | } 58 | }), 59 | loading = UniversalAdapterViewType.Loading(resourceLoading = R.layout.item_user_shimmer), 60 | ).build() 61 | } 62 | 63 | override fun onCreate(savedInstanceState: Bundle?) { 64 | super.onCreate(savedInstanceState) 65 | binding = ActivityListingBinding.inflate(layoutInflater) 66 | setContentView(binding.root) 67 | 68 | binding.recyclerView.adapter = mAdapter.getAdapter() 69 | 70 | mViewModel.data.observe(this, Observer { 71 | mAdapter.updateData(it) 72 | }) 73 | 74 | mViewModel.fetchData() 75 | } 76 | } -------------------------------------------------------------------------------- /app/src/main/java/com/techpaliyal/androidkotlinmvvm/ui/activity/UserListingActivity.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.ui.activity 2 | 3 | import android.content.Context 4 | import android.content.Intent 5 | import android.os.Bundle 6 | import android.widget.Toast 7 | import androidx.appcompat.app.AppCompatActivity 8 | import androidx.databinding.ViewDataBinding 9 | import androidx.lifecycle.Observer 10 | import com.techpaliyal.androidkotlinmvvm.R 11 | import com.techpaliyal.androidkotlinmvvm.databinding.ActivityListingBinding 12 | import com.techpaliyal.androidkotlinmvvm.listeners.UsersListener 13 | import com.techpaliyal.androidkotlinmvvm.model.UserModel 14 | import com.techpaliyal.androidkotlinmvvm.ui.view_model.UserListingActivityViewModel 15 | import com.techpaliyal.androidkotlinmvvm.ui.view_model.initViewModel 16 | import com.yogeshpaliyal.universalAdapter.adapter.UniversalRecyclerAdapter 17 | import com.yogeshpaliyal.universalAdapter.utils.Resource 18 | 19 | /** 20 | * @author Yogesh Paliyal 21 | * yogeshpaliyal.foss@gmail.com 22 | * https://techpaliyal.com 23 | * https://yogeshpaliyal.com 24 | * Created Date : 9 January 2020 25 | */ 26 | class UserListingActivity : AppCompatActivity() { 27 | 28 | lateinit var binding: ActivityListingBinding 29 | 30 | companion object { 31 | fun start(context: Context) { 32 | val intent = Intent(context, UserListingActivity::class.java) 33 | context.startActivity(intent) 34 | } 35 | } 36 | private val mViewModel by lazy { 37 | initViewModel(UserListingActivityViewModel::class.java) 38 | } 39 | 40 | private val mAdapter by lazy { 41 | UniversalRecyclerAdapter.Builder( 42 | R.layout.item_user, 43 | mListener = object : UsersListener { 44 | override fun onLikeClicked(binding: ViewDataBinding,model: UserModel) { 45 | model.isLiked = !model.isLiked 46 | binding.invalidateAll() 47 | } 48 | 49 | override fun onClick(model: UserModel) { 50 | Toast.makeText(this@UserListingActivity, model.name, Toast.LENGTH_SHORT).show() 51 | } 52 | }).build() 53 | } 54 | 55 | override fun onCreate(savedInstanceState: Bundle?) { 56 | super.onCreate(savedInstanceState) 57 | binding = ActivityListingBinding.inflate(layoutInflater) 58 | setContentView(binding.root) 59 | 60 | binding.recyclerView.adapter = mAdapter.getAdapter() 61 | 62 | mViewModel.data.observe(this, Observer { 63 | mAdapter.updateData(Resource.success(it.toList())) 64 | }) 65 | 66 | mViewModel.setData() 67 | 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /app/src/main/java/com/techpaliyal/androidkotlinmvvm/ui/multiple_view/HeadingModel.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.ui.multiple_view 2 | 3 | import com.techpaliyal.androidkotlinmvvm.R 4 | import com.yogeshpaliyal.universalAdapter.listener.UniversalViewType 5 | 6 | data class HeadingModel(val title: String) : UniversalViewType,SchoolListing { 7 | 8 | 9 | override fun getLayoutId(): Int { 10 | return R.layout.item_heading 11 | } 12 | } -------------------------------------------------------------------------------- /app/src/main/java/com/techpaliyal/androidkotlinmvvm/ui/multiple_view/ListItemModel.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.ui.multiple_view 2 | 3 | import com.techpaliyal.androidkotlinmvvm.R 4 | import com.yogeshpaliyal.universalAdapter.listener.UniversalViewType 5 | 6 | data class ListItemModel(val name: String) : UniversalViewType,SchoolListing { 7 | override fun getLayoutId(): Int { 8 | return R.layout.item_list 9 | } 10 | } -------------------------------------------------------------------------------- /app/src/main/java/com/techpaliyal/androidkotlinmvvm/ui/multiple_view/MultipleViewTypeActivity.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.ui.multiple_view 2 | 3 | import android.content.Context 4 | import android.content.Intent 5 | import androidx.appcompat.app.AppCompatActivity 6 | import android.os.Bundle 7 | import androidx.lifecycle.Observer 8 | import com.techpaliyal.androidkotlinmvvm.databinding.ActivityMultipleViewTypeBinding 9 | import com.techpaliyal.androidkotlinmvvm.ui.view_model.initViewModel 10 | import com.yogeshpaliyal.universalAdapter.adapter.UniversalAdapterViewType 11 | import com.yogeshpaliyal.universalAdapter.adapter.UniversalRecyclerAdapter 12 | 13 | class MultipleViewTypeActivity : AppCompatActivity() { 14 | 15 | companion object{ 16 | fun start(context: Context?) = context?.startActivity(Intent(context, MultipleViewTypeActivity::class.java)) 17 | } 18 | 19 | lateinit var binding: ActivityMultipleViewTypeBinding 20 | 21 | private val mViewModel by lazy { 22 | initViewModel(MultipleViewTypeViewModel::class.java) 23 | } 24 | 25 | 26 | private val mAdapter by lazy { 27 | UniversalRecyclerAdapter.Builder(lifecycleOwner = this, 28 | content = UniversalAdapterViewType.Content()).build() 29 | } 30 | 31 | override fun onCreate(savedInstanceState: Bundle?) { 32 | super.onCreate(savedInstanceState) 33 | binding = ActivityMultipleViewTypeBinding.inflate(layoutInflater) 34 | setContentView(binding.root) 35 | 36 | binding.recyclerView.adapter = mAdapter.getAdapter() 37 | 38 | mViewModel.sampleList.observe(this, Observer { 39 | mAdapter.updateData(it) 40 | }) 41 | 42 | 43 | } 44 | } -------------------------------------------------------------------------------- /app/src/main/java/com/techpaliyal/androidkotlinmvvm/ui/multiple_view/MultipleViewTypeViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.ui.multiple_view 2 | 3 | import androidx.lifecycle.LiveData 4 | import androidx.lifecycle.MutableLiveData 5 | import androidx.lifecycle.ViewModel 6 | import com.yogeshpaliyal.universalAdapter.utils.Resource 7 | 8 | class MultipleViewTypeViewModel : ViewModel() { 9 | 10 | private val _sampleList = MutableLiveData>>() 11 | val sampleList : LiveData>> = _sampleList 12 | 13 | 14 | init { 15 | loadDummyData() 16 | } 17 | 18 | private fun loadDummyData(){ 19 | val tempArray = ArrayList() 20 | tempArray.add(HeadingModel("Principal")) 21 | tempArray.add(ListItemModel("Yogesh Paliyal")) 22 | 23 | tempArray.add(HeadingModel("Staff")) 24 | tempArray.add(ListItemModel("Sachin Rupani")) 25 | tempArray.add(ListItemModel("Suraj Vaishnav")) 26 | tempArray.add(ListItemModel("Himanshu Choudhan")) 27 | tempArray.add(ListItemModel("Pramod Patel")) 28 | tempArray.add(ListItemModel("Bharath")) 29 | tempArray.add(ListItemModel("Sanjay")) 30 | tempArray.add(ListItemModel("Surendra Singh")) 31 | 32 | 33 | tempArray.add(HeadingModel("Students")) 34 | tempArray.add(ListItemModel("Bhoma Ram")) 35 | tempArray.add(ListItemModel("Deepak")) 36 | tempArray.add(ListItemModel("Sohan")) 37 | tempArray.add(ListItemModel("Umesh")) 38 | tempArray.add(ListItemModel("Amanda Howard")) 39 | tempArray.add(ListItemModel("Jeremy Glover")) 40 | tempArray.add(ListItemModel("Ginger Larson")) 41 | tempArray.add(ListItemModel("Lincoln Pierpoint")) 42 | tempArray.add(ListItemModel("Brian Brooks")) 43 | tempArray.add(ListItemModel("Erasmus Hall")) 44 | tempArray.add(ListItemModel("Amber Lane")) 45 | tempArray.add(ListItemModel("Elsie Cole")) 46 | 47 | _sampleList.value = Resource.success(tempArray) 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /app/src/main/java/com/techpaliyal/androidkotlinmvvm/ui/multiple_view/SchoolListing.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.ui.multiple_view 2 | 3 | interface SchoolListing -------------------------------------------------------------------------------- /app/src/main/java/com/techpaliyal/androidkotlinmvvm/ui/multiple_view_example_2/ChatListing.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.ui.multiple_view_example_2 2 | 3 | interface ChatListing -------------------------------------------------------------------------------- /app/src/main/java/com/techpaliyal/androidkotlinmvvm/ui/multiple_view_example_2/HeadingModel.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.ui.multiple_view_example_2 2 | 3 | import com.techpaliyal.androidkotlinmvvm.R 4 | import com.yogeshpaliyal.universalAdapter.listener.UniversalViewType 5 | 6 | data class HeadingModel(val title: String) : UniversalViewType, ChatListing { 7 | 8 | 9 | override fun getLayoutId(): Int { 10 | return R.layout.item_chat_header 11 | } 12 | } -------------------------------------------------------------------------------- /app/src/main/java/com/techpaliyal/androidkotlinmvvm/ui/multiple_view_example_2/ListItems.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.ui.multiple_view_example_2 2 | 3 | import com.techpaliyal.androidkotlinmvvm.R 4 | import com.techpaliyal.androidkotlinmvvm.ui.multiple_view.SchoolListing 5 | import com.yogeshpaliyal.universalAdapter.listener.UniversalViewType 6 | 7 | data class ListItems(val name: String,val time:String,val type:String) : UniversalViewType, ChatListing { 8 | override fun getLayoutId(): Int { 9 | 10 | if(type == "MessageSent"){ 11 | return R.layout.item_row_message_sent 12 | } 13 | else{ 14 | return R.layout.item_row_message_received 15 | } 16 | 17 | 18 | 19 | } 20 | } -------------------------------------------------------------------------------- /app/src/main/java/com/techpaliyal/androidkotlinmvvm/ui/multiple_view_example_2/MultipleViewChatViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.ui.multiple_view_example_2 2 | 3 | import androidx.lifecycle.LiveData 4 | import androidx.lifecycle.MutableLiveData 5 | import androidx.lifecycle.ViewModel 6 | import com.techpaliyal.androidkotlinmvvm.ui.multiple_view.ListItemModel 7 | import com.yogeshpaliyal.universalAdapter.utils.Resource 8 | 9 | class MultipleViewChatViewModel : ViewModel() { 10 | 11 | private val _sampleList = MutableLiveData>>() 12 | val sampleList : LiveData>> = _sampleList 13 | 14 | 15 | init { 16 | loadDummyData() 17 | } 18 | 19 | private fun loadDummyData(){ 20 | val tempArray = ArrayList() 21 | 22 | tempArray.add(HeadingModel("Yesterday")) 23 | tempArray.add(ListItems("Wassup","1:40 PM","MessageSent")) 24 | tempArray.add(ListItems("Just preparing for exams","1:43 PM","MessageReceived")) 25 | tempArray.add(ListItems("Great!","1:47 PM","MessageSent")) 26 | 27 | 28 | tempArray.add(HeadingModel("Today")) 29 | tempArray.add(ListItems("Hello","12:25 AM","MessageSent")) 30 | tempArray.add(ListItems("I am fine","12:27 AM","MessageReceived")) 31 | tempArray.add(ListItems("What about you","12:27 AM","MessageReceived")) 32 | tempArray.add(ListItems("I am great!","12:30 AM","MessageSent")) 33 | 34 | _sampleList.value = Resource.success(tempArray) 35 | } 36 | 37 | } -------------------------------------------------------------------------------- /app/src/main/java/com/techpaliyal/androidkotlinmvvm/ui/multiple_view_example_2/MultipleViewTypeChat.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.ui.multiple_view_example_2 2 | 3 | import android.content.Context 4 | import android.content.Intent 5 | import android.os.Bundle 6 | import androidx.appcompat.app.AppCompatActivity 7 | import androidx.lifecycle.Observer 8 | import com.techpaliyal.androidkotlinmvvm.databinding.ActivityMultipleViewTypeBinding 9 | import com.techpaliyal.androidkotlinmvvm.databinding.ActivityMultipleViewTypeExample2Binding 10 | import com.techpaliyal.androidkotlinmvvm.ui.multiple_view.MultipleViewTypeViewModel 11 | import com.techpaliyal.androidkotlinmvvm.ui.multiple_view.SchoolListing 12 | import com.techpaliyal.androidkotlinmvvm.ui.view_model.initViewModel 13 | import com.yogeshpaliyal.universalAdapter.adapter.UniversalAdapterViewType 14 | import com.yogeshpaliyal.universalAdapter.adapter.UniversalRecyclerAdapter 15 | 16 | class MultipleViewTypeChat : AppCompatActivity() { 17 | 18 | companion object{ 19 | fun start(context: Context?) = context?.startActivity(Intent(context, MultipleViewTypeChat::class.java)) 20 | } 21 | 22 | lateinit var binding: ActivityMultipleViewTypeExample2Binding 23 | 24 | private val mViewModel by lazy { 25 | initViewModel(MultipleViewChatViewModel::class.java) 26 | } 27 | 28 | 29 | private val mAdapter by lazy { 30 | UniversalRecyclerAdapter.Builder(lifecycleOwner = this, 31 | content = UniversalAdapterViewType.Content()).build() 32 | } 33 | 34 | override fun onCreate(savedInstanceState: Bundle?) { 35 | super.onCreate(savedInstanceState) 36 | binding = ActivityMultipleViewTypeExample2Binding.inflate(layoutInflater) 37 | setContentView(binding.root) 38 | 39 | binding.recyclerViewChat.adapter = mAdapter.getAdapter() 40 | 41 | mViewModel.sampleList.observe(this, Observer { 42 | mAdapter.updateData(it) 43 | }) 44 | 45 | 46 | } 47 | } -------------------------------------------------------------------------------- /app/src/main/java/com/techpaliyal/androidkotlinmvvm/ui/view_model/BasicListingActivityViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.ui.view_model 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | import androidx.lifecycle.ViewModel 5 | import com.techpaliyal.androidkotlinmvvm.model.BasicModel 6 | 7 | 8 | /** 9 | * @author Yogesh Paliyal 10 | * yogeshpaliyal.foss@gmail.com 11 | * https://techpaliyal.com 12 | * https://yogeshpaliyal.com 13 | * Created Date : 9 January 2020 14 | */ 15 | class BasicListingActivityViewModel : ViewModel() { 16 | 17 | val data = MutableLiveData>(ArrayList()) 18 | 19 | 20 | fun fetchData() { 21 | val tempArr = ArrayList() 22 | tempArr.add(BasicModel(name = "Yogesh")) 23 | tempArr.add(BasicModel(name = "Umesh")) 24 | tempArr.add(BasicModel(name = "Sohan")) 25 | tempArr.add(BasicModel(name = "Madan")) 26 | data.postValue(tempArr) 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /app/src/main/java/com/techpaliyal/androidkotlinmvvm/ui/view_model/BindingTestViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.ui.view_model 2 | 3 | import androidx.lifecycle.* 4 | import com.techpaliyal.androidkotlinmvvm.model.UserModel 5 | import com.yogeshpaliyal.universalAdapter.utils.Resource 6 | import kotlinx.coroutines.Dispatchers 7 | import kotlinx.coroutines.delay 8 | import kotlinx.coroutines.launch 9 | 10 | class BindingTestViewModel : ViewModel() { 11 | 12 | private val _usersData = MutableLiveData>>() 13 | val usersData : LiveData>> = _usersData 14 | 15 | 16 | init { 17 | loadData() 18 | } 19 | 20 | private fun loadData(){ 21 | 22 | viewModelScope.launch(Dispatchers.IO) { 23 | _usersData.postValue(Resource.loading()) 24 | for (i in 0 until 100) { 25 | delay(3000) 26 | addDummyData() 27 | } 28 | } 29 | 30 | } 31 | 32 | private fun addDummyData(){ 33 | val tempArr = ArrayList() 34 | tempArr.add(UserModel(name = "Yogesh",image = "https://randomuser.me/api/portraits/men/52.jpg", address = "Jodhpur")) 35 | tempArr.add(UserModel(name = "Umesh",image = "https://randomuser.me/api/portraits/men/62.jpg")) 36 | tempArr.add(UserModel(name = "Sohan",image = "https://randomuser.me/api/portraits/men/84.jpg")) 37 | tempArr.add(UserModel(name = "Jitendra",image = "https://randomuser.me/api/portraits/men/83.jpg")) 38 | tempArr.add(UserModel(name = "Yogesh",image = "https://randomuser.me/api/portraits/men/52.jpg", address = "Jodhpur")) 39 | tempArr.add(UserModel(name = "Umesh",image = "https://randomuser.me/api/portraits/men/62.jpg")) 40 | tempArr.add(UserModel(name = "Sohan",image = "https://randomuser.me/api/portraits/men/84.jpg")) 41 | tempArr.add(UserModel(name = "Jitendra",image = "https://randomuser.me/api/portraits/men/83.jpg")) 42 | tempArr.add(UserModel(name = "Yogesh",image = "https://randomuser.me/api/portraits/men/52.jpg", address = "Jodhpur")) 43 | tempArr.add(UserModel(name = "Umesh",image = "https://randomuser.me/api/portraits/men/62.jpg")) 44 | tempArr.add(UserModel(name = "Sohan",image = "https://randomuser.me/api/portraits/men/84.jpg")) 45 | tempArr.add(UserModel(name = "Jitendra",image = "https://randomuser.me/api/portraits/men/83.jpg")) 46 | tempArr.add(UserModel(name = "Yogesh",image = "https://randomuser.me/api/portraits/men/52.jpg", address = "Jodhpur")) 47 | tempArr.add(UserModel(name = "Umesh",image = "https://randomuser.me/api/portraits/men/62.jpg")) 48 | tempArr.add(UserModel(name = "Sohan",image = "https://randomuser.me/api/portraits/men/84.jpg")) 49 | tempArr.add(UserModel(name = "Jitendra",image = "https://randomuser.me/api/portraits/men/83.jpg")) 50 | _usersData.postValue(Resource.success(tempArr)) 51 | } 52 | 53 | } -------------------------------------------------------------------------------- /app/src/main/java/com/techpaliyal/androidkotlinmvvm/ui/view_model/LoadingListingViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.ui.view_model 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | import androidx.lifecycle.ViewModel 5 | import androidx.lifecycle.viewModelScope 6 | import com.techpaliyal.androidkotlinmvvm.model.UserModel 7 | import com.yogeshpaliyal.universalAdapter.utils.Resource 8 | import kotlinx.coroutines.Job 9 | import kotlinx.coroutines.delay 10 | import kotlinx.coroutines.isActive 11 | import kotlinx.coroutines.launch 12 | 13 | 14 | /** 15 | * @author Yogesh Paliyal 16 | * yogeshpaliyal.foss@gmail.com 17 | * https://techpaliyal.com 18 | * https://yogeshpaliyal.com 19 | * Created Date : 9 January 2020 20 | */ 21 | class LoadingListingViewModel : ViewModel() { 22 | val data = MutableLiveData>>() 23 | private var index = 1 24 | 25 | var fetchJob: Job? = null 26 | 27 | /** 28 | * Wait for 3 seconds then post the result 29 | */ 30 | fun fetchData() { 31 | fetchJob = viewModelScope.launch { 32 | data.postValue(Resource.loading(data.value?.data)) 33 | delay(3000) 34 | if (!isActive) 35 | return@launch 36 | 37 | val tempArr = data.value?.data ?: ArrayList() 38 | 39 | for (i in 0 until 10) { 40 | tempArr.add( 41 | UserModel( 42 | name = "Yogesh ${index++}", 43 | image = "https://randomuser.me/api/portraits/men/52.jpg", 44 | address = "Jodhpur" 45 | ) 46 | ) 47 | tempArr.add( 48 | UserModel( 49 | name = "Umesh ${index++}", 50 | image = "https://randomuser.me/api/portraits/men/62.jpg" 51 | ) 52 | ) 53 | tempArr.add( 54 | UserModel( 55 | name = "Sohan ${index++}", 56 | image = "https://randomuser.me/api/portraits/men/84.jpg" 57 | ) 58 | ) 59 | tempArr.add( 60 | UserModel( 61 | name = "Pramod ${index++}", 62 | image = "https://randomuser.me/api/portraits/men/83.jpg" 63 | ) 64 | ) 65 | } 66 | if (isActive) 67 | data.postValue(Resource.success(tempArr)) 68 | } 69 | 70 | } 71 | 72 | } -------------------------------------------------------------------------------- /app/src/main/java/com/techpaliyal/androidkotlinmvvm/ui/view_model/MultiSelectListingActivityViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.ui.view_model 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | import androidx.lifecycle.ViewModel 5 | import com.techpaliyal.androidkotlinmvvm.model.MultiSelectModel 6 | 7 | 8 | /** 9 | * @author Yogesh Paliyal 10 | * yogeshpaliyal.foss@gmail.com 11 | * https://techpaliyal.com 12 | * https://yogeshpaliyal.com 13 | * Created Date : 9 January 2020 14 | */ 15 | class MultiSelectListingActivityViewModel : ViewModel(){ 16 | 17 | val data = MutableLiveData>(ArrayList()) 18 | 19 | 20 | 21 | fun fetchData(){ 22 | if (data.value.isNullOrEmpty()) { 23 | val tempArr = ArrayList() 24 | tempArr.add(MultiSelectModel(name = "Apple", isChecked = true)) 25 | tempArr.add(MultiSelectModel(name = "Banana", isChecked = false)) 26 | tempArr.add(MultiSelectModel(name = "Cherry", isChecked = false)) 27 | tempArr.add(MultiSelectModel(name = "Mango", isChecked = false)) 28 | tempArr.add(MultiSelectModel(name = "Orange", isChecked = false)) 29 | tempArr.add(MultiSelectModel(name = "Pineapple", isChecked = false)) 30 | tempArr.add(MultiSelectModel(name = "Watermelon", isChecked = false)) 31 | data.value = tempArr 32 | } 33 | } 34 | 35 | fun logData(){ 36 | /* data.value?.forEach { 37 | Log.d("Testing","Name ${it.name} value => ${it.isChecked}") 38 | }*/ 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /app/src/main/java/com/techpaliyal/androidkotlinmvvm/ui/view_model/UserListingActivityViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.ui.view_model 2 | 3 | import androidx.lifecycle.MutableLiveData 4 | import androidx.lifecycle.ViewModel 5 | import com.techpaliyal.androidkotlinmvvm.model.UserModel 6 | 7 | 8 | /** 9 | * @author Yogesh Paliyal 10 | * yogeshpaliyal.foss@gmail.com 11 | * https://techpaliyal.com 12 | * https://yogeshpaliyal.com 13 | * Created Date : 9 January 2020 14 | */ 15 | class UserListingActivityViewModel : ViewModel() { 16 | 17 | val data = MutableLiveData>() 18 | 19 | 20 | 21 | fun setData(){ 22 | val tempArr = ArrayList() 23 | tempArr.add(UserModel(name = "Yogesh",image = "https://randomuser.me/api/portraits/men/52.jpg", address = "Jodhpur")) 24 | tempArr.add(UserModel(name = "Umesh",image = "https://randomuser.me/api/portraits/men/62.jpg")) 25 | tempArr.add(UserModel(name = "Sohan",image = "https://randomuser.me/api/portraits/men/84.jpg")) 26 | tempArr.add(UserModel(name = "Madan",image = "https://randomuser.me/api/portraits/men/83.jpg")) 27 | data.value = tempArr 28 | } 29 | 30 | } -------------------------------------------------------------------------------- /app/src/main/java/com/techpaliyal/androidkotlinmvvm/ui/view_model/ViewModelFactory.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.ui.view_model 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.ViewModelProvider 5 | import androidx.lifecycle.ViewModelStoreOwner 6 | 7 | 8 | /** 9 | * @author Yogesh Paliyal 10 | * yogeshpaliyal.foss@gmail.com 11 | * https://techpaliyal.com 12 | * https://yogeshpaliyal.com 13 | * Created Date : 9 January 2020 14 | */ 15 | class ViewModelFactory : 16 | ViewModelProvider.NewInstanceFactory() { 17 | 18 | override fun create(modelClass: Class): T { 19 | /* if (modelClass.isAssignableFrom(SingleNetworkCallViewModel::class.java)) { 20 | return SingleNetworkCallViewModel(apiHelper, dbHelper) as T 21 | }*/ 22 | 23 | return super.create(modelClass) 24 | } 25 | } 26 | 27 | fun ViewModelStoreOwner.initViewModel(viewModel: Class):T = ViewModelProvider(this, 28 | ViewModelFactory() 29 | ).get(viewModel) -------------------------------------------------------------------------------- /app/src/main/java/com/techpaliyal/androidkotlinmvvm/utils/StringHelper.kt: -------------------------------------------------------------------------------- 1 | package com.techpaliyal.androidkotlinmvvm.utils 2 | 3 | import android.view.View 4 | import androidx.databinding.BindingAdapter 5 | import java.util.* 6 | 7 | 8 | /** 9 | * @author Yogesh Paliyal 10 | * yogeshpaliyal.foss@gmail.com 11 | * https://techpaliyal.com 12 | * https://yogeshpaliyal.com 13 | * Created Date : 9 January 2020 14 | */ 15 | fun getRandomString()= UUID.randomUUID().toString() 16 | 17 | @BindingAdapter("isSelected") 18 | fun View.setIsSeleted(value : Boolean){ 19 | isSelected = value 20 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_round_thumb_up_24.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_round_thumb_up_24_red.xml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_thumb.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_binding_adapter_test.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 16 | 17 | 18 | 22 | 23 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_listing.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 9 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 13 | 14 |