├── .gitignore ├── .idea ├── $CACHE_FILE$ ├── codeStyles │ ├── Project.xml │ └── codeStyleConfig.xml ├── gradle.xml ├── jarRepositories.xml ├── misc.xml ├── runConfigurations.xml └── vcs.xml ├── Readme.txt ├── build.gradle ├── features ├── bindingfeature │ ├── .gitignore │ ├── build.gradle │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── ref │ │ │ └── bindingfeature │ │ │ └── ExampleInstrumentedTest.kt │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── ref │ │ │ │ └── bindingfeature │ │ │ │ ├── DataBindingActivity.kt │ │ │ │ ├── adapters │ │ │ │ └── BindingListAdapter.kt │ │ │ │ ├── databindinglistdetailnetwork │ │ │ │ ├── adapter │ │ │ │ │ ├── BindingAdapters.kt │ │ │ │ │ └── GitUserAdapter.kt │ │ │ │ ├── dependency │ │ │ │ │ ├── DependencyUtils.kt │ │ │ │ │ └── UnsafeOkHttpClient.kt │ │ │ │ ├── interfaces │ │ │ │ │ └── ItemClickListener.kt │ │ │ │ ├── model │ │ │ │ │ └── GitUserModel.kt │ │ │ │ ├── network │ │ │ │ │ ├── GitUserServiceAPI.kt │ │ │ │ │ └── NetworkUtil.kt │ │ │ │ ├── repository │ │ │ │ │ └── UserRepository.kt │ │ │ │ ├── view │ │ │ │ │ ├── GitUserDetailFragment.kt │ │ │ │ │ └── GitUserFragment.kt │ │ │ │ └── viewmodel │ │ │ │ │ ├── GitUserViewModel.kt │ │ │ │ │ └── GitUsersViewModelFactory.kt │ │ │ │ ├── interfaces │ │ │ │ └── BindingListener.kt │ │ │ │ ├── model │ │ │ │ └── BindingModel.kt │ │ │ │ ├── utils │ │ │ │ └── DependencyUtils.kt │ │ │ │ ├── viewbinding │ │ │ │ └── views │ │ │ │ │ ├── LoginViewBindingActivity.kt │ │ │ │ │ └── LoginViewBindingFragment.kt │ │ │ │ ├── viewmodel │ │ │ │ ├── BindingViewModel.kt │ │ │ │ └── BindingViewModelFactory.kt │ │ │ │ └── views │ │ │ │ └── BindingListFragment.kt │ │ └── res │ │ │ ├── layout │ │ │ ├── activity_binding.xml │ │ │ ├── activity_login_view_binding.xml │ │ │ ├── binding_list_item.xml │ │ │ ├── binding_list_layout.xml │ │ │ ├── fragment_git_user.xml │ │ │ ├── fragment_git_user_detail.xml │ │ │ ├── fragment_login_view_binding.xml │ │ │ ├── fragment_user_data_base.xml │ │ │ └── git_user_list_item.xml │ │ │ └── values │ │ │ └── strings.xml │ │ └── test │ │ └── java │ │ └── com │ │ └── ref │ │ └── bindingfeature │ │ └── ExampleUnitTest.kt ├── fileuploader │ ├── .gitignore │ ├── build.gradle │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── ref │ │ │ └── fileuploader │ │ │ └── ExampleInstrumentedTest.kt │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── ref │ │ │ │ └── fileuploader │ │ │ │ ├── extensions │ │ │ │ ├── UploadRequestBody.kt │ │ │ │ └── Utils.kt │ │ │ │ └── views │ │ │ │ ├── FileUploaderActivity.kt │ │ │ │ └── RadioButtonTestActivity.kt │ │ └── res │ │ │ ├── drawable │ │ │ ├── a.xml │ │ │ ├── b.xml │ │ │ ├── radio_layer.xml │ │ │ ├── radio_ring_checked.xml │ │ │ ├── radio_ring_unchecked.xml │ │ │ ├── selector_radio.xml │ │ │ └── yourbuttonbackground.xml │ │ │ ├── layout │ │ │ ├── activity_file_uploader.xml │ │ │ └── activity_radio_button_test.xml │ │ │ └── values │ │ │ └── strings.xml │ │ └── test │ │ └── java │ │ └── com │ │ └── ref │ │ └── fileuploader │ │ └── ExampleUnitTest.kt ├── firebaseoprs │ ├── .gitignore │ ├── build.gradle │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── ref │ │ │ └── firebaseoprs │ │ │ └── ExampleInstrumentedTest.kt │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── ref │ │ │ │ └── firebaseoprs │ │ │ │ ├── FirebaseoprsActivity.kt │ │ │ │ ├── adapter │ │ │ │ ├── CustomDropDownForTaxDetailTypesAdapter.kt │ │ │ │ └── TaxInfoAdapter.kt │ │ │ │ ├── interfaces │ │ │ │ └── ClickListener.kt │ │ │ │ ├── models │ │ │ │ └── TaxInfo.kt │ │ │ │ ├── viewmodels │ │ │ │ ├── FireBaseViewModel.kt │ │ │ │ └── FireBaseViewModelFactory.kt │ │ │ │ └── views │ │ │ │ ├── EmployeeTaxEntryFragment.kt │ │ │ │ ├── EmployeeTaxInfoFragment.kt │ │ │ │ ├── LoginFragment.kt │ │ │ │ └── RegistrationFragment.kt │ │ └── res │ │ │ ├── drawable │ │ │ └── ic_firebase_module.png │ │ │ ├── layout │ │ │ ├── activity_firebaseoprs.xml │ │ │ ├── custom_spinner_tax_detail_type_item.xml │ │ │ ├── emp_tax_item.xml │ │ │ ├── fragment_employee_tax_entry.xml │ │ │ ├── fragment_employee_tax_info.xml │ │ │ ├── fragment_login.xml │ │ │ └── fragment_registration.xml │ │ │ ├── navigation │ │ │ └── firebase_nav_graph.xml │ │ │ └── values │ │ │ └── strings.xml │ │ └── test │ │ └── java │ │ └── com │ │ └── ref │ │ └── firebaseoprs │ │ └── ExampleUnitTest.kt ├── listtypes │ ├── .gitignore │ ├── build.gradle │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── ref │ │ │ └── listtypes │ │ │ └── ExampleInstrumentedTest.kt │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── assets │ │ │ ├── countryinfo.json │ │ │ ├── countrystateinfo.json │ │ │ └── infinitelist.json │ │ ├── java │ │ │ └── com │ │ │ │ └── ref │ │ │ │ └── listtypes │ │ │ │ ├── adapters │ │ │ │ └── ListTypeAdapter.kt │ │ │ │ ├── expandable │ │ │ │ ├── ExpandableListFragment.kt │ │ │ │ ├── adapter │ │ │ │ │ └── CountryStateExpandableAdapter.kt │ │ │ │ ├── models │ │ │ │ │ ├── ExpandableCountryModel.kt │ │ │ │ │ └── StateCapital.kt │ │ │ │ ├── repository │ │ │ │ │ └── CountryStateRepository.kt │ │ │ │ └── viewmodels │ │ │ │ │ ├── CountryStateViewModel.kt │ │ │ │ │ └── CountryStateViewModelFactory.kt │ │ │ │ ├── infinite │ │ │ │ ├── adapters │ │ │ │ │ └── InfiniteAdapter.kt │ │ │ │ ├── interfaces │ │ │ │ │ └── LoadMore.kt │ │ │ │ ├── model │ │ │ │ │ ├── InfiniteAdapterModel.kt │ │ │ │ │ └── InfiniteModel.kt │ │ │ │ ├── repository │ │ │ │ │ └── InfiniteRepository.kt │ │ │ │ ├── viewmodels │ │ │ │ │ ├── InfiniteListViewModel.kt │ │ │ │ │ └── InfiniteViewModelFactory.kt │ │ │ │ └── views │ │ │ │ │ └── InfiniteListFragment.kt │ │ │ │ ├── interfaces │ │ │ │ └── ListTypeListener.kt │ │ │ │ ├── models │ │ │ │ └── ListTypeModel.kt │ │ │ │ ├── repository │ │ │ │ └── ListTypeRepository.kt │ │ │ │ ├── sectioned │ │ │ │ ├── SectionedListFragment.kt │ │ │ │ ├── adapters │ │ │ │ │ └── CountryStateSectionedAdapter.kt │ │ │ │ └── interfaces │ │ │ │ │ └── CountryClickedListener.kt │ │ │ │ ├── utils │ │ │ │ ├── JSONHelper.kt │ │ │ │ └── ListTypeUtils.kt │ │ │ │ ├── viewmodels │ │ │ │ ├── ListTypeViewModel.kt │ │ │ │ └── ListTypeViewModelFactory.kt │ │ │ │ └── views │ │ │ │ ├── ListTypeActivity.kt │ │ │ │ └── ListTypesFragment.kt │ │ └── res │ │ │ ├── drawable │ │ │ ├── ic_arrow_down.xml │ │ │ └── ic_arrow_drop_up.xml │ │ │ ├── layout │ │ │ ├── activity_list_type.xml │ │ │ ├── expandable_child_item.xml │ │ │ ├── expandable_parent_item.xml │ │ │ ├── fragment_expandable_list.xml │ │ │ ├── fragment_infinite_list.xml │ │ │ ├── fragment_list_types.xml │ │ │ ├── fragment_sectioned_list.xml │ │ │ ├── infinite_list_item.xml │ │ │ ├── infinite_loading.xml │ │ │ └── list_type_list_item.xml │ │ │ ├── navigation │ │ │ └── nav_list_type_graph.xml │ │ │ └── values │ │ │ └── strings.xml │ │ └── test │ │ └── java │ │ └── com │ │ └── ref │ │ └── listtypes │ │ └── ExampleUnitTest.kt ├── mvvmfeature │ ├── .gitignore │ ├── build.gradle │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── ref │ │ │ └── mvvmfeature │ │ │ └── ExampleInstrumentedTest.kt │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── ref │ │ │ │ └── mvvmfeature │ │ │ │ ├── MVVMActivity.kt │ │ │ │ ├── adapters │ │ │ │ ├── CommentsAdapter.kt │ │ │ │ └── PostsAdapter.kt │ │ │ │ ├── dependency │ │ │ │ └── DependencyUtils.kt │ │ │ │ ├── model │ │ │ │ ├── PlaceHolderCommentsModel.kt │ │ │ │ └── PlaceHolderPostsDataModel.kt │ │ │ │ ├── network │ │ │ │ ├── NetworkUtil.kt │ │ │ │ └── PlaceHolderServiceAPI.kt │ │ │ │ ├── repository │ │ │ │ └── PlaceHolderRepository.kt │ │ │ │ ├── view │ │ │ │ └── PlaceHolderFragment.kt │ │ │ │ └── viewmodel │ │ │ │ ├── PlaceHolderViewModel.kt │ │ │ │ └── PlaceHolderViewModelFactory.kt │ │ └── res │ │ │ ├── layout │ │ │ ├── activity_mvvm.xml │ │ │ ├── comments_item.xml │ │ │ ├── fragment_place_holder.xml │ │ │ └── posts_item.xml │ │ │ └── values │ │ │ └── strings.xml │ │ └── test │ │ └── java │ │ └── com │ │ └── ref │ │ └── mvvmfeature │ │ └── ExampleUnitTest.kt └── roomdboprs │ ├── .gitignore │ ├── build.gradle │ └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── ref │ │ └── roomdboprs │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── ref │ │ │ └── roomdboprs │ │ │ ├── RoomDBOpsActivity.kt │ │ │ ├── adapters │ │ │ └── UserBillAdapter.kt │ │ │ ├── database │ │ │ ├── UserDao.kt │ │ │ └── UserInfoDataBase.kt │ │ │ ├── dependency │ │ │ └── DependencyUtils.kt │ │ │ ├── interfaces │ │ │ └── ItemClickListener.kt │ │ │ ├── model │ │ │ └── User.kt │ │ │ ├── repository │ │ │ └── UserDBRepository.kt │ │ │ ├── viewmodels │ │ │ ├── UserViewModel.kt │ │ │ └── UserViewModelFactory.kt │ │ │ └── views │ │ │ ├── AddBillFragment.kt │ │ │ ├── BillListFragment.kt │ │ │ ├── EditBillFragment.kt │ │ │ └── LoginRegistrationFragment.kt │ └── res │ │ ├── drawable │ │ ├── ic_baseline_add_24.xml │ │ └── ic_baseline_list_24.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ ├── bill_item.xml │ │ ├── fragment_add_bill.xml │ │ ├── fragment_bill_list.xml │ │ ├── fragment_edit_bill.xml │ │ └── fragment_login_registration.xml │ │ └── navigation │ │ └── nav_graph.xml │ └── test │ └── java │ └── com │ └── ref │ └── roomdboprs │ └── ExampleUnitTest.kt ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── hiltfeaturemodule ├── .gitignore ├── build.gradle ├── consumer-rules.pro ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── ref │ │ └── hiltfeaturemodule │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── ref │ │ │ └── hiltfeaturemodule │ │ │ ├── adapter │ │ │ └── PostsAdapter.kt │ │ │ ├── di │ │ │ └── NetworkModule.kt │ │ │ ├── model │ │ │ └── PlaceHolderPostsDataModel.kt │ │ │ ├── network │ │ │ ├── NetworkUtil.kt │ │ │ └── PlaceHolderServiceAPI.kt │ │ │ ├── repository │ │ │ ├── CoroutineHelper.kt │ │ │ └── PlaceHolderRepository.kt │ │ │ ├── view │ │ │ ├── PostsHiltActivity.kt │ │ │ └── PostsHiltFragment.kt │ │ │ └── viewmodel │ │ │ └── HiltPostsViewModel.kt │ └── res │ │ ├── layout │ │ ├── activity_posts_hilt.xml │ │ ├── fragment_posts_hilt.xml │ │ └── posts_item.xml │ │ └── navigation │ │ └── navigation_posts_graph.xml │ └── test │ └── java │ └── com │ └── ref │ └── hiltfeaturemodule │ └── ExampleUnitTest.kt ├── libraries ├── baselibrary │ ├── .gitignore │ ├── build.gradle │ ├── consumer-rules.pro │ ├── proguard-rules.pro │ └── src │ │ ├── androidTest │ │ └── java │ │ │ └── com │ │ │ └── ref │ │ │ └── baselibrary │ │ │ └── ExampleInstrumentedTest.kt │ │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── ref │ │ │ │ └── baselibrary │ │ │ │ ├── dialogs │ │ │ │ ├── CustomAlertDialog.kt │ │ │ │ ├── DateGenerator.kt │ │ │ │ ├── DialogListener.kt │ │ │ │ └── DialogModel.kt │ │ │ │ ├── navigator │ │ │ │ └── AppNavigator.kt │ │ │ │ ├── responsehelper │ │ │ │ └── ResultOf.kt │ │ │ │ ├── viewmodels │ │ │ │ └── BaseViewModel.kt │ │ │ │ └── views │ │ │ │ ├── BaseActivity.kt │ │ │ │ └── BaseFragment.kt │ │ └── res │ │ │ ├── layout │ │ │ └── fragment_base.xml │ │ │ └── values │ │ │ └── strings.xml │ │ └── test │ │ └── java │ │ └── com │ │ └── ref │ │ └── baselibrary │ │ └── ExampleUnitTest.kt └── baseuilibrary │ ├── .gitignore │ ├── build.gradle │ ├── consumer-rules.pro │ ├── proguard-rules.pro │ └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── ref │ │ └── baseuilibrary │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ └── res │ │ ├── font │ │ ├── roboto.ttf │ │ ├── roboto_bold.ttf │ │ ├── roboto_fonts.xml │ │ ├── roboto_italic.ttf │ │ ├── roboto_light.ttf │ │ └── roboto_medium.ttf │ │ ├── layout │ │ ├── app_bar_for_navigation_drawer_layout.xml │ │ ├── app_bar_layout.xml │ │ ├── bottom_navigation_view_layout.xml │ │ ├── nav_header.xml │ │ ├── navigation_drawer_layout.xml │ │ └── test_layout.xml │ │ ├── menu │ │ ├── bottom_navigation_menu.xml │ │ ├── nav_drawer_menu_items.xml │ │ └── top_app_bar.xml │ │ ├── mipmap-hdpi │ │ ├── ic_clean.png │ │ ├── ic_mvp.png │ │ └── ic_mvvm.png │ │ ├── mipmap-mdpi │ │ ├── ic_clean.png │ │ ├── ic_mvp.png │ │ └── ic_mvvm.png │ │ ├── mipmap-xhdpi │ │ ├── ic_clean.png │ │ ├── ic_mvp.png │ │ └── ic_mvvm.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_clean.png │ │ ├── ic_mvp.png │ │ └── ic_mvvm.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_clean.png │ │ ├── ic_mvp.png │ │ └── ic_mvvm.png │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── font_certs.xml │ │ ├── preloaded_fonts.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── ref │ └── baseuilibrary │ └── ExampleUnitTest.kt ├── myreferenceapp ├── .gitignore ├── build.gradle ├── google-services.json ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── ref │ │ └── myreferenceproject │ │ └── ExampleInstrumentedTest.kt │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── ref │ │ │ └── myreferenceproject │ │ │ ├── MainActivity.kt │ │ │ └── ReferenceApplication.kt │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ └── activity_main.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 │ └── test │ └── java │ └── com │ └── ref │ └── myreferenceproject │ └── ExampleUnitTest.kt ├── screenshots ├── device-2021-01-01-205831.png ├── device-2021-01-01-205905.png ├── email_pass_firebase.txt ├── loadmore_1.png ├── loadmore_2.png ├── loadmore_3.png ├── loadmore_final.png ├── sectioned_list_1.png └── sectionedlist_2.png └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | .cxx 15 | -------------------------------------------------------------------------------- /.idea/$CACHE_FILE$: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Android 10 | 11 | 12 | ComplianceLintAndroid 13 | 14 | 15 | CorrectnessLintAndroid 16 | 17 | 18 | LintAndroid 19 | 20 | 21 | PerformanceLintAndroid 22 | 23 | 24 | UsabilityLintAndroid 25 | 26 | 27 | 28 | 29 | Android 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 33 | 34 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | 24 | 25 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Readme.txt: -------------------------------------------------------------------------------- 1 | Fonts: 2 | 3 | https://johncodeos.com/how-to-add-custom-fonts-in-your-android-app-using-kotlin/ 4 | https://fonts.google.com/specimen/Roboto#standard-styles 5 | 6 | 7 | Coroutines: 8 | 9 | https://medium.com/@moulesh.s/parallel-multiple-api-requests-using-kotlin-coroutines-26e98cf3a9d7 -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | buildscript { 3 | ext.kotlin_version = "1.3.72" 4 | ext.viewpager2_version = '1.0.0' 5 | ext.material_version = '1.2.1' 6 | ext.lifecycle_version = '2.2.0' 7 | ext.arch_version = '2.1.0' 8 | ext.retrofit_version = '2.6.1' 9 | ext.okhttp_version = '4.7.2' 10 | ext.coroutine_version = '1.3.9' 11 | ext.fragment_version = '1.2.5' 12 | ext.rxJava_version = '2.2.19' 13 | ext.rxAndroid_version = '2.1.1' 14 | ext.glide_version = '4.11.0' 15 | ext.cardview_version = '1.0.0' 16 | ext.appcompat_version = '1.2.0' 17 | ext.ktx_version = '1.3.2' 18 | ext.constraint_layout_version = '2.0.2' 19 | ext.drawer_layout_version = '1.1.1' 20 | ext.google_play_version = '1.8.0' 21 | ext.recycler_view_version = '1.2.0-alpha06' 22 | ext.room_version = '2.2.5' 23 | ext.nav_version = '2.3.2' 24 | ext.hilt_version = '2.28-alpha' 25 | ext.hilt_jetpack_dependencies = '1.0.0-alpha01' 26 | repositories { 27 | google() 28 | jcenter() 29 | } 30 | dependencies { 31 | classpath "com.android.tools.build:gradle:4.0.2" 32 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 33 | classpath "androidx.navigation:navigation-safe-args-gradle-plugin:$nav_version" 34 | classpath "com.google.dagger:hilt-android-gradle-plugin:$hilt_version" 35 | classpath 'com.google.gms:google-services:4.3.5' 36 | // NOTE: Do not place your application dependencies here; they belong 37 | // in the individual module build.gradle files 38 | } 39 | 40 | } 41 | 42 | allprojects { 43 | repositories { 44 | google() 45 | jcenter() 46 | } 47 | afterEvaluate { 48 | if (project.plugins.hasPlugin("kotlin-kapt")) { 49 | kapt { 50 | javacOptions { 51 | option("-Xmaxerrs", 10000) 52 | } 53 | } 54 | } 55 | } 56 | } 57 | 58 | task clean(type: Delete) { 59 | delete rootProject.buildDir 60 | } -------------------------------------------------------------------------------- /features/bindingfeature/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /features/bindingfeature/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.dynamic-feature" 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-android-extensions' 4 | apply plugin: 'kotlin-kapt' 5 | 6 | android { 7 | compileSdkVersion 30 8 | buildToolsVersion "30.0.0" 9 | 10 | defaultConfig { 11 | minSdkVersion 21 12 | targetSdkVersion 30 13 | versionCode 1 14 | versionName "1.0" 15 | 16 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 17 | } 18 | buildFeatures { 19 | // viewBinding true 20 | dataBinding true 21 | viewBinding true 22 | } 23 | 24 | } 25 | 26 | dependencies { 27 | implementation fileTree(dir: "libs", include: ["*.jar"]) 28 | implementation project(":myreferenceapp") 29 | implementation project(path: ':libraries:baselibrary') 30 | implementation project(path: ':libraries:baseuilibrary') 31 | implementation 'androidx.core:core-ktx:1.3.2' 32 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 33 | implementation 'androidx.appcompat:appcompat:1.2.0' 34 | implementation 'androidx.constraintlayout:constraintlayout:2.0.1' 35 | implementation 'androidx.legacy:legacy-support-v4:1.0.0' 36 | testImplementation 'junit:junit:4.12' 37 | androidTestImplementation 'androidx.test.ext:junit:1.1.2' 38 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' 39 | androidTestImplementation 'androidx.annotation:annotation:1.1.0' 40 | 41 | } -------------------------------------------------------------------------------- /features/bindingfeature/src/androidTest/java/com/ref/bindingfeature/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.ref.bindingfeature 2 | 3 | import androidx.test.ext.junit.runners.AndroidJUnit4 4 | import org.junit.Test 5 | import org.junit.runner.RunWith 6 | 7 | /** 8 | * Instrumented test, which will execute on an Android device. 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | @RunWith(AndroidJUnit4::class) 13 | class ExampleInstrumentedTest { 14 | @Test 15 | fun useAppContext() { 16 | } 17 | } -------------------------------------------------------------------------------- /features/bindingfeature/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /features/bindingfeature/src/main/java/com/ref/bindingfeature/DataBindingActivity.kt: -------------------------------------------------------------------------------- 1 | package com.ref.bindingfeature 2 | 3 | import androidx.appcompat.app.AppCompatActivity 4 | import android.os.Bundle 5 | import com.ref.baselibrary.navigator.replaceFragmentWithNoHistory 6 | import com.ref.baselibrary.views.BaseActivity 7 | import com.ref.bindingfeature.views.BindingListFragment 8 | 9 | class DataBindingActivity : BaseActivity() { 10 | 11 | override fun onCreate(savedInstanceState: Bundle?) { 12 | super.onCreate(savedInstanceState) 13 | setContentView(R.layout.activity_binding) 14 | 15 | } 16 | 17 | override fun onResume() { 18 | super.onResume() 19 | setSelectedModule("bindingfeature") 20 | launchFragment() 21 | } 22 | override fun getAppTitle(): String { 23 | return getString(com.ref.baseuilibrary.R.string.title_binding) 24 | } 25 | private fun launchFragment(){ 26 | replaceFragmentWithNoHistory(BindingListFragment(),com.ref.baseuilibrary.R.id.container_fragment) 27 | } 28 | } -------------------------------------------------------------------------------- /features/bindingfeature/src/main/java/com/ref/bindingfeature/adapters/BindingListAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.ref.bindingfeature.adapters 2 | 3 | import android.content.Context 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import androidx.recyclerview.widget.RecyclerView 8 | import com.ref.bindingfeature.R 9 | import com.ref.bindingfeature.interfaces.BindingListener 10 | import com.ref.bindingfeature.model.BindingModel 11 | import kotlinx.android.synthetic.main.binding_list_item.view.* 12 | 13 | class BindingListAdapter(var context: Context, var bindingList : MutableList,var bindingListener: BindingListener) : RecyclerView.Adapter() { 14 | 15 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BindingListAdapter.BindingViewHolder = BindingViewHolder( 16 | LayoutInflater.from(parent.context).inflate( 17 | R.layout.binding_list_item, parent, false)) 18 | 19 | override fun getItemCount(): Int = bindingList.size 20 | 21 | 22 | override fun onBindViewHolder(holder: BindingViewHolder, position: Int) = holder.bind(bindingList[position]) 23 | 24 | 25 | 26 | inner class BindingViewHolder(view: View) : RecyclerView.ViewHolder(view){ 27 | private val parent = view.binding_item_parent 28 | private val bindingItem = view.binding_list_item 29 | 30 | fun bind(bindingModel: BindingModel){ 31 | bindingItem.text = bindingModel.bindingType 32 | parent.setOnClickListener { 33 | println("Clicked on ${bindingItem.text}") 34 | bindingListener.onBindTemplateClick(bindingItem.text as String) 35 | } 36 | } 37 | } 38 | 39 | 40 | } -------------------------------------------------------------------------------- /features/bindingfeature/src/main/java/com/ref/bindingfeature/databindinglistdetailnetwork/adapter/BindingAdapters.kt: -------------------------------------------------------------------------------- 1 | package com.ref.bindingfeature.databindinglistdetailnetwork.adapter 2 | 3 | import android.widget.ImageView 4 | import androidx.databinding.BindingAdapter 5 | import com.bumptech.glide.Glide 6 | import com.bumptech.glide.request.RequestOptions 7 | 8 | 9 | @BindingAdapter("imageUrl") 10 | fun ImageView.loadImage(url: String) { 11 | /* if (url != "") { 12 | // Picasso.with(imageView.getContext()).load(url).resize(200, 200).into(imageView). 13 | // Picasso.get().load(url).into(this) 14 | }*/ 15 | Glide.with(this.context) 16 | .load(url).apply(RequestOptions().circleCrop()) 17 | .override(100,100) 18 | .into(this) 19 | } -------------------------------------------------------------------------------- /features/bindingfeature/src/main/java/com/ref/bindingfeature/databindinglistdetailnetwork/adapter/GitUserAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.ref.bindingfeature.databindinglistdetailnetwork.adapter 2 | 3 | import android.content.Context 4 | import android.view.LayoutInflater 5 | import android.view.ViewGroup 6 | import androidx.databinding.DataBindingUtil 7 | import androidx.recyclerview.widget.RecyclerView 8 | import com.ref.bindingfeature.R 9 | import com.ref.bindingfeature.databinding.GitUserListItemBinding 10 | import com.ref.bindingfeature.databindinglistdetailnetwork.interfaces.ItemClickListener 11 | import com.ref.bindingfeature.databindinglistdetailnetwork.model.GitUserModel 12 | 13 | 14 | class GitUserAdapter(var context: Context, var gitUserList: GitUserModel,var itemClickListener: ItemClickListener) : RecyclerView.Adapter() { 15 | 16 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): GitUserViewHolder { 17 | var gitUserListItemBinding : GitUserListItemBinding = DataBindingUtil.inflate( 18 | LayoutInflater.from(parent.context), 19 | R.layout.git_user_list_item, parent, false) 20 | 21 | return GitUserViewHolder(gitUserListItemBinding) 22 | } 23 | 24 | override fun getItemCount(): Int = gitUserList.size 25 | 26 | override fun onBindViewHolder(holder: GitUserViewHolder, position: Int) { 27 | holder.bind(gitUserList[position]) 28 | 29 | } 30 | 31 | inner class GitUserViewHolder(private val binding: GitUserListItemBinding) : 32 | RecyclerView.ViewHolder(binding.root) { 33 | 34 | fun bind(gitUser: GitUserModel.GitUserModelItem){ 35 | binding.gituser = gitUser 36 | binding.gitUserItemLayout.tag = gitUser 37 | binding.gitUserItemLayout.setOnClickListener { 38 | val clickedGitUser:GitUserModel.GitUserModelItem = binding.gitUserItemLayout.tag as GitUserModel.GitUserModelItem 39 | itemClickListener.gitUserClicked(clickedGitUser) 40 | println("Clicked Item is $clickedGitUser") 41 | } 42 | } 43 | 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /features/bindingfeature/src/main/java/com/ref/bindingfeature/databindinglistdetailnetwork/dependency/DependencyUtils.kt: -------------------------------------------------------------------------------- 1 | package com.ref.bindingfeature.databindinglistdetailnetwork.dependency 2 | 3 | import colruyt.android.dsa.rayon.network.GitUserServiceAPI 4 | import colruyt.android.dsa.rayon.network.NetworkUtil 5 | import com.ref.bindingfeature.databindinglistdetailnetwork.repository.UserRepository 6 | import okhttp3.OkHttpClient 7 | import okhttp3.logging.HttpLoggingInterceptor 8 | import retrofit2.Retrofit 9 | import retrofit2.converter.gson.GsonConverterFactory 10 | import java.util.concurrent.TimeUnit 11 | 12 | 13 | object DependencyUtils { 14 | 15 | private fun provideNetworkURL(): String = NetworkUtil.NETWORK_BASE_URL 16 | 17 | private fun provideHttpLogger(): HttpLoggingInterceptor = HttpLoggingInterceptor().setLevel( 18 | HttpLoggingInterceptor.Level.BODY) 19 | 20 | private fun provideOKHttp(logger: HttpLoggingInterceptor): OkHttpClient { 21 | val okHttpClient = OkHttpClient.Builder() 22 | 23 | with(okHttpClient) { 24 | addInterceptor(logger) 25 | callTimeout(NetworkUtil.REQUEST_TIMEOUT, TimeUnit.SECONDS) 26 | readTimeout(NetworkUtil.REQUEST_TIMEOUT, TimeUnit.SECONDS) 27 | writeTimeout(NetworkUtil.REQUEST_TIMEOUT, TimeUnit.SECONDS) 28 | connectTimeout(NetworkUtil.REQUEST_TIMEOUT, TimeUnit.SECONDS) 29 | } 30 | return okHttpClient.build() 31 | } 32 | 33 | 34 | private fun provideRetrofitInstance(): Retrofit { 35 | return Retrofit.Builder().baseUrl(provideNetworkURL()).client(provideOKHttp( 36 | provideHttpLogger())).addConverterFactory(GsonConverterFactory.create()) 37 | .client(UnsafeOkHttpClient.getUnsafeOkHttpClient().build()) 38 | .build() 39 | 40 | } 41 | 42 | private fun provideAPIService() :GitUserServiceAPI{ 43 | 44 | return provideRetrofitInstance().create(GitUserServiceAPI::class.java) 45 | } 46 | 47 | fun provideUserRepository() = UserRepository(provideAPIService()) 48 | 49 | } -------------------------------------------------------------------------------- /features/bindingfeature/src/main/java/com/ref/bindingfeature/databindinglistdetailnetwork/dependency/UnsafeOkHttpClient.kt: -------------------------------------------------------------------------------- 1 | package com.ref.bindingfeature.databindinglistdetailnetwork.dependency 2 | 3 | import okhttp3.OkHttpClient 4 | import javax.net.ssl.HostnameVerifier 5 | import javax.net.ssl.SSLContext 6 | import javax.net.ssl.TrustManager 7 | import javax.net.ssl.X509TrustManager 8 | import javax.security.cert.CertificateException 9 | 10 | class UnsafeOkHttpClient { 11 | companion object { 12 | fun getUnsafeOkHttpClient(): OkHttpClient.Builder { 13 | try { 14 | // Create a trust manager that does not validate certificate chains 15 | val trustAllCerts = arrayOf(object : X509TrustManager { 16 | @Throws(CertificateException::class) 17 | override fun checkClientTrusted(chain: Array, authType: String) { 18 | } 19 | 20 | @Throws(CertificateException::class) 21 | override fun checkServerTrusted(chain: Array, authType: String) { 22 | } 23 | 24 | override fun getAcceptedIssuers(): Array { 25 | return arrayOf() 26 | } 27 | }) 28 | 29 | // Install the all-trusting trust manager 30 | val sslContext = SSLContext.getInstance("SSL") 31 | sslContext.init(null, trustAllCerts, java.security.SecureRandom()) 32 | // Create an ssl socket factory with our all-trusting manager 33 | val sslSocketFactory = sslContext.socketFactory 34 | 35 | val builder = OkHttpClient.Builder() 36 | builder.sslSocketFactory(sslSocketFactory, trustAllCerts[0] as X509TrustManager) 37 | // builder.hostnameVerifier { _, _ -> true } 38 | builder.hostnameVerifier ( hostnameVerifier = HostnameVerifier{ _, _ -> true }) 39 | 40 | return builder 41 | } catch (e: Exception) { 42 | throw RuntimeException(e) 43 | } 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /features/bindingfeature/src/main/java/com/ref/bindingfeature/databindinglistdetailnetwork/interfaces/ItemClickListener.kt: -------------------------------------------------------------------------------- 1 | package com.ref.bindingfeature.databindinglistdetailnetwork.interfaces 2 | 3 | import com.ref.bindingfeature.databindinglistdetailnetwork.model.GitUserModel 4 | 5 | interface ItemClickListener { 6 | fun gitUserClicked(clickedUser: GitUserModel.GitUserModelItem) 7 | } -------------------------------------------------------------------------------- /features/bindingfeature/src/main/java/com/ref/bindingfeature/databindinglistdetailnetwork/model/GitUserModel.kt: -------------------------------------------------------------------------------- 1 | package com.ref.bindingfeature.databindinglistdetailnetwork.model 2 | 3 | import android.os.Parcelable 4 | import kotlinx.android.parcel.Parcelize 5 | 6 | class GitUserModel : ArrayList(){ 7 | @Parcelize 8 | data class GitUserModelItem( 9 | val avatar_url: String, // https://avatars2.githubusercontent.com/u/46?v=4 10 | val events_url: String, // https://api.github.com/users/bmizerany/events{/privacy} 11 | val followers_url: String, // https://api.github.com/users/bmizerany/followers 12 | val following_url: String, // https://api.github.com/users/bmizerany/following{/other_user} 13 | val gists_url: String, // https://api.github.com/users/bmizerany/gists{/gist_id} 14 | val gravatar_id: String, 15 | val html_url: String, // https://github.com/bmizerany 16 | val id: Int, // 46 17 | val login: String, // bmizerany 18 | val node_id: String, // MDQ6VXNlcjQ2 19 | val organizations_url: String, // https://api.github.com/users/bmizerany/orgs 20 | val received_events_url: String, // https://api.github.com/users/bmizerany/received_events 21 | val repos_url: String, // https://api.github.com/users/bmizerany/repos 22 | val site_admin: Boolean, // false 23 | val starred_url: String, // https://api.github.com/users/bmizerany/starred{/owner}{/repo} 24 | val subscriptions_url: String, // https://api.github.com/users/bmizerany/subscriptions 25 | val type: String, // User 26 | val url: String // https://api.github.com/users/bmizerany 27 | ) : Parcelable 28 | } -------------------------------------------------------------------------------- /features/bindingfeature/src/main/java/com/ref/bindingfeature/databindinglistdetailnetwork/network/GitUserServiceAPI.kt: -------------------------------------------------------------------------------- 1 | package colruyt.android.dsa.rayon.network 2 | 3 | 4 | import com.ref.bindingfeature.databindinglistdetailnetwork.model.GitUserModel 5 | import retrofit2.Response 6 | import retrofit2.http.* 7 | 8 | interface GitUserServiceAPI { 9 | 10 | @GET("users") 11 | suspend fun fetchUsers() : Response 12 | 13 | 14 | 15 | } 16 | -------------------------------------------------------------------------------- /features/bindingfeature/src/main/java/com/ref/bindingfeature/databindinglistdetailnetwork/network/NetworkUtil.kt: -------------------------------------------------------------------------------- 1 | package colruyt.android.dsa.rayon.network 2 | 3 | class NetworkUtil { 4 | companion object { 5 | const val NETWORK_BASE_URL = "https://api.github.com/" 6 | const val REQUEST_TIMEOUT = 60L 7 | 8 | } 9 | } -------------------------------------------------------------------------------- /features/bindingfeature/src/main/java/com/ref/bindingfeature/databindinglistdetailnetwork/repository/UserRepository.kt: -------------------------------------------------------------------------------- 1 | package com.ref.bindingfeature.databindinglistdetailnetwork.repository 2 | 3 | import colruyt.android.dsa.rayon.network.GitUserServiceAPI 4 | import com.ref.bindingfeature.databindinglistdetailnetwork.model.GitUserModel 5 | import retrofit2.Response 6 | 7 | class UserRepository(private val apiServiceAPI: GitUserServiceAPI) { 8 | 9 | suspend fun fetchUsers(): Response = apiServiceAPI.fetchUsers() 10 | } -------------------------------------------------------------------------------- /features/bindingfeature/src/main/java/com/ref/bindingfeature/databindinglistdetailnetwork/viewmodel/GitUsersViewModelFactory.kt: -------------------------------------------------------------------------------- 1 | package com.ref.bindingfeature.databindinglistdetailnetwork.viewmodel 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.ViewModelProvider 5 | import com.ref.bindingfeature.databindinglistdetailnetwork.dependency.DependencyUtils 6 | import com.ref.bindingfeature.databindinglistdetailnetwork.repository.UserRepository 7 | import kotlinx.coroutines.Dispatchers 8 | 9 | class GitUsersViewModelFactory : ViewModelProvider.Factory { 10 | lateinit var userRepository: UserRepository 11 | override fun create(modelClass: Class): T { 12 | userRepository = DependencyUtils.provideUserRepository() 13 | if (modelClass.isAssignableFrom(GitUserViewModel::class.java)) { 14 | return GitUserViewModel(Dispatchers.IO,userRepository) as T 15 | } 16 | throw IllegalArgumentException("Unknown ViewModel class") 17 | } 18 | } -------------------------------------------------------------------------------- /features/bindingfeature/src/main/java/com/ref/bindingfeature/interfaces/BindingListener.kt: -------------------------------------------------------------------------------- 1 | package com.ref.bindingfeature.interfaces 2 | 3 | interface BindingListener { 4 | fun onBindTemplateClick( template : String) 5 | } -------------------------------------------------------------------------------- /features/bindingfeature/src/main/java/com/ref/bindingfeature/model/BindingModel.kt: -------------------------------------------------------------------------------- 1 | package com.ref.bindingfeature.model 2 | 3 | data class BindingModel(val bindingType : String) -------------------------------------------------------------------------------- /features/bindingfeature/src/main/java/com/ref/bindingfeature/utils/DependencyUtils.kt: -------------------------------------------------------------------------------- 1 | package com.ref.bindingfeature.utils 2 | 3 | import com.ref.bindingfeature.model.BindingModel 4 | 5 | object DependencyUtils { 6 | 7 | fun prepareBindingMutableList():MutableList{ 8 | var bindingList = mutableListOf() 9 | var bindingModel = BindingModel("ViewBinding") 10 | bindingList.add(bindingModel) 11 | bindingModel = BindingModel("DataBindingList/Detail+Network") 12 | bindingList.add(bindingModel) 13 | return bindingList 14 | } 15 | } -------------------------------------------------------------------------------- /features/bindingfeature/src/main/java/com/ref/bindingfeature/viewbinding/views/LoginViewBindingActivity.kt: -------------------------------------------------------------------------------- 1 | package com.ref.bindingfeature.viewbinding.views 2 | 3 | import androidx.appcompat.app.AppCompatActivity 4 | import android.os.Bundle 5 | import com.ref.baselibrary.navigator.replaceFragmentWithNoHistory 6 | import com.ref.bindingfeature.R 7 | import com.ref.bindingfeature.databinding.ActivityLoginViewBindingBinding 8 | import com.ref.bindingfeature.views.BindingListFragment 9 | import kotlinx.android.synthetic.main.activity_login_view_binding.* 10 | import kotlinx.android.synthetic.main.fragment_login_view_binding.* 11 | 12 | class LoginViewBindingActivity : AppCompatActivity() { 13 | private lateinit var binding: ActivityLoginViewBindingBinding 14 | override fun onCreate(savedInstanceState: Bundle?) { 15 | super.onCreate(savedInstanceState) 16 | binding = ActivityLoginViewBindingBinding.inflate(layoutInflater) 17 | val view = binding.root 18 | setContentView(view) 19 | launchFragment() 20 | } 21 | 22 | 23 | private fun launchFragment(){ 24 | replaceFragmentWithNoHistory(LoginViewBindingFragment(),binding.containerFragment.id) 25 | } 26 | } -------------------------------------------------------------------------------- /features/bindingfeature/src/main/java/com/ref/bindingfeature/viewmodel/BindingViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.ref.bindingfeature.viewmodel 2 | 3 | import androidx.lifecycle.* 4 | import com.ref.bindingfeature.model.BindingModel 5 | import com.ref.bindingfeature.utils.DependencyUtils 6 | import kotlinx.coroutines.CoroutineDispatcher 7 | import kotlinx.coroutines.launch 8 | 9 | class BindingViewModel(private val dispatcher: CoroutineDispatcher) : ViewModel() , 10 | LifecycleObserver { 11 | var loading: MutableLiveData = MutableLiveData() 12 | var bindingListMutableLiveData = MutableLiveData>() 13 | 14 | 15 | fun fetchBindingListFromUtils(){ 16 | viewModelScope.launch(dispatcher) { 17 | bindingListMutableLiveData.postValue(DependencyUtils.prepareBindingMutableList()) 18 | } 19 | } 20 | 21 | fun fetchBindingListLiveData(): LiveData> = bindingListMutableLiveData 22 | fun fetchLiveLoadingStatus():LiveData = loading 23 | } -------------------------------------------------------------------------------- /features/bindingfeature/src/main/java/com/ref/bindingfeature/viewmodel/BindingViewModelFactory.kt: -------------------------------------------------------------------------------- 1 | package colruyt.android.dsa.rayon.viewmodel 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.ViewModelProvider 5 | import com.ref.bindingfeature.viewmodel.BindingViewModel 6 | import kotlinx.coroutines.Dispatchers 7 | 8 | class BindingViewModelFactory : ViewModelProvider.Factory { 9 | 10 | override fun create(modelClass: Class): T { 11 | 12 | if (modelClass.isAssignableFrom(BindingViewModel::class.java)) { 13 | return BindingViewModel(Dispatchers.IO) as T 14 | } 15 | throw IllegalArgumentException("Unknown ViewModel class") 16 | } 17 | } -------------------------------------------------------------------------------- /features/bindingfeature/src/main/res/layout/activity_binding.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /features/bindingfeature/src/main/res/layout/activity_login_view_binding.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /features/bindingfeature/src/main/res/layout/binding_list_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 21 | -------------------------------------------------------------------------------- /features/bindingfeature/src/main/res/layout/binding_list_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 16 | -------------------------------------------------------------------------------- /features/bindingfeature/src/main/res/layout/fragment_git_user.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 8 | 9 | 17 | 18 | 27 | 28 | -------------------------------------------------------------------------------- /features/bindingfeature/src/main/res/layout/fragment_git_user_detail.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | 10 | 14 | 15 | 16 | 26 | 27 | 41 | 42 | -------------------------------------------------------------------------------- /features/bindingfeature/src/main/res/layout/fragment_user_data_base.xml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /features/bindingfeature/src/main/res/layout/git_user_list_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | 10 | 15 | 16 | 26 | 27 | 37 | 38 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /features/bindingfeature/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Hello blank fragment 4 | -------------------------------------------------------------------------------- /features/bindingfeature/src/test/java/com/ref/bindingfeature/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.ref.bindingfeature 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } -------------------------------------------------------------------------------- /features/fileuploader/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /features/fileuploader/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.dynamic-feature" 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-android-extensions' 4 | 5 | android { 6 | compileSdkVersion 30 7 | buildToolsVersion "30.0.1" 8 | 9 | defaultConfig { 10 | minSdkVersion 21 11 | targetSdkVersion 30 12 | versionCode 1 13 | versionName "1.0" 14 | 15 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 16 | } 17 | 18 | } 19 | 20 | dependencies { 21 | implementation fileTree(dir: "libs", include: ["*.jar"]) 22 | implementation project(":myreferenceapp") 23 | implementation project(path: ':libraries:baselibrary') 24 | implementation project(path: ':libraries:baseuilibrary') 25 | implementation 'androidx.core:core-ktx:1.3.2' 26 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 27 | implementation 'androidx.appcompat:appcompat:1.2.0' 28 | implementation 'androidx.constraintlayout:constraintlayout:2.0.4' 29 | testImplementation 'junit:junit:4.12' 30 | androidTestImplementation 'androidx.test.ext:junit:1.1.2' 31 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' 32 | androidTestImplementation 'androidx.annotation:annotation:1.1.0' 33 | } -------------------------------------------------------------------------------- /features/fileuploader/src/androidTest/java/com/ref/fileuploader/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.ref.fileuploader 2 | 3 | import androidx.test.ext.junit.runners.AndroidJUnit4 4 | import org.junit.Test 5 | import org.junit.runner.RunWith 6 | 7 | /** 8 | * Instrumented test, which will execute on an Android device. 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | @RunWith(AndroidJUnit4::class) 13 | class ExampleInstrumentedTest { 14 | @Test 15 | fun useAppContext() { 16 | } 17 | } -------------------------------------------------------------------------------- /features/fileuploader/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /features/fileuploader/src/main/java/com/ref/fileuploader/extensions/UploadRequestBody.kt: -------------------------------------------------------------------------------- 1 | package com.ref.fileuploader.extensions 2 | 3 | import android.os.Handler 4 | import android.os.Looper 5 | import okhttp3.MediaType 6 | import okhttp3.MediaType.Companion.toMediaTypeOrNull 7 | import java.io.File 8 | import okhttp3.RequestBody 9 | import okio.BufferedSink 10 | import java.io.FileInputStream 11 | 12 | class UploadRequestBody(private val file: File, 13 | private val contentType: String, 14 | private val callback: UploadCallback) : RequestBody(){ 15 | 16 | override fun contentType() = "$contentType/*".toMediaTypeOrNull() 17 | override fun writeTo(sink: BufferedSink) { 18 | val length = file.length() 19 | val buffer = ByteArray(DEFAULT_BUFFER_SIZE) 20 | val fileInputStream = FileInputStream(file) 21 | var uploaded = 0L 22 | fileInputStream.use { inputStream -> 23 | var read: Int 24 | val handler = Handler(Looper.getMainLooper()) 25 | while (inputStream.read(buffer).also { read = it } != -1) { 26 | handler.post(ProgressUpdater(uploaded, length)) 27 | uploaded += read 28 | sink.write(buffer, 0, read) 29 | } 30 | } 31 | } 32 | 33 | override fun contentLength() = file.length() 34 | 35 | interface UploadCallback { 36 | fun onProgressUpdate(percentage: Int) 37 | } 38 | inner class ProgressUpdater( 39 | private val uploaded: Long, 40 | private val total: Long 41 | ) : Runnable { 42 | override fun run() { 43 | callback.onProgressUpdate((100 * uploaded / total).toInt()) 44 | } 45 | } 46 | companion object { 47 | private const val DEFAULT_BUFFER_SIZE = 2048 48 | } 49 | } -------------------------------------------------------------------------------- /features/fileuploader/src/main/java/com/ref/fileuploader/extensions/Utils.kt: -------------------------------------------------------------------------------- 1 | package com.ref.fileuploader.extensions 2 | 3 | import android.content.ContentResolver 4 | import android.net.Uri 5 | import android.provider.OpenableColumns 6 | import android.view.View 7 | import com.google.android.material.snackbar.Snackbar 8 | 9 | fun ContentResolver.getFileName(fileUri: Uri): String { 10 | var name = "" 11 | val returnCursor = this.query(fileUri, null, null, null, null) 12 | if (returnCursor != null) { 13 | val nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME) 14 | returnCursor.moveToFirst() 15 | name = returnCursor.getString(nameIndex) 16 | returnCursor.close() 17 | } 18 | return name 19 | } 20 | 21 | fun View.snackbar(message: String) { 22 | Snackbar.make( 23 | this, 24 | message, 25 | Snackbar.LENGTH_LONG 26 | ).also { snackbar -> 27 | snackbar.setAction("Ok") { 28 | snackbar.dismiss() 29 | } 30 | }.show() 31 | } -------------------------------------------------------------------------------- /features/fileuploader/src/main/java/com/ref/fileuploader/views/RadioButtonTestActivity.kt: -------------------------------------------------------------------------------- 1 | package com.ref.fileuploader.views 2 | 3 | import androidx.appcompat.app.AppCompatActivity 4 | import android.os.Bundle 5 | import com.ref.fileuploader.R 6 | 7 | class RadioButtonTestActivity : AppCompatActivity() { 8 | override fun onCreate(savedInstanceState: Bundle?) { 9 | super.onCreate(savedInstanceState) 10 | setContentView(R.layout.activity_radio_button_test) 11 | } 12 | } -------------------------------------------------------------------------------- /features/fileuploader/src/main/res/drawable/a.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /features/fileuploader/src/main/res/drawable/b.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 7 | 9 | 12 | -------------------------------------------------------------------------------- /features/fileuploader/src/main/res/drawable/radio_layer.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /features/fileuploader/src/main/res/drawable/radio_ring_checked.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 13 | 14 | -------------------------------------------------------------------------------- /features/fileuploader/src/main/res/drawable/radio_ring_unchecked.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 13 | 14 | -------------------------------------------------------------------------------- /features/fileuploader/src/main/res/drawable/selector_radio.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /features/fileuploader/src/main/res/drawable/yourbuttonbackground.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 10 | 13 | 15 | -------------------------------------------------------------------------------- /features/fileuploader/src/main/res/layout/activity_radio_button_test.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 21 | 22 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /features/fileuploader/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /features/fileuploader/src/test/java/com/ref/fileuploader/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.ref.fileuploader 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } -------------------------------------------------------------------------------- /features/firebaseoprs/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /features/firebaseoprs/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.dynamic-feature" 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-android-extensions' 4 | apply plugin: 'kotlin-kapt' 5 | 6 | 7 | android { 8 | compileSdkVersion 30 9 | buildToolsVersion "30.0.1" 10 | 11 | defaultConfig { 12 | minSdkVersion 21 13 | targetSdkVersion 30 14 | versionCode 1 15 | versionName "1.0" 16 | 17 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 18 | } 19 | 20 | } 21 | 22 | dependencies { 23 | implementation fileTree(dir: "libs", include: ["*.jar"]) 24 | implementation project(":myreferenceapp") 25 | implementation project(path: ':libraries:baselibrary') 26 | implementation project(path: ':libraries:baseuilibrary') 27 | implementation 'androidx.core:core-ktx:1.3.2' 28 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 29 | 30 | implementation 'androidx.appcompat:appcompat:1.2.0' 31 | implementation 'androidx.constraintlayout:constraintlayout:2.0.4' 32 | implementation 'androidx.legacy:legacy-support-v4:1.0.0' 33 | implementation 'androidx.navigation:navigation-fragment-ktx:2.3.3' 34 | implementation 'androidx.navigation:navigation-ui-ktx:2.3.3' 35 | // implementation 'com.google.android.gms:play-services-auth:19.0.0' 36 | // Import the BoM for the Firebase platform 37 | implementation platform('com.google.firebase:firebase-bom:26.5.0') 38 | 39 | // Declare the dependency for the Firebase Authentication library 40 | // When using the BoM, you don't specify versions in Firebase library dependencies 41 | implementation 'com.google.firebase:firebase-auth-ktx' 42 | implementation 'com.google.firebase:firebase-storage:19.2.1' 43 | // Declare the dependency for the Realtime Database library 44 | // When using the BoM, you don't specify versions in Firebase library dependencies 45 | implementation 'com.google.firebase:firebase-database-ktx' 46 | testImplementation 'junit:junit:4.12' 47 | androidTestImplementation 'androidx.test.ext:junit:1.1.2' 48 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' 49 | androidTestImplementation 'androidx.annotation:annotation:1.1.0' 50 | } 51 | -------------------------------------------------------------------------------- /features/firebaseoprs/src/androidTest/java/com/ref/firebaseoprs/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.ref.firebaseoprs 2 | 3 | import androidx.test.ext.junit.runners.AndroidJUnit4 4 | import org.junit.Test 5 | import org.junit.runner.RunWith 6 | 7 | /** 8 | * Instrumented test, which will execute on an Android device. 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | @RunWith(AndroidJUnit4::class) 13 | class ExampleInstrumentedTest { 14 | @Test 15 | fun useAppContext() { 16 | } 17 | } -------------------------------------------------------------------------------- /features/firebaseoprs/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /features/firebaseoprs/src/main/java/com/ref/firebaseoprs/adapter/CustomDropDownForTaxDetailTypesAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.ref.firebaseoprs.adapter 2 | 3 | import android.content.Context 4 | import android.graphics.Color 5 | import android.graphics.drawable.ColorDrawable 6 | import android.view.LayoutInflater 7 | import android.view.View 8 | import android.view.ViewGroup 9 | import android.widget.ArrayAdapter 10 | import android.widget.TextView 11 | import androidx.appcompat.widget.AppCompatSpinner 12 | import androidx.core.content.ContextCompat 13 | 14 | class CustomDropDownForTaxDetailTypesAdapter(context: Context, textViewResourceId: Int, var dataSource: MutableList, var selectedPositon:Int = 0, var spinner: AppCompatSpinner) : ArrayAdapter( 15 | context, 16 | textViewResourceId, 17 | dataSource 18 | 19 | ) 20 | { 21 | override fun getCount() = dataSource.size 22 | 23 | override fun getItem(position: Int) = dataSource[position] 24 | 25 | override fun getItemId(position: Int) = position.toLong() 26 | 27 | override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { 28 | return (super.getDropDownView(position, convertView, parent) as TextView).apply { 29 | text = dataSource[position] 30 | 31 | 32 | } 33 | } 34 | 35 | override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View { 36 | return (super.getDropDownView(position, convertView, parent) as TextView).apply { 37 | text = dataSource[position] 38 | if(position == spinner.selectedItemPosition){ 39 | setBackgroundColor(ContextCompat.getColor(context,com.ref.baseuilibrary.R.color.cg_notification_information)) 40 | setTextColor(Color.WHITE) 41 | } 42 | /*setOnClickListener { 43 | println("Selected Item is ${dataSource[position].filterDescription}") 44 | }*/ 45 | 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /features/firebaseoprs/src/main/java/com/ref/firebaseoprs/interfaces/ClickListener.kt: -------------------------------------------------------------------------------- 1 | package com.ref.firebaseoprs.interfaces 2 | 3 | interface ClickListener { 4 | fun onPdfClicked(imageURL : String) 5 | } -------------------------------------------------------------------------------- /features/firebaseoprs/src/main/java/com/ref/firebaseoprs/models/TaxInfo.kt: -------------------------------------------------------------------------------- 1 | package com.ref.firebaseoprs.models 2 | 3 | data class TaxInfo(val employeeEmail : String = "",val taxDetailType:String = "",val taxDetailAmount:String = "",val uploadUrl:String ="") -------------------------------------------------------------------------------- /features/firebaseoprs/src/main/java/com/ref/firebaseoprs/viewmodels/FireBaseViewModelFactory.kt: -------------------------------------------------------------------------------- 1 | package com.ref.firebaseoprs.viewmodels 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.ViewModelProvider 5 | import kotlinx.coroutines.Dispatchers 6 | 7 | class FireBaseViewModelFactory : ViewModelProvider.Factory{ 8 | override fun create(modelClass: Class): T { 9 | 10 | if (modelClass.isAssignableFrom(FireBaseViewModel::class.java)) { 11 | return FireBaseViewModel(Dispatchers.IO) as T 12 | } 13 | throw IllegalArgumentException("Unknown ViewModel class") 14 | } 15 | } -------------------------------------------------------------------------------- /features/firebaseoprs/src/main/res/drawable/ic_firebase_module.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chandragithub2014/MyReferenceProject/2802a9c82f5691c9f9f0c9a21cab232cd07e4319/features/firebaseoprs/src/main/res/drawable/ic_firebase_module.png -------------------------------------------------------------------------------- /features/firebaseoprs/src/main/res/layout/activity_firebaseoprs.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 21 | 22 | -------------------------------------------------------------------------------- /features/firebaseoprs/src/main/res/layout/custom_spinner_tax_detail_type_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 15 | -------------------------------------------------------------------------------- /features/firebaseoprs/src/main/res/navigation/firebase_nav_graph.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 13 | 16 | 19 | 20 | 24 | 28 | 31 | 32 | 36 | -------------------------------------------------------------------------------- /features/firebaseoprs/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Hello blank fragment 4 | 5 | 80C 6 | HouseLoan 7 | Telephone Bills 8 | Education 9 | 10 | -------------------------------------------------------------------------------- /features/firebaseoprs/src/test/java/com/ref/firebaseoprs/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.ref.firebaseoprs 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } -------------------------------------------------------------------------------- /features/listtypes/.gitignore: -------------------------------------------------------------------------------- 1 | /build -------------------------------------------------------------------------------- /features/listtypes/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: "com.android.dynamic-feature" 2 | apply plugin: 'kotlin-android' 3 | apply plugin: 'kotlin-android-extensions' 4 | apply plugin: 'kotlin-kapt' 5 | android { 6 | compileSdkVersion 30 7 | buildToolsVersion "30.0.1" 8 | 9 | defaultConfig { 10 | minSdkVersion 21 11 | targetSdkVersion 30 12 | versionCode 1 13 | versionName "1.0" 14 | 15 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" 16 | } 17 | 18 | } 19 | 20 | dependencies { 21 | implementation fileTree(dir: "libs", include: ["*.jar"]) 22 | implementation project(":myreferenceapp") 23 | implementation project(path: ':libraries:baselibrary') 24 | implementation project(path: ':libraries:baseuilibrary') 25 | implementation 'androidx.core:core-ktx:1.3.2' 26 | implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" 27 | 28 | implementation 'androidx.appcompat:appcompat:1.2.0' 29 | implementation 'androidx.constraintlayout:constraintlayout:2.0.4' 30 | implementation 'androidx.legacy:legacy-support-v4:1.0.0' 31 | testImplementation 'junit:junit:4.12' 32 | androidTestImplementation 'androidx.test.ext:junit:1.1.2' 33 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' 34 | androidTestImplementation 'androidx.annotation:annotation:1.1.0' 35 | } -------------------------------------------------------------------------------- /features/listtypes/src/androidTest/java/com/ref/listtypes/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.ref.listtypes 2 | 3 | import androidx.test.ext.junit.runners.AndroidJUnit4 4 | import org.junit.Test 5 | import org.junit.runner.RunWith 6 | 7 | /** 8 | * Instrumented test, which will execute on an Android device. 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | @RunWith(AndroidJUnit4::class) 13 | class ExampleInstrumentedTest { 14 | @Test 15 | fun useAppContext() { 16 | } 17 | } -------------------------------------------------------------------------------- /features/listtypes/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /features/listtypes/src/main/assets/countryinfo.json: -------------------------------------------------------------------------------- 1 | { 2 | "countries": [ 3 | { 4 | "country": "India", 5 | "states": [ 6 | {"name": "Telangana", "capital": "Hyderabad"}, 7 | {"name": "AP", "capital": "Amaravathi"}, 8 | {"name": "Tamilnadu", "capital": "Chennai"}, 9 | {"name": "Karnataka", "capital": "Bengaluru"} 10 | ] 11 | }, 12 | 13 | { 14 | "country": "America", 15 | "states": [ 16 | {"name": "Alabama", "capital": "Montgomery"}, 17 | {"name": "Alaska", "capital": "Juneau"}, 18 | {"name": "Arizona", "capital": "Chennai"}, 19 | {"name": "Karnataka", "capital": "Bengaluru"} 20 | ] 21 | }, 22 | 23 | { 24 | "country": "Australia", 25 | "states": [ 26 | {"name": "Australian Capital Territory", "capital": "Canberra"}, 27 | {"name": "New South Wales", "capital": "Sydney"}, 28 | {"name": "Queensland", "capital": "Brisbane"}, 29 | {"name": "Victoria", "capital": "Melbourne"} 30 | ] 31 | } 32 | ] 33 | } 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /features/listtypes/src/main/assets/countrystateinfo.json: -------------------------------------------------------------------------------- 1 | { 2 | "countries": [ 3 | { 4 | "country": "India", 5 | "states": [ 6 | {"name": "Telangana", "capital": "Hyderabad"}, 7 | {"name": "AP", "capital": "Amaravathi"}, 8 | {"name": "Tamilnadu", "capital": "Chennai"}, 9 | {"name": "Karnataka", "capital": "Bengaluru"} 10 | ] 11 | }, 12 | 13 | { 14 | "country": "America", 15 | "states": [ 16 | {"name": "Alabama", "capital": "Montgomery"}, 17 | {"name": "Alaska", "capital": "Juneau"}, 18 | {"name": "Arizona", "capital": "Chennai"}, 19 | {"name": "Karnataka", "capital": "Bengaluru"} 20 | ] 21 | }, 22 | 23 | { 24 | "country": "Australia", 25 | "states": [ 26 | {"name": "Australian Capital Territory", "capital": "Canberra"}, 27 | {"name": "New South Wales", "capital": "Sydney"}, 28 | {"name": "Queensland", "capital": "Brisbane"}, 29 | {"name": "Victoria", "capital": "Melbourne"} 30 | ] 31 | }, 32 | { 33 | "country": "SouthAfrica", 34 | "states": [ 35 | {"name": "Eastern Cape", "capital": "Bhisho"}, 36 | {"name": "Free State", "capital": "Bloemfontein"}, 37 | {"name": "Gauteng", "capital": "Johannesburg"}, 38 | {"name": "Western Cape", "capital": "Cape Town"}, 39 | {"name": "Northern Cape", "capital": "Kimberley"}, 40 | {"name": "North West", "capital": "Mahikeng"}, 41 | {"name": "Mpumalanga", "capital": "Nelspruit"} 42 | ] 43 | } 44 | ] 45 | } 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /features/listtypes/src/main/java/com/ref/listtypes/adapters/ListTypeAdapter.kt: -------------------------------------------------------------------------------- 1 | package com.ref.listtypes.adapters 2 | 3 | import android.content.Context 4 | import android.view.LayoutInflater 5 | import android.view.View 6 | import android.view.ViewGroup 7 | import android.widget.TextView 8 | import androidx.recyclerview.widget.RecyclerView 9 | import com.ref.listtypes.R 10 | import com.ref.listtypes.interfaces.ListTypeListener 11 | import com.ref.listtypes.models.ListTypeModel 12 | import kotlinx.android.synthetic.main.list_type_list_item.view.* 13 | 14 | class ListTypeAdapter(var context: Context, var listTypeList : MutableList, var listTypeListener: ListTypeListener) : RecyclerView.Adapter(){ 15 | 16 | 17 | 18 | inner class ListTypeViewHolder(view: View) : RecyclerView.ViewHolder(view){ 19 | private val parent = view.list_type_item_parent 20 | private val bindingItem = view.list_type_list_item 21 | 22 | fun bind(bindingModel: ListTypeModel){ 23 | bindingItem.text = bindingModel.listType 24 | parent.setOnClickListener { 25 | println("Clicked on ${bindingItem.text}") 26 | listTypeListener.onListTypeClick(bindingItem.text as String) 27 | } 28 | } 29 | } 30 | 31 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ListTypeViewHolder = ListTypeViewHolder( 32 | LayoutInflater.from(parent.context).inflate( 33 | R.layout.list_type_list_item, parent, false)) 34 | 35 | override fun getItemCount(): Int = listTypeList.size 36 | 37 | override fun onBindViewHolder(holder: ListTypeViewHolder, position: Int) = holder.bind(listTypeList[position]) 38 | 39 | 40 | 41 | } -------------------------------------------------------------------------------- /features/listtypes/src/main/java/com/ref/listtypes/expandable/models/ExpandableCountryModel.kt: -------------------------------------------------------------------------------- 1 | package com.ref.listtypes.expandable.models 2 | 3 | class ExpandableCountryModel { 4 | companion object{ 5 | const val PARENT = 1 6 | const val CHILD = 2 7 | /* const val BUTTONLAYOUT = 3 8 | const val REMOVELIST = 4 9 | const val EMPTYLAYOUT = 5*/ 10 | } 11 | lateinit var countryParent: StateCapital.Country 12 | var type : Int 13 | lateinit var countryChild : StateCapital.Country.State 14 | var isExpanded : Boolean 15 | // var isPauseShown : Boolean 16 | private var isCloseShown : Boolean 17 | // var isLocked : Boolean 18 | 19 | constructor( type : Int, countryParent: StateCapital.Country, isExpanded : Boolean = false,isCloseShown : Boolean = false ){ 20 | this.type = type 21 | this.countryParent = countryParent 22 | this.isExpanded = isExpanded 23 | this.isCloseShown = isCloseShown 24 | 25 | } 26 | 27 | 28 | constructor(type : Int, countryChild : StateCapital.Country.State, isExpanded : Boolean = false,isCloseShown : Boolean = false){ 29 | this.type = type 30 | this.countryChild = countryChild 31 | this.isExpanded = isExpanded 32 | this.isCloseShown = isCloseShown 33 | 34 | 35 | } 36 | } -------------------------------------------------------------------------------- /features/listtypes/src/main/java/com/ref/listtypes/expandable/models/StateCapital.kt: -------------------------------------------------------------------------------- 1 | package com.ref.listtypes.expandable.models 2 | 3 | data class StateCapital( 4 | val countries: List 5 | ) { 6 | data class Country( 7 | val country: String, // India 8 | val states: List 9 | ) { 10 | data class State( 11 | val capital: String, // Hyderabad 12 | val name: String // Telangana 13 | ) 14 | } 15 | } -------------------------------------------------------------------------------- /features/listtypes/src/main/java/com/ref/listtypes/expandable/repository/CountryStateRepository.kt: -------------------------------------------------------------------------------- 1 | package com.ref.listtypes.expandable.repository 2 | 3 | import com.ref.listtypes.expandable.models.StateCapital 4 | import com.ref.listtypes.utils.JSONHelper 5 | 6 | class CountryStateRepository { 7 | fun fetchCountryStateCapitals() : StateCapital = JSONHelper.fetchParsedJSONInfoForStateCapitals() 8 | } -------------------------------------------------------------------------------- /features/listtypes/src/main/java/com/ref/listtypes/expandable/viewmodels/CountryStateViewModelFactory.kt: -------------------------------------------------------------------------------- 1 | package com.ref.listtypes.expandable.viewmodels 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.ViewModelProvider 5 | import com.ref.listtypes.expandable.repository.CountryStateRepository 6 | import kotlinx.coroutines.Dispatchers 7 | 8 | class CountryStateViewModelFactory : ViewModelProvider.Factory{ 9 | 10 | lateinit var countryStateRepository: CountryStateRepository 11 | override fun create(modelClass: Class): T { 12 | countryStateRepository = CountryStateRepository() 13 | if (modelClass.isAssignableFrom(CountryStateViewModel::class.java)) { 14 | return CountryStateViewModel(Dispatchers.IO,countryStateRepository) as T 15 | } 16 | throw IllegalArgumentException("Unknown ViewModel class") 17 | } 18 | } -------------------------------------------------------------------------------- /features/listtypes/src/main/java/com/ref/listtypes/infinite/interfaces/LoadMore.kt: -------------------------------------------------------------------------------- 1 | package com.ref.listtypes.infinite.interfaces 2 | 3 | import com.ref.listtypes.infinite.model.InfiniteAdapterModel 4 | import com.ref.listtypes.infinite.model.InfiniteModel 5 | 6 | interface LoadMore { 7 | fun loadMore(startPosition:Int,endPosition:Int,previousList:MutableList, originalModel: InfiniteModel) 8 | } -------------------------------------------------------------------------------- /features/listtypes/src/main/java/com/ref/listtypes/infinite/model/InfiniteAdapterModel.kt: -------------------------------------------------------------------------------- 1 | package com.ref.listtypes.infinite.model 2 | 3 | import com.ref.listtypes.expandable.models.StateCapital 4 | 5 | class InfiniteAdapterModel { 6 | companion object{ 7 | const val VIEW_TYPE_DATA = 0 8 | const val VIEW_TYPE_PROGRESS =1 9 | 10 | } 11 | 12 | var infiniteModelItem: InfiniteModel.InfiniteModelItem 13 | var type : Int 14 | 15 | constructor( type : Int, infiniteModelItem: InfiniteModel.InfiniteModelItem){ 16 | this.type = type 17 | this.infiniteModelItem = infiniteModelItem 18 | } 19 | } -------------------------------------------------------------------------------- /features/listtypes/src/main/java/com/ref/listtypes/infinite/model/InfiniteModel.kt: -------------------------------------------------------------------------------- 1 | package com.ref.listtypes.infinite.model 2 | 3 | class InfiniteModel : ArrayList(){ 4 | data class InfiniteModelItem( 5 | val completed: Boolean, // false 6 | val id: Int, // 200 7 | val title: String, // ipsam aperiam voluptates qui 8 | val userId: Int // 10 9 | ) 10 | } -------------------------------------------------------------------------------- /features/listtypes/src/main/java/com/ref/listtypes/infinite/repository/InfiniteRepository.kt: -------------------------------------------------------------------------------- 1 | package com.ref.listtypes.infinite.repository 2 | 3 | import com.ref.listtypes.expandable.models.StateCapital 4 | import com.ref.listtypes.infinite.model.InfiniteModel 5 | import com.ref.listtypes.utils.JSONHelper 6 | import retrofit2.Response 7 | 8 | class InfiniteRepository { 9 | suspend fun fetchInfiniteList() : Response = JSONHelper.fetchParsedJSONInfoForInfiniteList() 10 | } -------------------------------------------------------------------------------- /features/listtypes/src/main/java/com/ref/listtypes/infinite/viewmodels/InfiniteViewModelFactory.kt: -------------------------------------------------------------------------------- 1 | package com.ref.listtypes.infinite.viewmodels 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.ViewModelProvider 5 | import com.ref.listtypes.expandable.viewmodels.CountryStateViewModel 6 | import com.ref.listtypes.infinite.repository.InfiniteRepository 7 | import kotlinx.coroutines.Dispatchers 8 | 9 | class InfiniteViewModelFactory : ViewModelProvider.Factory { 10 | lateinit var infiniteRepository: InfiniteRepository 11 | override fun create(modelClass: Class): T { 12 | infiniteRepository = InfiniteRepository() 13 | if (modelClass.isAssignableFrom(InfiniteListViewModel::class.java)) { 14 | return InfiniteListViewModel(Dispatchers.IO,infiniteRepository) as T 15 | } 16 | throw IllegalArgumentException("Unknown ViewModel class") 17 | } 18 | 19 | } -------------------------------------------------------------------------------- /features/listtypes/src/main/java/com/ref/listtypes/interfaces/ListTypeListener.kt: -------------------------------------------------------------------------------- 1 | package com.ref.listtypes.interfaces 2 | 3 | interface ListTypeListener { 4 | fun onListTypeClick( listType : String) 5 | } -------------------------------------------------------------------------------- /features/listtypes/src/main/java/com/ref/listtypes/models/ListTypeModel.kt: -------------------------------------------------------------------------------- 1 | package com.ref.listtypes.models 2 | 3 | data class ListTypeModel(val listType : String) -------------------------------------------------------------------------------- /features/listtypes/src/main/java/com/ref/listtypes/repository/ListTypeRepository.kt: -------------------------------------------------------------------------------- 1 | package com.ref.listtypes.repository 2 | 3 | import com.ref.listtypes.utils.ListTypeUtils 4 | 5 | class ListTypeRepository { 6 | fun fetchListTypeInfo() = ListTypeUtils.fetchListTypeInfo() 7 | } -------------------------------------------------------------------------------- /features/listtypes/src/main/java/com/ref/listtypes/sectioned/interfaces/CountryClickedListener.kt: -------------------------------------------------------------------------------- 1 | package com.ref.listtypes.sectioned.interfaces 2 | 3 | import com.ref.listtypes.expandable.models.StateCapital 4 | 5 | interface CountryClickedListener { 6 | fun onItemClick(countryName : String, countryChild : StateCapital.Country.State ) 7 | } -------------------------------------------------------------------------------- /features/listtypes/src/main/java/com/ref/listtypes/utils/JSONHelper.kt: -------------------------------------------------------------------------------- 1 | package com.ref.listtypes.utils 2 | 3 | 4 | import com.google.gson.Gson 5 | import com.google.gson.reflect.TypeToken 6 | import com.ref.listtypes.expandable.models.StateCapital 7 | import com.ref.listtypes.infinite.model.InfiniteModel 8 | import com.ref.myreferenceproject.ReferenceApplication 9 | import retrofit2.Response 10 | import java.lang.reflect.Type 11 | 12 | 13 | object JSONHelper { 14 | 15 | 16 | 17 | fun fetchParsedJSONInfoForStateCapitals() : StateCapital{ 18 | val jsonfile: String = ReferenceApplication.instance.applicationContext.assets.open("countrystateinfo.json").bufferedReader().use {it.readText()} 19 | println("Parsed JSON file is.... $jsonfile") 20 | 21 | val gson = Gson() 22 | val stateCapitalModelType: Type = object : TypeToken() {}.type 23 | var stateCapital = gson.fromJson(jsonfile,stateCapitalModelType) 24 | println("Output in String ${stateCapital.toString()}") 25 | return stateCapital 26 | 27 | } 28 | fun fetchParsedJSONInfoForInfiniteList() : Response { 29 | val jsonfile: String = ReferenceApplication.instance.applicationContext.assets.open("infinitelist.json").bufferedReader().use {it.readText()} 30 | println("Parsed JSON file is.... $jsonfile") 31 | 32 | val gson = Gson() 33 | val infiniteListModelType: Type = object : TypeToken() {}.type 34 | var infiniteModel = gson.fromJson(jsonfile,infiniteListModelType) 35 | println("Output in String ${infiniteModel.toString()}") 36 | return Response.success(infiniteModel) 37 | } 38 | 39 | 40 | 41 | } -------------------------------------------------------------------------------- /features/listtypes/src/main/java/com/ref/listtypes/utils/ListTypeUtils.kt: -------------------------------------------------------------------------------- 1 | package com.ref.listtypes.utils 2 | 3 | import com.ref.listtypes.models.ListTypeModel 4 | 5 | object ListTypeUtils { 6 | 7 | fun fetchListTypeInfo():MutableList { 8 | var listTypesList = mutableListOf() 9 | var listTypeModel = ListTypeModel("ExpandableRecyclerView") 10 | listTypesList.add(listTypeModel) 11 | listTypeModel = ListTypeModel("SectionedRecyclerView") 12 | listTypesList.add(listTypeModel) 13 | listTypeModel = ListTypeModel("InfiniteList") 14 | listTypesList.add(listTypeModel) 15 | return listTypesList 16 | } 17 | } -------------------------------------------------------------------------------- /features/listtypes/src/main/java/com/ref/listtypes/viewmodels/ListTypeViewModel.kt: -------------------------------------------------------------------------------- 1 | package com.ref.listtypes.viewmodels 2 | 3 | import androidx.lifecycle.* 4 | import com.ref.baselibrary.responsehelper.ResultOf 5 | import com.ref.listtypes.expandable.models.StateCapital 6 | import com.ref.listtypes.models.ListTypeModel 7 | import com.ref.listtypes.repository.ListTypeRepository 8 | import kotlinx.coroutines.CoroutineDispatcher 9 | import kotlinx.coroutines.launch 10 | 11 | class ListTypeViewModel(private val dispatcher: CoroutineDispatcher, private val listTypeRepository: ListTypeRepository) : ViewModel(), 12 | LifecycleObserver { 13 | private val LOG_TAG = "ListTypeViewModel" 14 | var loading: MutableLiveData = MutableLiveData() 15 | 16 | private val _obtainListTypeResponse= MutableLiveData>>() 17 | val obtainListTypeResponse: LiveData>> = _obtainListTypeResponse 18 | 19 | fun obtainListTypeInfo() { 20 | loading.postValue(true) 21 | 22 | viewModelScope.launch(dispatcher) { 23 | var errorCode = -1 24 | try{ 25 | var listTypeResponse = listTypeRepository.fetchListTypeInfo() 26 | listTypeResponse?.let { 27 | loading.postValue(false) 28 | _obtainListTypeResponse.postValue(ResultOf.Success(it)) 29 | } 30 | }catch (e : Exception){ 31 | e.printStackTrace() 32 | loading.postValue(false) 33 | if(errorCode != -1){ 34 | _obtainListTypeResponse.postValue(ResultOf.Failure("Failed with Error Code ${errorCode} ", e)) 35 | }else{ 36 | _obtainListTypeResponse.postValue(ResultOf.Failure("Failed with Exception ${e.message} ", e)) 37 | } 38 | } 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /features/listtypes/src/main/java/com/ref/listtypes/viewmodels/ListTypeViewModelFactory.kt: -------------------------------------------------------------------------------- 1 | package com.ref.listtypes.viewmodels 2 | 3 | import androidx.lifecycle.ViewModel 4 | import androidx.lifecycle.ViewModelProvider 5 | import com.ref.listtypes.expandable.repository.CountryStateRepository 6 | import com.ref.listtypes.expandable.viewmodels.CountryStateViewModel 7 | import com.ref.listtypes.repository.ListTypeRepository 8 | import kotlinx.coroutines.Dispatchers 9 | 10 | class ListTypeViewModelFactory : ViewModelProvider.Factory { 11 | lateinit var listTypeRepository: ListTypeRepository 12 | override fun create(modelClass: Class): T { 13 | listTypeRepository = ListTypeRepository() 14 | if (modelClass.isAssignableFrom(ListTypeViewModel::class.java)) { 15 | return ListTypeViewModel(Dispatchers.IO,listTypeRepository) as T 16 | } 17 | throw IllegalArgumentException("Unknown ViewModel class") 18 | } 19 | } -------------------------------------------------------------------------------- /features/listtypes/src/main/java/com/ref/listtypes/views/ListTypeActivity.kt: -------------------------------------------------------------------------------- 1 | package com.ref.listtypes.views 2 | 3 | import android.os.Bundle 4 | import android.view.View 5 | import android.view.ViewGroup 6 | import android.widget.FrameLayout 7 | import androidx.appcompat.app.AppCompatActivity 8 | import androidx.navigation.Navigation 9 | import com.ref.baselibrary.views.BaseActivity 10 | import com.ref.listtypes.R 11 | 12 | 13 | class ListTypeActivity : AppCompatActivity() { 14 | override fun onCreate(savedInstanceState: Bundle?) { 15 | super.onCreate(savedInstanceState) 16 | setContentView(R.layout.activity_list_type) 17 | } 18 | 19 | override fun onResume() { 20 | super.onResume() 21 | // setSelectedModule("listtypes") 22 | // launchFragment() 23 | 24 | } 25 | 26 | /*override fun getAppTitle(): String { 27 | return getString(com.ref.baseuilibrary.R.string.title_list_types) 28 | } 29 | */ 30 | private fun launchFragment(){ 31 | /* var navHostFragment: Fragment? = 32 | supportFragmentManager.findFragmentById(R.id.nav_host_fragment) 33 | navHostFragment?.let { 34 | val fragment = navHostFragment.childFragmentManager.fragments[0] 35 | replaceFragmentWithNoHistory(fragment,com.ref.baseuilibrary.R.id.container_fragment) 36 | }*/ 37 | 38 | 39 | var childView :View = findViewById(com.ref.baseuilibrary.R.id.container_fragment) 40 | val parent = childView.parent as ViewGroup 41 | var index:Int = parent.indexOfChild(childView) 42 | parent.removeView(childView) 43 | 44 | Navigation.findNavController(this, R.id.nav_host_fragment) 45 | // childView = layoutInflater.inflate(R.layout.activity_list_type, parent, false) 46 | // parent.addView(childView, index); 47 | 48 | // frameLayout.visibility = View.GONE 49 | } 50 | } 51 | //https://stackoverflow.com/questions/50689206/how-i-can-retrieve-current-fragment-in-navhostfragment/51962582 -------------------------------------------------------------------------------- /features/listtypes/src/main/res/drawable/ic_arrow_down.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /features/listtypes/src/main/res/drawable/ic_arrow_drop_up.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /features/listtypes/src/main/res/layout/activity_list_type.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 20 | 21 | 32 | 33 | -------------------------------------------------------------------------------- /features/listtypes/src/main/res/layout/expandable_child_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 21 | 22 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /features/listtypes/src/main/res/layout/expandable_parent_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 21 | 22 | 32 | 33 | 44 | -------------------------------------------------------------------------------- /features/listtypes/src/main/res/layout/fragment_expandable_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 18 | -------------------------------------------------------------------------------- /features/listtypes/src/main/res/layout/fragment_infinite_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 19 | 20 | 29 | -------------------------------------------------------------------------------- /features/listtypes/src/main/res/layout/fragment_list_types.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 16 | -------------------------------------------------------------------------------- /features/listtypes/src/main/res/layout/fragment_sectioned_list.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 19 | -------------------------------------------------------------------------------- /features/listtypes/src/main/res/layout/infinite_list_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 22 | 23 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /features/listtypes/src/main/res/layout/infinite_loading.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 |