Repository: devrath/KotlinAlchemy
Branch: main
Commit: b87ccbc3cba7
Files: 421
Total size: 1.0 MB
Directory structure:
gitextract_70x6tywz/
├── .gitignore
├── .idea/
│ ├── .gitignore
│ ├── .name
│ ├── compiler.xml
│ ├── jarRepositories.xml
│ └── misc.xml
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
└── application/
├── .idea/
│ ├── .gitignore
│ ├── .name
│ ├── compiler.xml
│ ├── gradle.xml
│ ├── jarRepositories.xml
│ ├── misc.xml
│ └── modules.xml
├── KotlinConcepts/
│ ├── .gitignore
│ ├── .idea/
│ │ ├── .gitignore
│ │ ├── .name
│ │ ├── appInsightsSettings.xml
│ │ ├── compiler.xml
│ │ ├── deploymentTargetDropDown.xml
│ │ ├── deploymentTargetSelector.xml
│ │ ├── gradle.xml
│ │ ├── inspectionProfiles/
│ │ │ └── Project_Default.xml
│ │ ├── kotlinc.xml
│ │ ├── material_theme_project_new.xml
│ │ ├── migrations.xml
│ │ ├── misc.xml
│ │ ├── other.xml
│ │ └── runConfigurations.xml
│ ├── app/
│ │ ├── .gitignore
│ │ ├── build.gradle.kts
│ │ ├── proguard-rules.pro
│ │ └── src/
│ │ ├── androidTest/
│ │ │ └── java/
│ │ │ └── com/
│ │ │ └── istudio/
│ │ │ └── app/
│ │ │ └── ExampleInstrumentedTest.kt
│ │ ├── main/
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── assets/
│ │ │ │ └── stockdata.csv
│ │ │ ├── java/
│ │ │ │ └── com/
│ │ │ │ └── istudio/
│ │ │ │ └── app/
│ │ │ │ ├── application/
│ │ │ │ │ └── CurrentApplication.kt
│ │ │ │ ├── data/
│ │ │ │ │ └── mock/
│ │ │ │ │ ├── FlowMockApi.kt
│ │ │ │ │ ├── FlowMockData.kt
│ │ │ │ │ └── MockNetworkInterceptor.kt
│ │ │ │ ├── main/
│ │ │ │ │ ├── MainActivity.kt
│ │ │ │ │ └── MainViewModel.kt
│ │ │ │ ├── modules/
│ │ │ │ │ ├── module_demos/
│ │ │ │ │ │ ├── basic_fundamentals/
│ │ │ │ │ │ │ ├── ui/
│ │ │ │ │ │ │ │ ├── KotlinBasicsDemo.kt
│ │ │ │ │ │ │ │ └── KotlinBasicsDemoVm.kt
│ │ │ │ │ │ │ └── utils/
│ │ │ │ │ │ │ ├── Student.kt
│ │ │ │ │ │ │ └── multipleInheritance/
│ │ │ │ │ │ │ ├── in_java/
│ │ │ │ │ │ │ │ └── InJava.java
│ │ │ │ │ │ │ └── in_kotlin/
│ │ │ │ │ │ │ └── InKotlin.kt
│ │ │ │ │ │ ├── channels/
│ │ │ │ │ │ │ ├── ChannelsDemo.kt
│ │ │ │ │ │ │ └── ChannelsDemoVm.kt
│ │ │ │ │ │ ├── coroutines/
│ │ │ │ │ │ │ ├── CoroutinesDemo.kt
│ │ │ │ │ │ │ ├── CoroutinesDemoVm.kt
│ │ │ │ │ │ │ ├── compare_join_and_async/
│ │ │ │ │ │ │ │ ├── CompareJoinAsyncDemo.kt
│ │ │ │ │ │ │ │ └── CompareJoinAsyncDemoVm.kt
│ │ │ │ │ │ │ ├── coroutine_cancellation/
│ │ │ │ │ │ │ │ ├── CoroutinesCancellationSelection.kt
│ │ │ │ │ │ │ │ ├── ensure_active_demo/
│ │ │ │ │ │ │ │ │ ├── EnsureActiveDemo.kt
│ │ │ │ │ │ │ │ │ └── EnsureActiveDemoVm.kt
│ │ │ │ │ │ │ │ ├── is_active_demo/
│ │ │ │ │ │ │ │ │ ├── IsActiveDemo.kt
│ │ │ │ │ │ │ │ │ └── IsActiveDemoVm.kt
│ │ │ │ │ │ │ │ ├── non_cancellable_job/
│ │ │ │ │ │ │ │ │ ├── NonCancellableDemo.kt
│ │ │ │ │ │ │ │ │ └── NonCancellableDemoVm.kt
│ │ │ │ │ │ │ │ └── root_children_cencel_demo/
│ │ │ │ │ │ │ │ ├── RootChildrenCancelDemo.kt
│ │ │ │ │ │ │ │ └── RootChildrenCancelDemoVm.kt
│ │ │ │ │ │ │ ├── dispatchers/
│ │ │ │ │ │ │ │ ├── DispatchersDemo.kt
│ │ │ │ │ │ │ │ └── DispatchersDemoVm.kt
│ │ │ │ │ │ │ ├── exception_handeling/
│ │ │ │ │ │ │ │ ├── ExceptionHandlingSelectionDemo.kt
│ │ │ │ │ │ │ │ ├── using_async/
│ │ │ │ │ │ │ │ │ ├── UsingAsyncExceptionHandleDemo.kt
│ │ │ │ │ │ │ │ │ └── UsingAsyncExceptionHandleDemoVm.kt
│ │ │ │ │ │ │ │ └── using_launch/
│ │ │ │ │ │ │ │ ├── UsingLaunchExceptionHandleDemo.kt
│ │ │ │ │ │ │ │ └── UsingLaunchExceptionHandleDemoVm.kt
│ │ │ │ │ │ │ ├── job/
│ │ │ │ │ │ │ │ ├── JobDemoSelection.kt
│ │ │ │ │ │ │ │ └── JobDemoSelectionVm.kt
│ │ │ │ │ │ │ ├── launch_and_withcontext/
│ │ │ │ │ │ │ │ ├── LaunchAndWithContextDemo.kt
│ │ │ │ │ │ │ │ └── LaunchAndWithContextDemoVm.kt
│ │ │ │ │ │ │ ├── simple_structured_concurrency/
│ │ │ │ │ │ │ │ ├── SimpleStructuredConcurrencyDemo.kt
│ │ │ │ │ │ │ │ └── SimpleStructuredConcurrencyDemoVm.kt
│ │ │ │ │ │ │ ├── suspend_and_launch_demo/
│ │ │ │ │ │ │ │ ├── NonCancellableDemoVm.kt
│ │ │ │ │ │ │ │ └── SuspendAndLaunchDemo.kt
│ │ │ │ │ │ │ ├── using_async_await/
│ │ │ │ │ │ │ │ ├── UsingAsyncAwaitDemo.kt
│ │ │ │ │ │ │ │ └── UsingAsyncAwaitDemoVm.kt
│ │ │ │ │ │ │ └── using_join/
│ │ │ │ │ │ │ ├── UsingJoinDemo.kt
│ │ │ │ │ │ │ └── UsingJoinDemoVm.kt
│ │ │ │ │ │ ├── flows/
│ │ │ │ │ │ │ ├── FlowsDemo.kt
│ │ │ │ │ │ │ ├── FlowsDemoVm.kt
│ │ │ │ │ │ │ └── modules/
│ │ │ │ │ │ │ ├── collect_as_state_with_lifecycle/
│ │ │ │ │ │ │ │ ├── CollectAsStateWithLifeCycleDemo.kt
│ │ │ │ │ │ │ │ └── CollectAsStateWithLifeCycleVm.kt
│ │ │ │ │ │ │ ├── compose_and_flatten_flows/
│ │ │ │ │ │ │ │ ├── ComposeAndFlattenFlows.kt
│ │ │ │ │ │ │ │ └── ComposeAndFlattenFlowsVm.kt
│ │ │ │ │ │ │ ├── flatten_flows/
│ │ │ │ │ │ │ │ ├── FlattenFlowsDemo.kt
│ │ │ │ │ │ │ │ └── FlattenFlowsDemoVm.kt
│ │ │ │ │ │ │ ├── flow_basics/
│ │ │ │ │ │ │ │ ├── chapters/
│ │ │ │ │ │ │ │ │ └── display_data_from_server/
│ │ │ │ │ │ │ │ │ ├── DisplayDataFromServerDemo.kt
│ │ │ │ │ │ │ │ │ ├── DisplayDataFromServerVm.kt
│ │ │ │ │ │ │ │ │ └── composables/
│ │ │ │ │ │ │ │ │ └── StockItem.kt
│ │ │ │ │ │ │ │ ├── data/
│ │ │ │ │ │ │ │ │ ├── StockData.kt
│ │ │ │ │ │ │ │ │ ├── StockPriceDataSource.kt
│ │ │ │ │ │ │ │ │ └── api/
│ │ │ │ │ │ │ │ │ └── MockApiBehavior.kt
│ │ │ │ │ │ │ │ ├── state/
│ │ │ │ │ │ │ │ │ └── UiState.kt
│ │ │ │ │ │ │ │ └── ui/
│ │ │ │ │ │ │ │ ├── FlowBasics.kt
│ │ │ │ │ │ │ │ └── FlowBasicsVm.kt
│ │ │ │ │ │ │ ├── intermediate_operators/
│ │ │ │ │ │ │ │ ├── IntermediateOperators.kt
│ │ │ │ │ │ │ │ └── IntermediateOperatorsVm.kt
│ │ │ │ │ │ │ ├── mutable_state_of_flow/
│ │ │ │ │ │ │ │ ├── MutableStateOfFlowDemo.kt
│ │ │ │ │ │ │ │ └── MutableStateOfFlowDemoVm.kt
│ │ │ │ │ │ │ ├── state_and_shared_flows/
│ │ │ │ │ │ │ │ ├── StateAndSharedFlowsDemo.kt
│ │ │ │ │ │ │ │ └── StateAndSharedFlowsDemoVm.kt
│ │ │ │ │ │ │ └── terminal_operators/
│ │ │ │ │ │ │ ├── TerminalOperators.kt
│ │ │ │ │ │ │ └── TerminalOperatorsVm.kt
│ │ │ │ │ │ ├── higher_order_functions/
│ │ │ │ │ │ │ └── ui/
│ │ │ │ │ │ │ ├── HigherOrderFunctionDemo.kt
│ │ │ │ │ │ │ └── HigherOrderFunctionDemoVm.kt
│ │ │ │ │ │ ├── kotlin_annotations/
│ │ │ │ │ │ │ ├── ui/
│ │ │ │ │ │ │ │ ├── KotlinAnnotationsDemoVm.kt
│ │ │ │ │ │ │ │ └── kotlinAnnotationsDemo.kt
│ │ │ │ │ │ │ └── utils/
│ │ │ │ │ │ │ ├── jvmField/
│ │ │ │ │ │ │ │ ├── JavaPerson.java
│ │ │ │ │ │ │ │ ├── KotlinPerson.kt
│ │ │ │ │ │ │ │ └── init/
│ │ │ │ │ │ │ │ ├── JavaInstanceJf.java
│ │ │ │ │ │ │ │ └── KotlinInstanceJf.kt
│ │ │ │ │ │ │ ├── jvmOverloads/
│ │ │ │ │ │ │ │ ├── Student1.kt
│ │ │ │ │ │ │ │ ├── Student2.kt
│ │ │ │ │ │ │ │ └── init/
│ │ │ │ │ │ │ │ ├── JavaInstanceJo.java
│ │ │ │ │ │ │ │ └── KotlinInstanceJo.kt
│ │ │ │ │ │ │ ├── jvmstatic/
│ │ │ │ │ │ │ │ ├── Cinema.kt
│ │ │ │ │ │ │ │ └── init/
│ │ │ │ │ │ │ │ ├── JavaInstanceJs.java
│ │ │ │ │ │ │ │ └── KotlinInstanceJs.kt
│ │ │ │ │ │ │ ├── nullableAndNotNull/
│ │ │ │ │ │ │ │ └── SuperHero.java
│ │ │ │ │ │ │ ├── stringDef/
│ │ │ │ │ │ │ │ ├── UserManager.kt
│ │ │ │ │ │ │ │ └── UserStatus.kt
│ │ │ │ │ │ │ └── stringRes/
│ │ │ │ │ │ │ ├── HomeNavItem.kt
│ │ │ │ │ │ │ └── init/
│ │ │ │ │ │ │ ├── JavaInstanceSr.java
│ │ │ │ │ │ │ └── KotlinInstanceSr.kt
│ │ │ │ │ │ ├── nested_vs_inner/
│ │ │ │ │ │ │ ├── ui/
│ │ │ │ │ │ │ │ ├── NestedVsInner.kt
│ │ │ │ │ │ │ │ └── NestedVsInnerVm.kt
│ │ │ │ │ │ │ └── utils/
│ │ │ │ │ │ │ └── OuterClass.kt
│ │ │ │ │ │ ├── sealed_class/
│ │ │ │ │ │ │ ├── ui/
│ │ │ │ │ │ │ │ ├── SealedClassDemo.kt
│ │ │ │ │ │ │ │ └── SealedClassDemoVm.kt
│ │ │ │ │ │ │ └── utils/
│ │ │ │ │ │ │ ├── Student/
│ │ │ │ │ │ │ │ └── Student.kt
│ │ │ │ │ │ │ ├── animals/
│ │ │ │ │ │ │ │ ├── Animal.kt
│ │ │ │ │ │ │ │ ├── Monkey.kt
│ │ │ │ │ │ │ │ └── Tiger.kt
│ │ │ │ │ │ │ ├── payment/
│ │ │ │ │ │ │ │ └── Payment.kt
│ │ │ │ │ │ │ └── superHero/
│ │ │ │ │ │ │ ├── Hero.kt
│ │ │ │ │ │ │ └── Payment.kt
│ │ │ │ │ │ └── type_alias/
│ │ │ │ │ │ ├── ui/
│ │ │ │ │ │ │ ├── TypeAlias.kt
│ │ │ │ │ │ │ └── TypeAliasVm.kt
│ │ │ │ │ │ └── utils/
│ │ │ │ │ │ └── TypeAliasReferences.kt
│ │ │ │ │ ├── module_exercises/
│ │ │ │ │ │ ├── ExerciseSelection.kt
│ │ │ │ │ │ ├── exercise_1/
│ │ │ │ │ │ │ ├── Exercise1.kt
│ │ │ │ │ │ │ └── Exercise1vm.kt
│ │ │ │ │ │ └── exercise_2/
│ │ │ │ │ │ ├── Exercise2.kt
│ │ │ │ │ │ └── Exercise2vm.kt
│ │ │ │ │ └── module_selection/
│ │ │ │ │ ├── ModuleDemo.kt
│ │ │ │ │ └── ModuleSelectionScreen.kt
│ │ │ │ ├── ui/
│ │ │ │ │ ├── composables/
│ │ │ │ │ │ ├── Buttons.kt
│ │ │ │ │ │ └── Text.kt
│ │ │ │ │ └── theme/
│ │ │ │ │ ├── Color.kt
│ │ │ │ │ ├── Shape.kt
│ │ │ │ │ ├── Theme.kt
│ │ │ │ │ └── Type.kt
│ │ │ │ └── utils/
│ │ │ │ ├── base/
│ │ │ │ │ └── BaseViewModel.kt
│ │ │ │ ├── endpoints/
│ │ │ │ │ └── EndPointSimulation.kt
│ │ │ │ ├── extensions/
│ │ │ │ │ ├── Activity.kt
│ │ │ │ │ └── Coroutine.kt
│ │ │ │ └── log/
│ │ │ │ └── ThreadInfoLogger.kt
│ │ │ └── res/
│ │ │ ├── drawable/
│ │ │ │ ├── ic_launcher_background.xml
│ │ │ │ └── ic_launcher_foreground.xml
│ │ │ ├── values/
│ │ │ │ ├── colors.xml
│ │ │ │ ├── strings.xml
│ │ │ │ └── themes.xml
│ │ │ └── xml/
│ │ │ ├── backup_rules.xml
│ │ │ └── data_extraction_rules.xml
│ │ └── test/
│ │ └── java/
│ │ └── com/
│ │ └── istudio/
│ │ └── app/
│ │ └── ExampleUnitTest.kt
│ ├── build.gradle.kts
│ ├── gradle/
│ │ └── wrapper/
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
│ ├── gradle.properties
│ ├── gradlew
│ ├── gradlew.bat
│ └── settings.gradle.kts
└── Sample-Coroutines/
├── .idea/
│ ├── .name
│ ├── compiler.xml
│ ├── deploymentTargetDropDown.xml
│ ├── deploymentTargetSelector.xml
│ ├── gradle.xml
│ ├── kotlinc.xml
│ ├── material_theme_project_new.xml
│ ├── migrations.xml
│ ├── misc.xml
│ ├── modules.xml
│ ├── other.xml
│ └── workspace.xml
├── README.md
├── app/
│ ├── .gitignore
│ ├── build.gradle
│ ├── proguard-rules.pro
│ └── src/
│ ├── androidTest/
│ │ └── java/
│ │ └── com/
│ │ └── demo/
│ │ └── code/
│ │ └── ExampleInstrumentedTest.kt
│ ├── main/
│ │ ├── AndroidManifest.xml
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── demo/
│ │ │ └── code/
│ │ │ ├── CoroutineUsecasesOnAndroidApplication.kt
│ │ │ ├── activities/
│ │ │ │ ├── JobsActivity.kt
│ │ │ │ ├── MainActivity.kt
│ │ │ │ ├── SelectionActivity.kt
│ │ │ │ └── SuspendingFuncActivity.kt
│ │ │ ├── base/
│ │ │ │ ├── BaseActivity.kt
│ │ │ │ ├── BaseViewModel.kt
│ │ │ │ ├── UseCase.kt
│ │ │ │ ├── UseCaseActivity.kt
│ │ │ │ ├── UseCaseAdapter.kt
│ │ │ │ └── UseCaseCategoryAdapter.kt
│ │ │ ├── mock/
│ │ │ │ ├── MockAnalyticsApi.kt
│ │ │ │ ├── MockApi.kt
│ │ │ │ └── MockData.kt
│ │ │ ├── modules/
│ │ │ │ ├── legacycode/
│ │ │ │ │ ├── LegacyCallbackSampleOne.kt
│ │ │ │ │ ├── LegacyCallbackSampleTwo.kt
│ │ │ │ │ └── User.kt
│ │ │ │ ├── observabletypes/
│ │ │ │ │ ├── ObservableTypesActivity.kt
│ │ │ │ │ └── ObservableTypesViewModel.kt
│ │ │ │ └── placeholder
│ │ │ ├── playground/
│ │ │ │ ├── cancellation/
│ │ │ │ │ ├── 1_cancellation.kt
│ │ │ │ │ └── 2_cooperative_cancellation.kt
│ │ │ │ ├── coroutine_scope.kt
│ │ │ │ ├── coroutinebuilders/
│ │ │ │ │ ├── 1_launch.kt
│ │ │ │ │ └── 2_async.kt
│ │ │ │ ├── exceptionhandling/
│ │ │ │ │ ├── 1_try_catch.kt
│ │ │ │ │ ├── 2_coroutine_exception_handler.kt
│ │ │ │ │ ├── 3_try_catch_vs_exception_handler.kt
│ │ │ │ │ ├── 4_launch_and_async.kt
│ │ │ │ │ ├── 5_exception_handling_specifics_coroutineScope.kt
│ │ │ │ │ └── 6_exception_handling_specifics_supervisorScope.kt
│ │ │ │ ├── fundamentals/
│ │ │ │ │ ├── 10_how_delay_works.kt
│ │ │ │ │ ├── 1_routines.kt
│ │ │ │ │ ├── 2_coroutines.kt
│ │ │ │ │ ├── 3_routines_threads.kt
│ │ │ │ │ ├── 4_coroutines_with_thread_info.kt
│ │ │ │ │ ├── 5_starting_lots_of_coroutines.kt
│ │ │ │ │ ├── 7_starting_lots_of_threads.kt
│ │ │ │ │ ├── 8_suspending_coroutines.kt
│ │ │ │ │ └── 9_coroutine_in_different_threads.kt
│ │ │ │ └── structuredconcurrency/
│ │ │ │ ├── 1_coroutines_need_to_be_started_in_scope.kt
│ │ │ │ ├── 2_job_hierarchy.kt
│ │ │ │ ├── 3_parents_wait_for_children.kt
│ │ │ │ ├── 4_cancelling_parents_and_children.kt
│ │ │ │ ├── 5_exception_propagation.kt
│ │ │ │ ├── 6_globalscope.kt
│ │ │ │ └── 7_scoping_functions.kt
│ │ │ ├── usecases/
│ │ │ │ ├── channels/
│ │ │ │ │ └── usecase1/
│ │ │ │ │ └── ChannelUseCase1Activity.kt
│ │ │ │ ├── coroutines/
│ │ │ │ │ ├── usecase1/
│ │ │ │ │ │ ├── MockApi.kt
│ │ │ │ │ │ ├── PerformSingleNetworkRequestActivity.kt
│ │ │ │ │ │ ├── PerformSingleNetworkRequestViewModel.kt
│ │ │ │ │ │ └── UiState.kt
│ │ │ │ │ ├── usecase10/
│ │ │ │ │ │ ├── CalculationInBackgroundActivity.kt
│ │ │ │ │ │ ├── CalculationInBackgroundViewModel.kt
│ │ │ │ │ │ └── UiState.kt
│ │ │ │ │ ├── usecase11/
│ │ │ │ │ │ ├── CooperativeCancellationActivity.kt
│ │ │ │ │ │ ├── CooperativeCancellationViewModel.kt
│ │ │ │ │ │ └── UiState.kt
│ │ │ │ │ ├── usecase12/
│ │ │ │ │ │ ├── CalculationInSeveralCoroutinesActivity.kt
│ │ │ │ │ │ ├── CalculationInSeveralCoroutinesViewModel.kt
│ │ │ │ │ │ ├── FactorialCalculator.kt
│ │ │ │ │ │ └── UiState.kt
│ │ │ │ │ ├── usecase13/
│ │ │ │ │ │ ├── ExceptionHandlingActivity.kt
│ │ │ │ │ │ ├── ExceptionHandlingViewModel.kt
│ │ │ │ │ │ ├── MockApi.kt
│ │ │ │ │ │ └── UiState.kt
│ │ │ │ │ ├── usecase14/
│ │ │ │ │ │ ├── AndroidVersionDao.kt
│ │ │ │ │ │ ├── AndroidVersionDatabase.kt
│ │ │ │ │ │ ├── AndroidVersionEntity.kt
│ │ │ │ │ │ ├── AndroidVersionRepository.kt
│ │ │ │ │ │ ├── ContinueCoroutineWhenUserLeavesScreenActivity.kt
│ │ │ │ │ │ ├── ContinueCoroutineWhenUserLeavesScreenViewModel.kt
│ │ │ │ │ │ ├── MockApi.kt
│ │ │ │ │ │ ├── UiState.kt
│ │ │ │ │ │ └── ViewModelFactory.kt
│ │ │ │ │ ├── usecase15/
│ │ │ │ │ │ ├── AnalyticsWorker.kt
│ │ │ │ │ │ ├── ViewModelFactory.kt
│ │ │ │ │ │ ├── WorkManagerActivity.kt
│ │ │ │ │ │ └── WorkManagerViewModel.kt
│ │ │ │ │ ├── usecase16/
│ │ │ │ │ │ ├── FactorialCalculator.kt
│ │ │ │ │ │ ├── PerformanceAnalysisActivity.kt
│ │ │ │ │ │ ├── PerformanceAnalysisViewModel.kt
│ │ │ │ │ │ ├── ResultAdapter.kt
│ │ │ │ │ │ └── UiState.kt
│ │ │ │ │ ├── usecase17/
│ │ │ │ │ │ ├── PerformCalculationOnMainThreadActivity.kt
│ │ │ │ │ │ ├── PerformCalculationOnMainThreadViewModel.kt
│ │ │ │ │ │ └── UiState.kt
│ │ │ │ │ ├── usecase2/
│ │ │ │ │ │ ├── MockApi.kt
│ │ │ │ │ │ ├── Perform2SequentialNetworkRequestsActivity.kt
│ │ │ │ │ │ ├── Perform2SequentialNetworkRequestsViewModel.kt
│ │ │ │ │ │ ├── UiState.kt
│ │ │ │ │ │ ├── callbacks/
│ │ │ │ │ │ │ ├── MockApi.kt
│ │ │ │ │ │ │ ├── SequentialNetworkRequestsCallbacksActivity.kt
│ │ │ │ │ │ │ ├── SequentialNetworkRequestsCallbacksViewModel.kt
│ │ │ │ │ │ │ └── UiState.kt
│ │ │ │ │ │ └── rx/
│ │ │ │ │ │ ├── MockApi.kt
│ │ │ │ │ │ ├── SequentialNetworkRequestsRxActivity.kt
│ │ │ │ │ │ ├── SequentialNetworkRequestsRxViewModel.kt
│ │ │ │ │ │ └── UiState.kt
│ │ │ │ │ ├── usecase3/
│ │ │ │ │ │ ├── MockApi.kt
│ │ │ │ │ │ ├── PerformNetworkRequestsConcurrentlyActivity.kt
│ │ │ │ │ │ ├── PerformNetworkRequestsConcurrentlyViewModel.kt
│ │ │ │ │ │ └── UiState.kt
│ │ │ │ │ ├── usecase4/
│ │ │ │ │ │ ├── MockApi.kt
│ │ │ │ │ │ ├── UiState.kt
│ │ │ │ │ │ ├── VariableAmountOfNetworkRequestsActivity.kt
│ │ │ │ │ │ └── VariableAmountOfNetworkRequestsViewModel.kt
│ │ │ │ │ ├── usecase5/
│ │ │ │ │ │ ├── MockApi.kt
│ │ │ │ │ │ ├── NetworkRequestWithTimeoutActivity.kt
│ │ │ │ │ │ ├── NetworkRequestWithTimeoutViewModel.kt
│ │ │ │ │ │ └── UiState.kt
│ │ │ │ │ ├── usecase6/
│ │ │ │ │ │ ├── MockApi.kt
│ │ │ │ │ │ ├── RetryNetworkRequestActivity.kt
│ │ │ │ │ │ ├── RetryNetworkRequestViewModel.kt
│ │ │ │ │ │ └── UiState.kt
│ │ │ │ │ ├── usecase7/
│ │ │ │ │ │ ├── MockApi.kt
│ │ │ │ │ │ ├── TimeoutAndRetryActivity.kt
│ │ │ │ │ │ ├── TimeoutAndRetryViewModel.kt
│ │ │ │ │ │ ├── UiState.kt
│ │ │ │ │ │ ├── callbacks/
│ │ │ │ │ │ │ ├── MockApi.kt
│ │ │ │ │ │ │ ├── TimeoutAndRetryCallbackActivity.kt
│ │ │ │ │ │ │ ├── TimeoutAndRetryCallbackViewModel.kt
│ │ │ │ │ │ │ └── UiState.kt
│ │ │ │ │ │ └── rx/
│ │ │ │ │ │ ├── MockApi.kt
│ │ │ │ │ │ ├── TimeoutAndRetryRxActivity.kt
│ │ │ │ │ │ ├── TimeoutAndRetryRxViewModel.kt
│ │ │ │ │ │ └── UiState.kt
│ │ │ │ │ ├── usecase8/
│ │ │ │ │ │ ├── AndroidVersionDao.kt
│ │ │ │ │ │ ├── AndroidVersionDatabase.kt
│ │ │ │ │ │ ├── AndroidVersionEntity.kt
│ │ │ │ │ │ ├── MockApi.kt
│ │ │ │ │ │ ├── RoomAndCoroutinesActivity.kt
│ │ │ │ │ │ ├── RoomAndCoroutinesViewModel.kt
│ │ │ │ │ │ ├── UiState.kt
│ │ │ │ │ │ └── ViewModelFactory.kt
│ │ │ │ │ └── usecase9/
│ │ │ │ │ ├── DebuggingCoroutinesActivity.kt
│ │ │ │ │ ├── DebuggingCoroutinesViewModel.kt
│ │ │ │ │ ├── MockApi.kt
│ │ │ │ │ └── UiState.kt
│ │ │ │ └── flow/
│ │ │ │ └── usecase1/
│ │ │ │ └── FlowUseCase1Activity.kt
│ │ │ └── utils/
│ │ │ ├── Extensions.kt
│ │ │ └── MockNetworkInterceptor.kt
│ │ └── res/
│ │ ├── drawable/
│ │ │ ├── ic_arrow_back_white.xml
│ │ │ ├── ic_check_green_24dp.xml
│ │ │ ├── ic_clear_red_24dp.xml
│ │ │ ├── ic_launcher_background.xml
│ │ │ └── recyclerview_divider.xml
│ │ ├── drawable-v24/
│ │ │ └── ic_launcher_foreground.xml
│ │ ├── layout/
│ │ │ ├── activity_calculateonmain.xml
│ │ │ ├── activity_calculationinbackground.xml
│ │ │ ├── activity_calculationinmultiplebackgroundthreads.xml
│ │ │ ├── activity_channels_usecase1.xml
│ │ │ ├── activity_cooperativecancellation.xml
│ │ │ ├── activity_debuggingcoroutines.xml
│ │ │ ├── activity_exceptionhandling.xml
│ │ │ ├── activity_flow_usecase1.xml
│ │ │ ├── activity_jobs.xml
│ │ │ ├── activity_main.xml
│ │ │ ├── activity_networkrequestwithtimeout.xml
│ │ │ ├── activity_observable_types.xml
│ │ │ ├── activity_perform2sequentialnetworkrequests.xml
│ │ │ ├── activity_performanceanalysis.xml
│ │ │ ├── activity_performnetworkrequestsconcurrently.xml
│ │ │ ├── activity_performsinglenetworkrequest.xml
│ │ │ ├── activity_performvariableamountofnetworkrequestsconcurrently.xml
│ │ │ ├── activity_queryfromroomdatabase.xml
│ │ │ ├── activity_retrynetworkrequest.xml
│ │ │ ├── activity_selection.xml
│ │ │ ├── activity_suspending_func.xml
│ │ │ ├── activity_usecases.xml
│ │ │ ├── activity_workmanger.xml
│ │ │ ├── recyclerview_item.xml
│ │ │ ├── recyclerview_item_calculation_result.xml
│ │ │ └── toolbar.xml
│ │ ├── mipmap-anydpi-v26/
│ │ │ ├── ic_launcher.xml
│ │ │ └── ic_launcher_round.xml
│ │ └── values/
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test/
│ └── java/
│ └── com/
│ └── demo/
│ └── code/
│ ├── ExampleUnitTest.kt
│ ├── playground/
│ │ └── testing/
│ │ └── 1_testing_coroutines.kt
│ ├── usecases/
│ │ └── coroutines/
│ │ ├── usecase1/
│ │ │ ├── FakeErrorApi.kt
│ │ │ ├── FakeSuccessApi.kt
│ │ │ └── PerformSingleNetworkRequestViewModelTest.kt
│ │ ├── usecase10/
│ │ │ └── CalculationInBackgroundViewModelTest.kt
│ │ ├── usecase12/
│ │ │ └── FactorialCalculatorTest.kt
│ │ ├── usecase14/
│ │ │ ├── AndroidVersionRepositoryTest.kt
│ │ │ ├── FakeApi.kt
│ │ │ └── FakeDatabase.kt
│ │ ├── usecase2/
│ │ │ ├── FakeFeaturesErrorApi.kt
│ │ │ ├── FakeSuccessApi.kt
│ │ │ ├── FakeVersionsErrorApi.kt
│ │ │ ├── Perform2SequentialNetworkRequestsViewModelTest.kt
│ │ │ └── callbacks/
│ │ │ ├── FakeFeaturesErrorApi.kt
│ │ │ ├── FakeSuccessApi.kt
│ │ │ ├── FakeVersionsErrorApi.kt
│ │ │ └── SequentialNetworkRequestsCallbacksViewModelTest.kt
│ │ ├── usecase3/
│ │ │ ├── FakeErrorApi.kt
│ │ │ ├── FakeSuccessApi.kt
│ │ │ └── PerformNetworkRequestsConcurrentlyViewModelTest.kt
│ │ ├── usecase4/
│ │ │ ├── FakeFeaturesErrorApi.kt
│ │ │ ├── FakeSuccessApi.kt
│ │ │ ├── FakeVersionsErrorApi.kt
│ │ │ └── VariableAmountOfNetworkRequestsViewModelTest.kt
│ │ ├── usecase5/
│ │ │ ├── FakeSuccessApi.kt
│ │ │ ├── FakeVersionsErrorApi.kt
│ │ │ └── NetworkRequestWithTimeoutViewModelTest.kt
│ │ └── usecase6/
│ │ ├── FakeSuccessApi.kt
│ │ ├── FakeSuccessOnThirdAttemptApi.kt
│ │ ├── FakeVersionsErrorApi.kt
│ │ └── RetryNetworkRequestViewModelTest.kt
│ └── utils/
│ ├── EndpointShouldNotBeCalledException.kt
│ └── MainCoroutineScopeRule.kt
├── build.gradle.kts
├── buildSrc/
│ ├── build.gradle.kts
│ └── src/
│ └── main/
│ └── java/
│ ├── AppConfig.kt
│ ├── AppDependencies.kt
│ ├── BuildPlugins.kt
│ └── Versions.kt
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
└── settings.gradle.kts
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Built application files
*.apk
*.aar
*.ap_
*.aab
# Files for the ART/Dalvik VM
*.dex
# Java class files
*.class
# Generated files
bin/
gen/
out/
# Uncomment the following line in case you need and you don't have the release build type files in your app
# release/
# Gradle files
.gradle/
build/
# Local configuration file (sdk path, etc)
local.properties
# Proguard folder generated by Eclipse
proguard/
# Log Files
*.log
# Android Studio Navigation editor temp files
.navigation/
# Android Studio captures folder
captures/
# IntelliJ
*.iml
.idea/workspace.xml
.idea/tasks.xml
.idea/gradle.xml
.idea/assetWizardSettings.xml
.idea/dictionaries
.idea/libraries
# Android Studio 3 in .gitignore file.
.idea/caches
.idea/modules.xml
# Comment next line if keeping position of elements in Navigation Editor is relevant for you
.idea/navEditor.xml
# Keystore files
# Uncomment the following lines if you do not want to check your keystore files in.
#*.jks
#*.keystore
# External native build folder generated in Android Studio 2.2 and later
.externalNativeBuild
.cxx/
# Google Services (e.g. APIs or Firebase)
# google-services.json
# Freeline
freeline.py
freeline/
freeline_project_description.json
# fastlane
fastlane/report.xml
fastlane/Preview.html
fastlane/screenshots
fastlane/test_output
fastlane/readme.md
# Version control
vcs.xml
# lint
lint/intermediates/
lint/generated/
lint/outputs/
lint/tmp/
# lint/reports/
================================================
FILE: .idea/.gitignore
================================================
# Default ignored files
/shelf/
/workspace.xml
================================================
FILE: .idea/.name
================================================
My Application
================================================
FILE: .idea/compiler.xml
================================================
================================================
FILE: .idea/jarRepositories.xml
================================================
================================================
FILE: .idea/misc.xml
================================================
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.
================================================
FILE: CONTRIBUTING.md
================================================
## Feeling Awesome! Thanks for thinking about this.
You can contribute us by filing issues, bugs and PRs. You can also take a look at active issues and fix them.
If you want to discuss on something then feel free to present your opinions, views or any other relevant comment on [discussions](https://github.com/devrath/DroidAndroidKotlinWiki/discussions).
### Code contribution
- Open issue regarding proposed change.
- If your proposed change is approved, Fork this repo and do changes.
- Open PR against latest *development* branch. Add nice description in PR.
- You're done!
### How to Contribute
- Fork it
- Create your feature branch (git checkout -b my-new-feature)
- Commit your changes (git commit -am 'Add some feature')
- Push to the branch (git push origin my-new-feature)
- Create new Pull Request
### Code contribution checklist
- New code addition/deletion should not break existing flow of a system.
- All tests should be passed.
- Verify `./gradlew build` is passing before raising a PR.
- Reformat code with Spotless `./gradlew spotlessApply` before raising a PR.
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: README.md
================================================
𝙺𝚘𝚝𝚕𝚒𝚗𝙰𝚕𝚌𝚑𝚎𝚖𝚢

⚗️ 𝚃𝚑𝚒𝚜 𝚙𝚛𝚘𝚓𝚎𝚌𝚝 𝚌𝚘𝚗𝚝𝚊𝚒𝚗𝚜 𝚟𝚊𝚛𝚒𝚘𝚞𝚜 𝚌𝚘𝚗𝚌𝚎𝚙𝚝𝚜 𝚊𝚗𝚍 𝚕𝚎𝚊𝚛𝚗𝚒𝚗𝚐𝚜 𝚘𝚏 𝚔𝚘𝚝𝚕𝚒𝚗 𝚞𝚜𝚎𝚍 𝚏𝚘𝚛 𝚊𝚗𝚍𝚛𝚘𝚒𝚍 𝚍𝚎𝚟𝚎𝚕𝚘𝚙𝚖𝚎𝚗𝚝
| `𝙲𝙾𝙽𝚃𝙴𝙽𝚃𝚂` |
| ---------- |
| [`𝙺𝚘𝚝𝚕𝚒𝚗 𝙱𝚊𝚜𝚒𝚌 𝙵𝚞𝚗𝚍𝚊𝚖𝚎𝚗𝚝𝚊𝚕𝚜`](https://github.com/devrath/KotlinAlchemy/wiki/Kotlin-Basic-Fundamentals) |
| [`𝙺𝚘𝚝𝚕𝚒𝚗 𝚌𝚘𝚕𝚕𝚎𝚌𝚝𝚒𝚘𝚗 𝚏𝚞𝚗𝚌𝚝𝚒𝚘𝚗𝚜`](https://github.com/devrath/KotlinAlchemy/blob/main/README.md#kotlin-collection-functions)
| [`𝙺𝚘𝚝𝚕𝚒𝚗 𝙿𝚘𝚠𝚎𝚛𝚜`](https://github.com/devrath/KotlinAlchemy/blob/main/README.md#kotlin-powers) |
| [`𝙺𝚘𝚝𝚕𝚒𝚗 𝙲𝚘𝚛𝚘𝚞𝚝𝚒𝚗𝚎𝚜`](https://github.com/devrath/KotlinAlchemy/blob/main/README.md#kotlin-coroutines) |
# `Kotlin Basic Fundamentals`

* [**`𝚄𝚜𝚒𝚗𝚐 𝚅𝙰𝙻 𝚊𝚗𝚍 𝚅𝙰𝚁 𝚒𝚗 𝚔𝚘𝚝𝚕𝚒𝚗`**](https://github.com/devrath/KotlinAlchemy/wiki/Using-val-and-var-in-Kotlin)
* [**`𝚄𝚜𝚒𝚗𝚐 (𝚅𝙰𝙻) 𝚊𝚗𝚍 (𝙲𝙾𝙽𝚂𝚃 𝚅𝙰𝙻) 𝚒𝚗 𝙺𝚘𝚝𝚕𝚒𝚗`**](https://github.com/devrath/KotlinAlchemy/wiki/Using-(val)-and-(const-val)-in-Kotlin)
* [**`𝚄𝚜𝚒𝚗𝚐 𝚂𝚝𝚛𝚒𝚗𝚐𝚜 𝚒𝚗 𝙺𝚘𝚝𝚕𝚒𝚗`**](https://github.com/devrath/KotlinAlchemy/wiki/Kotlin-Basics-:-Strings)
* [**`𝚄𝚜𝚒𝚗𝚐 𝚌𝚘𝚖𝚙𝚊𝚛𝚒𝚜𝚘𝚗 𝚘𝚙𝚎𝚛𝚊𝚝𝚘𝚛𝚜`**](https://github.com/devrath/KotlinAlchemy/wiki/Kotlin-Basics-:-Comparison-Operators)
* [**`𝚆𝚑𝚊𝚝 𝚒𝚜 𝚝𝚑𝚎 𝚜𝚌𝚘𝚙𝚎 𝚒𝚗 𝚔𝚘𝚝𝚕𝚒𝚗`**](https://github.com/devrath/KotlinAlchemy/wiki/Kotlin-Basics-:-Using-Scopes-in-kotlin)
* [**`𝙻𝚊𝚛𝚐𝚎 𝚝𝚛𝚎𝚎 𝚘𝚏 𝚌𝚘𝚗𝚍𝚒𝚝𝚒𝚘𝚗 𝚜𝚝𝚊𝚝𝚎𝚖𝚎𝚗𝚝𝚜`**](https://github.com/devrath/KotlinAlchemy/wiki/Kotlin-Basics:-Large-tree-of-condition-statements)
* [**`𝙳𝚎𝚏𝚒𝚗𝚒𝚗𝚐 𝚊𝚗𝚍 𝚞𝚜𝚒𝚗𝚐 𝙽𝚞𝚕𝚕𝚊𝚋𝚕𝚎 𝚟𝚊𝚕𝚞𝚎𝚜`**](https://github.com/devrath/KotlinAlchemy/wiki/Kotlin-Basics:-Defining-and-using-Nullable-values)
* [**`𝚆𝚑𝚊𝚝 𝚊𝚛𝚎 𝚙𝚊𝚒𝚛𝚜 𝚊𝚗𝚍 𝚝𝚛𝚒𝚙𝚕𝚎𝚝𝚜`**](https://github.com/devrath/KotlinAlchemy/wiki/Kotlin-Basics-:-What-are-pairs-and-triplets)
* [**`𝙼𝚎𝚖𝚋𝚎𝚛 𝚁𝚎𝚏𝚎𝚛𝚎𝚗𝚌𝚎 𝚒𝚗 𝙺𝚘𝚝𝚕𝚒𝚗: 𝚄𝚜𝚒𝚗𝚐 (::) 𝙾𝚙𝚎𝚛𝚊𝚝𝚘𝚛`**](https://github.com/devrath/KotlinAlchemy/wiki/Member-Reference-in-Kotlin:-Using-(::)-Operator)
* [**`𝚆𝚑𝚊𝚝 𝚊𝚛𝚎 𝚝𝚑𝚎 𝚍𝚒𝚏𝚏𝚎𝚛𝚎𝚗𝚌𝚎𝚜 𝚋𝚎𝚝𝚠𝚎𝚎𝚗 𝚊𝚗 𝙴𝚚𝚞𝚊𝚕𝚒𝚝𝚢 𝙾𝚙𝚎𝚛𝚊𝚝𝚘𝚛 𝚊𝚗𝚍 𝚊 𝚁𝚎𝚏𝚎𝚛𝚎𝚗𝚝𝚒𝚊𝚕 𝙴𝚚𝚞𝚊𝚕𝚒𝚝𝚢 𝙾𝚙𝚎𝚛𝚊𝚝𝚘𝚛?`**](https://github.com/devrath/KotlinAlchemy/wiki/What-are-the-difference-between-Equality-Operator-and-Referential-Equality-Operator)
* [**`𝙻𝚘𝚘𝚙𝚒𝚗𝚐 𝚖𝚎𝚌𝚑𝚊𝚗𝚒𝚜𝚖𝚜 𝚒𝚗 𝚔𝚘𝚝𝚕𝚒𝚗`**](https://github.com/devrath/KotlinAlchemy/wiki/Kotlin-basics-:-Looping-mechanisms)
* [**`𝙲𝚞𝚜𝚝𝚘𝚖 𝙰𝚌𝚌𝚎𝚜𝚜𝚘𝚛𝚜 𝚒𝚗 𝚔𝚘𝚝𝚕𝚒𝚗`**](https://github.com/devrath/KotlinAlchemy/wiki/Kotlin-basics-:-Custom-Accessors)
* [**`𝙴𝚗𝚞𝚖 𝚒𝚗 𝙺𝚘𝚝𝚕𝚒𝚗`**](https://github.com/devrath/KotlinAlchemy/wiki/Kotlin-basics-:-Enum-in-Kotlin)
* **Classes and Interfaces**
* [**`𝙲𝚕𝚊𝚜𝚜𝚎𝚜`**](https://github.com/devrath/KotlinAlchemy/wiki/Kotlin-Fundamentals:-Classes)
* [**`𝙸𝚗𝚑𝚎𝚛𝚒𝚝𝚊𝚗𝚌𝚎`**](https://github.com/devrath/KotlinAlchemy/wiki/Kotlin-Fundamentals:-Inheritance)
* **Kotlin Basic collections**
* [**`𝚄𝚜𝚒𝚗𝚐 𝚊𝚛𝚛𝚊𝚢𝚜 𝚒𝚗 𝚝𝚑𝚎 𝚌𝚘𝚍𝚎`**](https://github.com/devrath/KotlinAlchemy/wiki/Kotlin-basics-:-Using-arrays-in-the-code)
* [**`𝚄𝚜𝚒𝚗𝚐 𝚕𝚒𝚜𝚝 𝚒𝚗 𝚝𝚑𝚎 𝚌𝚘𝚍𝚎`**](https://github.com/devrath/KotlinAlchemy/wiki/Kotlin-basics-:-Using-list-in-the-code)
* [**`𝚄𝚜𝚒𝚗𝚐 𝙼𝚊𝚙 𝚒𝚗 𝚝𝚑𝚎 𝚌𝚘𝚍𝚎`**](https://github.com/devrath/KotlinAlchemy/wiki/Kotlin-basics-:-Using-Map-in-the-code)
* [**`𝚄𝚜𝚒𝚗𝚐 𝚂𝚎𝚝 𝚒𝚗 𝚝𝚑𝚎 𝚌𝚘𝚍𝚎`**](https://github.com/devrath/KotlinAlchemy/wiki/kotlin-basics-:-Using-Set-in-the-code)
# `Kotlin Collection Functions`
| `Operation` | `Operators` |
| ----------- | ------------------------------------------------------------ |
| [`Removing Duplicates`](https://github.com/devrath/KotlinAlchemy/wiki/Collections:-Removing-duplicates) | `distinct` , `toSet` . `toMutableSet`, `toHashSet` |
| [`Combining a list of items to a string`](https://github.com/devrath/KotlinAlchemy/wiki/Collections:-Converting--a-list-array-to-string) | `joinToString` |
| [`Transform a collection into a single result`](https://github.com/devrath/KotlinAlchemy/wiki/Collections:-Transform-a-collection-into-a-single-result) | `reduce` |
| [`Find if all elements are satisfying a particular condition`](https://github.com/devrath/KotlinAlchemy/wiki/Collection:-Find-if-all-elements-are-satisfying-a-particular-condition) | `all` |
| [`Find a particular element based on a certain condition`](https://github.com/devrath/KotlinAlchemy/wiki/Collection:-Find-a-particular-element-based-on-a-certain-condition) | `single`,`all` |
| [`Break the list of items to sub‐chunks of items`](https://github.com/devrath/KotlinAlchemy/wiki/Collections:-Break-the-list-of-items-to-sub%E2%80%90chunks-of-items) | `chunked` |
| [`Associating the data using some key`](https://github.com/devrath/KotlinAlchemy/wiki/Collections:-Associating-the-data-using-some-key) | `AssociateBy` |
| [`Using the Intersection and Union`](https://github.com/devrath/KotlinAlchemy/wiki/Collection:-Intersection-&-Union) | `union`,`intersect` |
| [`Sorting a collection of objects based on a parameter in the object`](https://github.com/devrath/KotlinAlchemy/wiki/Collection:-Sorting-a-collection-of-objects-based-on-a-parameter-in-the-object) | `sortBy` |
# `Kotlin Powers`
| `🪴` | `🍀` | `🌿` |
| ---------- | --------------------------------------------- | --------------------------------------------- |
| [`𝙺𝚘𝚝𝚕𝚒𝚗 𝚂𝚌𝚘𝚙𝚎 𝙵𝚞𝚗𝚌𝚝𝚒𝚘𝚗𝚜`](https://github.com/devrath/KotlinAlchemy/wiki/Kotlin-scope-functions) | [`𝙺𝚘𝚝𝚕𝚒𝚗: 𝙲𝚕𝚊𝚜𝚜 𝚟𝚜 𝙳𝚊𝚝𝚊𝙲𝚕𝚊𝚜𝚜`](https://github.com/devrath/KotlinAlchemy/wiki/Kotlin:-Class-vs-DataClass) | [`𝚂𝚎𝚊𝚕𝚎𝚍 𝚌𝚕𝚊𝚜𝚜𝚎𝚜`](https://github.com/devrath/KotlinAlchemy/wiki/Sealed-Class) |
| [`𝙷𝚒𝚐𝚑𝚎𝚛-𝚘𝚛𝚍𝚎𝚛 𝚏𝚞𝚗𝚌𝚝𝚒𝚘𝚗𝚜`](https://github.com/devrath/KotlinAlchemy/wiki/Higher-order-functions) | [`𝙺𝚘𝚝𝚕𝚒𝚗 𝙾𝚋𝚓𝚎𝚌𝚝`](https://github.com/devrath/KotlinAlchemy/wiki/Kotlin-Object) | [`𝙺𝚘𝚝𝚕𝚒𝚗 𝙲𝚘𝚖𝚙𝚊𝚗𝚒𝚘𝚗 𝙾𝚋𝚓𝚎𝚌𝚝`](https://github.com/devrath/KotlinAlchemy/wiki/Kotlin-Companion-Object) |
| [`𝙰𝚗𝚗𝚘𝚝𝚊𝚝𝚒𝚘𝚗𝚜 𝚒𝚗 𝚔𝚘𝚝𝚕𝚒𝚗`](https://github.com/devrath/KotlinAlchemy/wiki/Annotations-in-kotlin) | [`𝚃𝚢𝚙𝚎 𝙰𝚕𝚒𝚊𝚜`](https://github.com/devrath/KotlinAlchemy/wiki/Kotlin:-Type-Alias) | [`𝙸𝚗𝚕𝚒𝚗𝚎 𝙵𝚞𝚗𝚌𝚝𝚒𝚘𝚗`](https://github.com/devrath/KotlinAlchemy/wiki/Kotlin:-Inline-Functions) |
| [`𝚂𝚖𝚊𝚛𝚝 𝙲𝚊𝚜𝚝𝚜`](https://github.com/devrath/KotlinAlchemy/wiki/Kotlin:-Smart-Casts) | [`𝙽𝚎𝚜𝚝𝚎𝚍 𝚌𝚕𝚊𝚜𝚜 𝚟𝚜 𝙸𝚗𝚗𝚎𝚛 𝚌𝚕𝚊𝚜𝚜`](https://github.com/devrath/KotlinAlchemy/wiki/Nested-class-vs-Inner-class) | [`𝚂𝚎𝚊𝚕𝚎𝚍 𝙲𝚕𝚊𝚜𝚜`](https://github.com/devrath/KotlinAlchemy/wiki/Sealed-Class) |
| [`𝙰𝚗𝚗𝚘𝚝𝚊𝚝𝚒𝚘𝚗𝚜 𝚒𝚗 𝚔𝚘𝚝𝚕𝚒𝚗`](https://github.com/devrath/KotlinAlchemy/wiki/Annotations-in-kotlin) | [`𝙶𝚎𝚗𝚎𝚛𝚒𝚌𝚜`](https://github.com/devrath/KotlinAlchemy/wiki/Kotlin-Generics) | [`𝚁𝚎𝚒𝚏𝚒𝚎𝚍`](https://github.com/devrath/KotlinAlchemy/wiki/Reified) |
| [`𝙲𝚛𝚘𝚜𝚜𝚕𝚒𝚗𝚎 𝚖𝚘𝚍𝚒𝚏𝚒𝚎𝚛`](https://github.com/devrath/KotlinAlchemy/wiki/Crossline-modifier) | [ `𝚍𝚎𝚕𝚎𝚐𝚊𝚝𝚒𝚘𝚗 𝚒𝚗 𝚔𝚘𝚝𝚕𝚒𝚗` ](https://github.com/devrath/KotlinAlchemy/wiki/what-is-delegation-in-kotlin) | [`𝚂𝚎𝚚𝚞𝚎𝚗𝚌𝚎𝚜`](https://github.com/devrath/KotlinAlchemy/wiki/Sequences-in-kotlin) |
| [`noinline`](https://github.com/devrath/KotlinAlchemy/wiki/noinline) | [`𝚆𝚑𝚊𝚝 𝚊𝚛𝚎 𝚎𝚡𝚝𝚎𝚗𝚜𝚒𝚘𝚗 𝚏𝚞𝚗𝚌𝚝𝚒𝚘𝚗𝚜?`](https://github.com/devrath/KotlinAlchemy/wiki/What-are-extension-functions) | [`𝚂𝚎𝚊𝚕𝚎𝚍 𝙸𝚗𝚝𝚎𝚛𝚏𝚊𝚌𝚎`](https://github.com/devrath/KotlinAlchemy/wiki/sealed-interface) |
| [`𝙺𝚘𝚝𝚕𝚒𝚗: 𝙾𝚋𝚓𝚎𝚌𝚝 𝙲𝚕𝚊𝚜𝚜 𝚟𝚜 𝙳𝚊𝚝𝚊 𝙾𝚋𝚓𝚎𝚌𝚝 𝙲𝚕𝚊𝚜𝚜`](https://github.com/devrath/KotlinAlchemy/wiki/Kotlin:-Object-Class-vs-Data-Object-Class) | | |
# `Kotlin Coroutines`
| `Contents` |
| ---------- |
| [𝙵𝚞𝚗𝚍𝚊𝚖𝚎𝚗𝚝𝚊𝚕 𝚌𝚘𝚗𝚌𝚎𝚙𝚝𝚜 𝚘𝚏 𝚌𝚘𝚛𝚘𝚞𝚝𝚒𝚗𝚎𝚜](https://github.com/devrath/KotlinAlchemy/blob/main/README.md#%F0%9D%99%B5%F0%9D%9A%9E%F0%9D%9A%97%F0%9D%9A%8D%F0%9D%9A%8A%F0%9D%9A%96%F0%9D%9A%8E%F0%9D%9A%97%F0%9D%9A%9D%F0%9D%9A%8A%F0%9D%9A%95-%F0%9D%9A%8C%F0%9D%9A%98%F0%9D%9A%97%F0%9D%9A%8C%F0%9D%9A%8E%F0%9D%9A%99%F0%9D%9A%9D%F0%9D%9A%9C-%F0%9D%9A%98%F0%9D%9A%8F-%F0%9D%9A%8C%F0%9D%9A%98%F0%9D%9A%9B%F0%9D%9A%98%F0%9D%9A%9E%F0%9D%9A%9D%F0%9D%9A%92%F0%9D%9A%97%F0%9D%9A%8E%F0%9D%9A%9C) |
| [𝙲𝚘𝚖𝚖𝚞𝚗𝚒𝚌𝚊𝚝𝚒𝚗𝚐 𝚋𝚎𝚝𝚠𝚎𝚎𝚗 𝚌𝚘-𝚛𝚘𝚞𝚝𝚒𝚗𝚎𝚜](https://github.com/devrath/KotlinAlchemy/blob/main/README.md#%F0%9D%99%B2%F0%9D%9A%98%F0%9D%9A%96%F0%9D%9A%96%F0%9D%9A%9E%F0%9D%9A%97%F0%9D%9A%92%F0%9D%9A%8C%F0%9D%9A%8A%F0%9D%9A%9D%F0%9D%9A%92%F0%9D%9A%97%F0%9D%9A%90-%F0%9D%9A%8B%F0%9D%9A%8E%F0%9D%9A%9D%F0%9D%9A%A0%F0%9D%9A%8E%F0%9D%9A%8E%F0%9D%9A%97-%F0%9D%9A%8C%F0%9D%9A%98-%F0%9D%9A%9B%F0%9D%9A%98%F0%9D%9A%9E%F0%9D%9A%9D%F0%9D%9A%92%F0%9D%9A%97%F0%9D%9A%8E%F0%9D%9A%9C) |
| [𝙶𝚒𝚜𝚝 𝚎𝚡𝚊𝚖𝚙𝚕𝚎𝚜 𝚘𝚏 𝚌𝚘𝚛𝚘𝚞𝚝𝚒𝚗𝚎𝚜 𝚒𝚗 𝚊𝚌𝚝𝚒𝚘𝚗](https://github.com/devrath/KotlinAlchemy/blob/main/README.md#%F0%9D%99%B6%F0%9D%9A%92%F0%9D%9A%9C%F0%9D%9A%9D-%F0%9D%9A%8E%F0%9D%9A%A1%F0%9D%9A%8A%F0%9D%9A%96%F0%9D%9A%99%F0%9D%9A%95%F0%9D%9A%8E%F0%9D%9A%9C-%F0%9D%9A%98%F0%9D%9A%8F-%F0%9D%9A%8C%F0%9D%9A%98%F0%9D%9A%9B%F0%9D%9A%98%F0%9D%9A%9E%F0%9D%9A%9D%F0%9D%9A%92%F0%9D%9A%97%F0%9D%9A%8E%F0%9D%9A%9C-%F0%9D%9A%92%F0%9D%9A%97-%F0%9D%9A%8A%F0%9D%9A%8C%F0%9D%9A%9D%F0%9D%9A%92%F0%9D%9A%98%F0%9D%9A%97) |
| [𝙳𝚒𝚏𝚏𝚎𝚛𝚎𝚗𝚌𝚎 𝚋𝚎𝚝𝚠𝚎𝚎𝚗 𝙻𝚒𝚟𝚎𝙳𝚊𝚝𝚊, 𝚂𝚝𝚊𝚝𝚎𝙵𝚕𝚘𝚠, 𝙵𝚕𝚘𝚠, 𝚂𝚑𝚊𝚛𝚎𝚍𝙵𝚕𝚘𝚠](https://github.com/devrath/KotlinAlchemy/wiki/Difference-between-LiveData,-StateFlow,-Flow,-SharedFlow) |
| [𝙲𝚑𝚊𝚗𝚗𝚎𝚕𝚜 𝚊𝚗𝚍 𝙵𝚕𝚘𝚠𝚜 - 𝚆𝚑𝚎𝚗 𝚝𝚘 𝚞𝚜𝚎 𝚎𝚊𝚌𝚑 𝚘𝚏 𝚝𝚑𝚎𝚖](https://github.com/devrath/KotlinAlchemy/wiki/Channels-and-Flows-%E2%80%90-When-to-use-each-of-them) |
#### `𝙵𝚞𝚗𝚍𝚊𝚖𝚎𝚗𝚝𝚊𝚕 𝚌𝚘𝚗𝚌𝚎𝚙𝚝𝚜 𝚘𝚏 𝚌𝚘𝚛𝚘𝚞𝚝𝚒𝚗𝚎𝚜`
* [**`𝚆𝚑𝚊𝚝 𝚒𝚜 𝚌𝚘𝚗𝚌𝚞𝚛𝚛𝚎𝚗𝚌𝚢`**](https://github.com/devrath/KotlinAlchemy/wiki/What-is-concurrency)
* [**`𝙱𝚕𝚘𝚌𝚔𝚒𝚗𝚐 𝚟𝚜 𝚂𝚞𝚜𝚙𝚎𝚗𝚍𝚒𝚗𝚐`**](https://github.com/devrath/KotlinAlchemy/wiki/Blocking-function-vs-Suspending-function)
* About asynchronous code, suspending code, co-routines
* [**`𝙷𝚘𝚠 𝚊𝚜𝚢𝚗𝚌𝚑𝚛𝚘𝚗𝚘𝚞𝚜 𝚙𝚛𝚘𝚐𝚛𝚊𝚖𝚖𝚒𝚗𝚐 𝚠𝚘𝚛𝚔𝚜`**](https://github.com/devrath/KotlinAlchemy/wiki/How-asynchronous-programming-works)
* [**`𝙷𝚘𝚠 𝚌𝚘𝚛𝚘𝚞𝚝𝚒𝚗𝚎𝚜 𝚙𝚛𝚘𝚐𝚛𝚊𝚖𝚖𝚒𝚗𝚐 𝚠𝚘𝚛𝚔𝚜`**](https://github.com/devrath/KotlinAlchemy/wiki/How-coroutines-programming-works)
* [**`𝚆𝚑𝚊𝚝 𝚒𝚜 𝚊 𝚌𝚘-𝚛𝚘𝚞𝚝𝚒𝚗𝚎 𝚊𝚗𝚍 𝙷𝚘𝚠 𝚒𝚝 𝚠𝚘𝚛𝚔𝚜`**](https://github.com/devrath/KotlinAlchemy/wiki/What-is-Coroutine-and-How-it-works)
* [**`𝚆𝚑𝚊𝚝 𝚒𝚜 𝚜𝚞𝚜𝚙𝚎𝚗𝚍𝚒𝚗𝚐 𝚏𝚞𝚗𝚌𝚝𝚒𝚘𝚗 𝚊𝚗𝚍 𝚑𝚘𝚠 𝚒𝚝 𝚠𝚘𝚛𝚔𝚜`**](https://github.com/devrath/KotlinAlchemy/wiki/What-is-suspending-function-and-how-it-works)
* [**`𝙲𝚘𝚖𝚙𝚊𝚛𝚒𝚗𝚐 𝚌𝚘𝚛𝚘𝚞𝚝𝚒𝚗𝚎 𝚟𝚜 𝚜𝚞𝚜𝚙𝚎𝚗𝚍 𝚏𝚞𝚗𝚌𝚝𝚒𝚘𝚗`**](https://github.com/devrath/KotlinAlchemy/wiki/Comparing-coroutine-vs-suspend-function)
* Context and Scope
* [**`𝙳𝚒𝚏𝚏𝚎𝚛𝚎𝚗𝚌𝚎 𝚋𝚎𝚝𝚠𝚎𝚎𝚗 𝚕𝚊𝚞𝚗𝚌𝚑 𝚊𝚗𝚍 𝚠𝚒𝚝𝚑𝙲𝚘𝚗𝚝𝚎𝚡𝚝`**](https://github.com/devrath/KotlinAlchemy/wiki/Difference-between-launch--and--withContext)
* [**`𝚁𝚎𝚕𝚊𝚝𝚒𝚘𝚗𝚜𝚑𝚒𝚙 𝚋𝚎𝚝𝚠𝚎𝚎𝚗 𝚜𝚌𝚘𝚙𝚎 𝚊𝚗𝚍 𝚌𝚘𝚗𝚝𝚎𝚡𝚝`**](https://github.com/devrath/KotlinAlchemy/wiki/Coroutines:-Relationship-between-Scope-and-Context)
* [**`𝚄𝚗𝚍𝚎𝚛𝚜𝚝𝚊𝚗𝚍𝚒𝚗𝚐 𝚟𝚒𝚎𝚠-𝚖𝚘𝚍𝚎𝚕 𝚜𝚌𝚘𝚙𝚎`**](https://github.com/devrath/KotlinAlchemy/wiki/Coroutines:-Understanding-ViewModel-Scope)
* [**`𝙷𝚘𝚠 𝚊𝚜𝚢𝚗𝚌/𝚊𝚠𝚊𝚒𝚝 𝚠𝚘𝚛𝚔𝚜`**](https://github.com/devrath/KotlinAlchemy/wiki/How-async-await-works)
* [**`𝚄𝚜𝚒𝚗𝚐 𝚓𝚘𝚒𝚗 𝚒𝚗 𝚌𝚘𝚛𝚘𝚞𝚝𝚒𝚗𝚎𝚜`**](https://github.com/devrath/KotlinAlchemy/wiki/Using-join-in-coroutines)
* Dispatchers
* [**`𝙳𝚒𝚏𝚏𝚎𝚛𝚎𝚗𝚝 𝚝𝚢𝚙𝚎𝚜 𝚘𝚏 𝚍𝚒𝚜𝚙𝚊𝚝𝚌𝚑𝚎𝚛𝚜`**](https://github.com/devrath/KotlinAlchemy/wiki/Coroutines:-Types-of-dispatchers)
* [**`𝚂𝚝𝚛𝚊𝚝𝚎𝚐𝚒𝚎𝚜 𝚏𝚘𝚛 𝚞𝚜𝚒𝚗𝚐 𝚝𝚑𝚎 𝚍𝚒𝚜𝚙𝚊𝚝𝚌𝚑𝚎𝚛𝚜`**](https://github.com/devrath/KotlinAlchemy/wiki/Strategies-for-using-the-dispatchers)
* [**`𝙳𝚒𝚜𝚙𝚊𝚝𝚌𝚑𝚎𝚛𝚜 𝚁𝚞𝚗𝚗𝚒𝚗𝚐 𝚘𝚗 𝚝𝚑𝚛𝚎𝚊𝚍 𝚍𝚎𝚖𝚘`**](https://github.com/devrath/KotlinAlchemy/wiki/Dispatchers-Running-on-thread-demo)
* Using coroutines sample use cases
* [**`𝙲𝚛𝚎𝚊𝚝𝚒𝚗𝚐 𝚊 𝚜𝚒𝚖𝚙𝚕𝚎 𝚌𝚘𝚛𝚘𝚞𝚝𝚒𝚗𝚎 𝚌𝚘𝚗𝚝𝚎𝚡𝚝`**](https://github.com/devrath/KotlinAlchemy/wiki/Coroutines:-Creating-a-simple-coroutine-context)
* [**`𝚆𝚊𝚒𝚝 𝚏𝚘𝚛 𝚌𝚘𝚛𝚘𝚞𝚝𝚒𝚗𝚎 𝚝𝚘 𝚏𝚒𝚗𝚒𝚜𝚑`**](https://github.com/devrath/KotlinAlchemy/wiki/Coroutines:-Wait-for-coroutine-to-finish)
* [**`𝚂𝚎𝚚𝚞𝚎𝚗𝚝𝚒𝚊𝚕 𝚌𝚘𝚛𝚘𝚞𝚝𝚒𝚗𝚎𝚜 𝚎𝚡𝚎𝚌𝚞𝚝𝚒𝚘𝚗`**](https://github.com/devrath/KotlinAlchemy/wiki/Coroutines:-Sequential-coroutines-execution)
* Cancelling the coroutines
* [**`𝙱𝚕𝚘𝚌𝚔 𝙳𝚒𝚊𝚐𝚛𝚊𝚖 𝚘𝚏 𝚌𝚊𝚗𝚌𝚎𝚕𝚕𝚊𝚝𝚒𝚘𝚗`**](https://github.com/devrath/KotlinAlchemy/wiki/Block-Diagram-of-cancellation)
* [**`𝚂𝚒𝚐𝚗𝚒𝚏𝚒𝚌𝚊𝚗𝚌𝚎 𝚘𝚏 𝚎𝚗𝚜𝚞𝚛𝚎 𝚊𝚌𝚝𝚒𝚟𝚎 𝚌𝚘‐𝚘𝚙𝚎𝚛𝚊𝚝𝚒𝚟𝚎 𝚌𝚊𝚗𝚌𝚎𝚕𝚕𝚊𝚝𝚒𝚘𝚗`**](https://github.com/devrath/KotlinAlchemy/wiki/Significance-of-ensureActive-co%E2%80%90operative-cancellation)
* [**`𝚄𝚜𝚒𝚗𝚐 𝙸𝚜𝙰𝚌𝚝𝚒𝚟𝚎 𝚏𝚘𝚛 𝚌𝚘‐𝚘𝚙𝚎𝚛𝚊𝚝𝚒𝚟𝚎 𝚌𝚊𝚗𝚌𝚎𝚕𝚕𝚊𝚝𝚒𝚘𝚗`**](https://github.com/devrath/KotlinAlchemy/wiki/Using-IsActive-for-co%E2%80%90operative-cancellation)
* [**`𝙲𝚊𝚗𝚌𝚎𝚕𝚕𝚒𝚗𝚐 𝙲𝚘𝚛𝚘𝚞𝚝𝚒𝚗𝚎 𝚅𝚜 𝙲𝚊𝚗𝚌𝚎𝚕𝚕𝚒𝚗𝚐 𝙲𝚘𝚛𝚘𝚞𝚝𝚒𝚗𝚎𝚜 𝚌𝚑𝚒𝚕𝚍𝚛𝚎𝚗`**](https://github.com/devrath/KotlinAlchemy/wiki/Cancelling-Coroutine-Vs-Cancelling-Coroutines-children)
* [**`𝙽𝚘𝚗-𝚌𝚊𝚗𝚌𝚎𝚕𝚕𝚊𝚋𝚕𝚎 𝚓𝚘𝚋`**](https://github.com/devrath/KotlinAlchemy/wiki/Non-Cancellable-job)
* Structured Concurrency
* [**`𝚆𝚑𝚊𝚝 𝚒𝚜 𝚂𝚝𝚛𝚞𝚌𝚝𝚞𝚛𝚎𝚍 𝚌𝚘𝚗𝚌𝚞𝚛𝚛𝚎𝚗𝚌𝚢?`**](https://github.com/devrath/KotlinAlchemy/wiki/What-is-Structured-concurrency)
* Jobs
* [**`𝙷𝚘𝚠 𝚓𝚘𝚋 𝚒𝚗 𝚌𝚘𝚛𝚘𝚞𝚝𝚒𝚗𝚎 𝚠𝚘𝚛𝚔𝚜`**](https://github.com/devrath/KotlinAlchemy/wiki/How-Job-in-coroutine-works)
* [**`𝙹𝚘𝚋-𝙷𝚒𝚎𝚛𝚊𝚛𝚌𝚑𝚢`**](https://github.com/devrath/KotlinAlchemy/wiki/Job%E2%80%90Hierarchy)
* Parallel Decomposition
* [**`𝙰𝚋𝚘𝚞𝚝 𝚙𝚊𝚛𝚊𝚕𝚕𝚎𝚕 𝚍𝚎𝚌𝚘𝚖𝚙𝚘𝚜𝚒𝚝𝚒𝚘𝚗`**](https://github.com/devrath/KotlinAlchemy/wiki/About-parallel-decomposition)
* [**`𝙰𝚋𝚘𝚞𝚝 𝙰𝚜𝚢𝚗𝚌 𝚊𝚗𝚍 𝙰𝚠𝚊𝚒𝚝`**](https://github.com/devrath/KotlinAlchemy/wiki/About-Async-and-Await)
* [**`𝙺𝚘𝚝𝚕𝚒𝚗 𝙲𝚘𝚛𝚘𝚞𝚝𝚒𝚗𝚎𝚜 𝚓𝚘𝚒𝚗 𝚟𝚜 𝚊𝚠𝚊𝚒𝚝`**](https://github.com/devrath/KotlinAlchemy/wiki/Kotlin-Coroutines-join-vs-await)
* Exception Handling
* [**`𝙴𝚡𝚌𝚎𝚙𝚝𝚒𝚘𝚗 𝚑𝚊𝚗𝚍𝚕𝚒𝚗𝚐 𝚒𝚗 𝚕𝚊𝚞𝚗𝚌𝚑`**](https://github.com/devrath/KotlinAlchemy/wiki/Exception-handling-in-launch)
* [**`𝙴𝚡𝚌𝚎𝚙𝚝𝚒𝚘𝚗 𝚑𝚊𝚗𝚍𝚕𝚒𝚗𝚐 𝚒𝚗 𝚊𝚜𝚢𝚗𝚌`**](https://github.com/devrath/KotlinAlchemy/wiki/Exception-handling-in-async)
* [**`𝚂𝚞𝚙𝚎𝚛𝚟𝚒𝚜𝚘𝚛 𝚂𝚌𝚘𝚙𝚎 𝚊𝚗𝚍 𝚂𝚞𝚙𝚎𝚛𝚟𝚒𝚜𝚘𝚛 𝙹𝚘𝚋 𝚒𝚗 𝚌𝚘𝚛𝚘𝚞𝚝𝚒𝚗𝚎𝚜`**](https://github.com/devrath/KotlinAlchemy/wiki/Supervisor-Scope-and-Supervisor-Job-in-coroutines)
* [**`𝚆𝚑𝚊𝚝 𝚒𝚜 𝚝𝚊𝚒𝚕𝚛𝚎𝚌 𝚒𝚗 𝚔𝚘𝚝𝚕𝚒𝚗`**](https://github.com/devrath/KotlinAlchemy/wiki/What-is-tailrec-in-kotlin)
#### `𝙲𝚘𝚖𝚖𝚞𝚗𝚒𝚌𝚊𝚝𝚒𝚗𝚐 𝚋𝚎𝚝𝚠𝚎𝚎𝚗 𝚌𝚘-𝚛𝚘𝚞𝚝𝚒𝚗𝚎𝚜`
* [𝙰𝚋𝚘𝚞𝚝 𝙲𝚘𝚖𝚖𝚞𝚗𝚒𝚌𝚊𝚝𝚒𝚗𝚐 𝚋𝚎𝚝𝚠𝚎𝚎𝚗 𝚝𝚑𝚎 𝚌𝚘‐𝚛𝚘𝚞𝚝𝚒𝚗𝚎𝚜](https://github.com/devrath/KotlinAlchemy/wiki/About-Communicating-between-the-co%E2%80%90routines)
* Kotlin flow
* [𝙰𝚋𝚘𝚞𝚝 𝙵𝚕𝚘𝚠](https://github.com/devrath/KotlinAlchemy/wiki/About-Flow)
* [𝙵𝚕𝚘𝚠 𝙱𝚞𝚒𝚕𝚍𝚎𝚛𝚜](https://github.com/devrath/KotlinAlchemy/wiki/KotlinFlow:-Flow-Builders)
* [𝙵𝚕𝚘𝚠 𝙲𝚘𝚗𝚝𝚎𝚡𝚝](https://github.com/devrath/KotlinAlchemy/wiki/Flow-Context)
* Composing and Flattening Flows
* [𝙰𝚋𝚘𝚞𝚝 𝚌𝚘𝚖𝚙𝚘𝚜𝚒𝚗𝚐 𝚊𝚗𝚍 𝚏𝚕𝚊𝚝𝚝𝚎𝚗𝚒𝚗𝚐 𝚏𝚕𝚘𝚠𝚜](https://github.com/devrath/KotlinAlchemy/wiki/About-composing-and-flattening-flows)
* Composing
* [𝙱𝚞𝚏𝚏𝚎𝚛𝚒𝚗𝚐](https://github.com/devrath/KotlinAlchemy/wiki/Flows:-Buffering)
* [𝙲𝚘𝚗𝚏𝚕𝚊𝚝𝚒𝚘𝚗](https://github.com/devrath/KotlinAlchemy/wiki/Flows:-Conflation)
* [𝙲𝚘𝚕𝚕𝚎𝚌𝚝𝚒𝚗𝚐 𝙻𝚊𝚝𝚎𝚜𝚝](https://github.com/devrath/KotlinAlchemy/wiki/Flows:-Collecting-Latest)
* [𝚉𝚒𝚙𝚙𝚒𝚗𝚐](https://github.com/devrath/KotlinAlchemy/wiki/Flows:-Zipping)
* [𝙲𝚘𝚖𝚋𝚒𝚗𝚒𝚗𝚐](https://github.com/devrath/KotlinAlchemy/wiki/Flows:-Combining)
* Flattening
* [𝚆𝚑𝚊𝚝 𝚒𝚜 𝚖𝚎𝚊𝚗𝚝 𝚋𝚢 𝚏𝚕𝚊𝚝𝚝𝚎𝚗𝚒𝚗𝚐](https://github.com/devrath/KotlinAlchemy/wiki/Flows:-What-is-meant-by-flattening)
* [𝙵𝚕𝚊𝚝𝙼𝚊𝚙𝙲𝚘𝚗𝚌𝚊𝚝 𝚘𝚛 𝙵𝚕𝚊𝚝𝚝𝚎𝚗𝙲𝚘𝚗𝚌𝚊𝚝](https://github.com/devrath/KotlinAlchemy/wiki/Flattening-Flow:-FlatMapConcat-or-FlattenConcat)
* [𝙵𝚕𝚊𝚝𝙼𝚊𝚙𝙼𝚎𝚛𝚐𝚎 𝚘𝚛 𝙵𝚕𝚊𝚝𝚝𝚎𝚗𝙼𝚎𝚛𝚐𝚎](https://github.com/devrath/KotlinAlchemy/wiki/Flattening-Flow:-FlatMapMerge-or-FlattenMerge)
* [𝙵𝚕𝚊𝚝𝙼𝚊𝚙𝙻𝚊𝚝𝚎𝚜𝚝 𝚘𝚛 𝙵𝚕𝚊𝚝𝚝𝚎𝚗𝙻𝚊𝚝𝚎𝚜𝚝](https://github.com/devrath/KotlinAlchemy/wiki/Flattening-Flow:-FlatMapLatest-or-FlattenLatest)
* Operators
* [𝚃𝚎𝚛𝚖𝚒𝚗𝚊𝚕 𝚘𝚙𝚎𝚛𝚊𝚝𝚘𝚛𝚜](https://github.com/devrath/KotlinAlchemy/wiki/Flow:-Terminal-operators)
* [𝙸𝚗𝚝𝚎𝚛𝚖𝚎𝚍𝚒𝚊𝚝𝚎 𝚘𝚙𝚎𝚛𝚊𝚝𝚘𝚛𝚜](https://github.com/devrath/KotlinAlchemy/wiki/Flow:-Intermediate-operators)
* [𝙻𝚒𝚏𝚎𝚌𝚢𝚌𝚕𝚎 𝙾𝚙𝚎𝚛𝚊𝚝𝚘𝚛𝚜](https://github.com/devrath/KotlinAlchemy/wiki/Flow:-Lifecycle-operators)
* [𝙴𝚡𝚌𝚎𝚙𝚝𝚒𝚘𝚗 𝙷𝚊𝚗𝚍𝚕𝚒𝚗𝚐](https://github.com/devrath/KotlinAlchemy/wiki/Flows:-Exception-Handeling)
* [𝚂𝚝𝚊𝚝𝚎 𝙵𝚕𝚘𝚠 𝚊𝚗𝚍 𝚂𝚑𝚊𝚛𝚎𝚍 𝙵𝚕𝚘𝚠](https://github.com/devrath/KotlinAlchemy/wiki/State-Flow-and-Shared-Flow)
* Shared Flow
* [𝙲𝚛𝚎𝚊𝚝𝚒𝚗𝚐 𝚊 𝚂𝚑𝚊𝚛𝚎𝚍 𝙵𝚕𝚘𝚠 𝚠𝚒𝚝𝚑 𝚂𝚑𝚊𝚛𝚎𝚍‐𝙸𝚗](https://github.com/devrath/KotlinAlchemy/wiki/Creating-a-Shared-Flow-with-Shared%E2%80%90In)
* [𝚄𝚜𝚒𝚗𝚐 𝙼𝚞𝚝𝚊𝚋𝚕𝚎 𝚂𝚑𝚊𝚛𝚎𝚍 𝙵𝚕𝚘𝚠](https://github.com/devrath/KotlinAlchemy/wiki/Using-Mutable-Shared-Flow)
* State Flow
* [𝙲𝚛𝚎𝚊𝚝𝚒𝚗𝚐 𝚊 𝚂𝚝𝚊𝚝𝚎 𝙵𝚕𝚘𝚠 𝚠𝚒𝚝𝚑 𝚂𝚝𝚊𝚝𝚎‐𝙸𝚗](https://github.com/devrath/KotlinAlchemy/wiki/Creating-a-state-flow-with-state-in)
* [𝚄𝚜𝚒𝚗𝚐 𝙼𝚞𝚝𝚊𝚋𝚕𝚎 𝚂𝚝𝚊𝚝𝚎 𝙵𝚕𝚘𝚠](https://github.com/devrath/KotlinAlchemy/wiki/Using-Mutable-State-Flow)
* Collecting the flows
* [𝙲𝚘𝚗𝚜𝚞𝚖𝚒𝚗𝚐 𝚝𝚑𝚎 𝚏𝚕𝚘𝚠𝚜 𝚜𝚊𝚏𝚎𝚕𝚢 𝚒𝚗 𝙲𝚘𝚖𝚙𝚘𝚜𝚎](https://github.com/devrath/KotlinAlchemy/wiki/Consuming-the-flows-safely-in-Compose)
* [𝙲𝚊𝚕𝚕𝚋𝚊𝚌𝚔 𝙵𝚕𝚘𝚠](https://github.com/devrath/KotlinAlchemy/wiki/CallbackFlow)
* 𝙺𝚘𝚝𝚕𝚒𝚗 𝙲𝚑𝚊𝚗𝚗𝚎𝚕𝚜
* [𝙰𝚋𝚘𝚞𝚝 𝙲𝚑𝚊𝚗𝚗𝚎𝚕𝚜](https://github.com/devrath/KotlinAlchemy/wiki/Channels-%E2%80%90-About)
* [𝙲𝚘𝚖𝚖𝚞𝚗𝚒𝚌𝚊𝚝𝚒𝚘𝚗 𝚋𝚎𝚝𝚠𝚎𝚎𝚗 𝚌𝚘𝚛𝚘𝚞𝚝𝚒𝚗𝚎𝚜](https://github.com/devrath/KotlinAlchemy/wiki/Channels-%E2%80%90-Communication-between-coroutines)
* [𝚄𝚜𝚒𝚗𝚐 𝙿𝚛𝚘𝚍𝚞𝚌𝚎](https://github.com/devrath/KotlinAlchemy/wiki/Channel-%E2%80%90-Using-produce
)
* [𝙴𝚗𝚍-𝚝𝚘-𝚎𝚗𝚍 𝚌𝚘𝚖𝚖𝚞𝚗𝚒𝚌𝚊𝚝𝚒𝚘𝚗 𝚝𝚢𝚙𝚎𝚜](https://github.com/devrath/KotlinAlchemy/wiki/End-to-end-communication-types-in-channels)
* [𝙲𝚑𝚊𝚗𝚗𝚎𝚕 𝚝𝚢𝚙𝚎𝚜](https://github.com/devrath/KotlinAlchemy/wiki/Channel-Types)
#### `𝙶𝚒𝚜𝚝 𝚎𝚡𝚊𝚖𝚙𝚕𝚎𝚜 𝚘𝚏 𝚌𝚘𝚛𝚘𝚞𝚝𝚒𝚗𝚎𝚜 𝚒𝚗 𝚊𝚌𝚝𝚒𝚘𝚗`
* [**`𝚂𝚒𝚗𝚐𝚕𝚎 𝚗𝚎𝚝𝚠𝚘𝚛𝚔 𝚛𝚎𝚚𝚞𝚎𝚜𝚝`**](https://github.com/devrath/KotlinAlchemy/wiki/Single-network-request)
* [**`𝚂𝚎𝚚𝚞𝚎𝚗𝚝𝚒𝚊𝚕 𝚗𝚎𝚝𝚠𝚘𝚛𝚔 𝚛𝚎𝚚𝚞𝚎𝚜𝚝`**](https://github.com/devrath/KotlinAlchemy/wiki/Sequential-network-request)
* [**`𝙲𝚘𝚗𝚌𝚞𝚛𝚛𝚎𝚗𝚝 𝚗𝚎𝚝𝚠𝚘𝚛𝚔 𝚛𝚎𝚚𝚞𝚎𝚜𝚝`**](https://github.com/devrath/KotlinAlchemy/wiki/Concurrent-network-request)
* [**`𝚅𝚊𝚛𝚒𝚊𝚋𝚕𝚎 𝚗𝚞𝚖𝚋𝚎𝚛 𝚘𝚏 𝚗𝚎𝚝𝚠𝚘𝚛𝚔 𝚛𝚎𝚚𝚞𝚎𝚜𝚝𝚜`**](https://github.com/devrath/KotlinAlchemy/wiki/Variable-number-of-network-requests)
* [**`𝙸𝚖𝚙𝚕𝚎𝚖𝚎𝚗𝚝𝚒𝚗𝚐 𝚊 𝚝𝚒𝚖𝚎𝚘𝚞𝚝 𝚏𝚘𝚛 𝚗𝚎𝚝𝚠𝚘𝚛𝚔 𝚛𝚎𝚚𝚞𝚎𝚜𝚝`**](https://github.com/devrath/KotlinAlchemy/wiki/Implementing-a-timeout-for-network-request)
* [**`𝚁𝚎𝚝𝚛𝚢𝚒𝚗𝚐 𝚗𝚎𝚝𝚠𝚘𝚛𝚔 𝚛𝚎𝚚𝚞𝚎𝚜𝚝𝚜 𝚒𝚗 𝚌𝚊𝚜𝚎 𝚘𝚏 𝚏𝚊𝚒𝚕𝚞𝚛𝚎`**](https://github.com/devrath/KotlinAlchemy/wiki/Retrying-network-requests-in-case-of-failure)
* [**`𝙲𝚘𝚖𝚋𝚒𝚗𝚒𝚗𝚐 𝚝𝚒𝚖𝚎𝚘𝚞𝚝 𝚊𝚗𝚍 𝚛𝚎𝚝𝚛𝚢 𝚘𝚏 𝚗𝚎𝚝𝚠𝚘𝚛𝚔 𝚛𝚎𝚚𝚞𝚎𝚜𝚝`**](https://github.com/devrath/KotlinAlchemy/wiki/Combining-timeout-and-retry-of-network-request)
* [**`𝚄𝚜𝚒𝚗𝚐 𝚛𝚘𝚘𝚖 𝚒𝚗 𝚌𝚘𝚛𝚘𝚞𝚝𝚒𝚗𝚎𝚜`**](https://github.com/devrath/KotlinAlchemy/wiki/Using-room-in-coroutines)
* [**`𝙰𝚗𝚊𝚕𝚢𝚣𝚒𝚗𝚐 𝚊𝚗𝚍 𝚍𝚎𝚋𝚞𝚐𝚐𝚒𝚗𝚐 𝚌𝚘𝚛𝚘𝚞𝚝𝚒𝚗𝚎𝚜`**](https://github.com/devrath/KotlinAlchemy/wiki/Analysing-and-debugging-of-coroutines)
* [**`𝙷𝚘𝚠 𝚝𝚘 𝚙𝚎𝚛𝚏𝚘𝚛𝚖 𝚊 𝚑𝚎𝚊𝚟𝚢 𝚘𝚙𝚎𝚛𝚊𝚝𝚒𝚘𝚗 𝚒𝚗 𝚝𝚑𝚎 𝚋𝚊𝚌𝚔𝚐𝚛𝚘𝚞𝚗𝚍 𝚝𝚑𝚛𝚎𝚊𝚍`**](https://github.com/devrath/KotlinAlchemy/wiki/How-to-perform-a-heavy-operation-in-background-thread)
* [**`𝙷𝚘𝚠 𝚝𝚘 𝚙𝚎𝚛𝚏𝚘𝚛𝚖 𝚝𝚑𝚎 𝚌𝚊𝚗𝚌𝚎𝚕𝚕𝚊𝚝𝚒𝚘𝚗`**](https://github.com/devrath/KotlinAlchemy/wiki/How-to-perform-cancellation)
* [**`𝚄𝚜𝚒𝚗𝚐 𝚖𝚊𝚗𝚢 𝚌𝚘𝚛𝚘𝚞𝚝𝚒𝚗𝚎𝚜 𝚝𝚘 𝚙𝚊𝚜𝚜 𝚘𝚗 𝚝𝚑𝚎 𝚠𝚘𝚛𝚔`**](https://github.com/devrath/KotlinAlchemy/wiki/Using-many-coroutines-to-pass-on-the-work)
* [**`𝙷𝚘𝚠 𝚝𝚘 𝚙𝚎𝚛𝚏𝚘𝚛𝚖 𝚎𝚡𝚌𝚎𝚙𝚝𝚒𝚘𝚗 𝚑𝚊𝚗𝚍𝚕𝚒𝚗𝚐 𝚒𝚗 𝚝𝚑𝚎 𝚌𝚘𝚛𝚘𝚞𝚝𝚒𝚗𝚎𝚜`**](https://github.com/devrath/KotlinAlchemy/wiki/How-to-perform-exception-handling-in-the-coroutines)
* [**`𝙷𝚘𝚠 𝚝𝚘 𝚛𝚞𝚗 𝚝𝚑𝚎 𝚌𝚘𝚛𝚘𝚞𝚝𝚒𝚗𝚎 𝚎𝚟𝚎𝚗 𝚒𝚏 𝚝𝚑𝚎 𝚞𝚜𝚎𝚛 𝚕𝚎𝚊𝚟𝚎𝚜 𝚝𝚑𝚎 𝚜𝚌𝚛𝚎𝚎𝚗`**](https://github.com/devrath/KotlinAlchemy/wiki/How-to-run-the-coroutine-even-if-the-user-leaves-the-screen)
* [**`𝚄𝚜𝚒𝚗𝚐 𝚠𝚘𝚛𝚔 𝚖𝚊𝚗𝚊𝚐𝚎𝚛 𝚊𝚕𝚘𝚗𝚐 𝚠𝚒𝚝𝚑 𝚌𝚘𝚛𝚘𝚞𝚝𝚒𝚗𝚎𝚜`**](https://github.com/devrath/KotlinAlchemy/wiki/Using-work-manager-along-with-coroutines)
* [**`𝙼𝚊𝚔𝚒𝚗𝚐 𝚙𝚊𝚛𝚎𝚗𝚝 𝚌𝚘 𝚛𝚘𝚞𝚝𝚒𝚗𝚎 𝚝𝚘 𝚠𝚊𝚒𝚝 𝚞𝚗𝚝𝚒𝚕 𝚊𝚕𝚕 𝚝𝚑𝚎 𝚌𝚑𝚒𝚕𝚍𝚛𝚎𝚗 𝚌𝚘 𝚛𝚘𝚞𝚝𝚒𝚗𝚎𝚜 𝚊𝚛𝚎 𝚏𝚒𝚗𝚒𝚜𝚑𝚎𝚍`**](https://github.com/devrath/KotlinAlchemy/wiki/Making-parent-co-routine-to-wait-until-all-the-children-co-routines-are-finished)
* [**`𝙲𝚊𝚗𝚌𝚎𝚕𝚒𝚗𝚐 𝚝𝚑𝚎 𝚙𝚊𝚛𝚎𝚗𝚝 𝚊𝚗𝚍 𝚌𝚑𝚒𝚕𝚍 𝚓𝚘𝚋`**](https://github.com/devrath/KotlinAlchemy/wiki/Canceling-the-parent-and-child-job)
## **`𝚂𝚞𝚙𝚙𝚘𝚛𝚝`** ☕
𝙸𝚏 𝚢𝚘𝚞 𝚏𝚎𝚎𝚕 𝚕𝚒𝚔𝚎 𝚜𝚞𝚙𝚙𝚘𝚛𝚝 𝚖𝚎 𝚊 𝚌𝚘𝚏𝚏𝚎𝚎 𝚏𝚘𝚛 𝚖𝚢 𝚎𝚏𝚏𝚘𝚛𝚝𝚜, 𝙸 𝚠𝚘𝚞𝚕𝚍 𝚐𝚛𝚎𝚊𝚝𝚕𝚢 𝚊𝚙𝚙𝚛𝚎𝚌𝚒𝚊𝚝𝚎 𝚒𝚝.
## **`𝙲𝚘𝚗𝚝𝚛𝚒𝚋𝚞𝚝𝚎`** 🙋♂️
𝚁𝚎𝚊𝚍 [𝚌𝚘𝚗𝚝𝚛𝚒𝚋𝚞𝚝𝚒𝚘𝚗 𝚐𝚞𝚒𝚍𝚎𝚕𝚒𝚗𝚎𝚜](CONTRIBUTING.md) 𝚏𝚘𝚛 𝚖𝚘𝚛𝚎 𝚒𝚗𝚏𝚘𝚛𝚖𝚊𝚝𝚒𝚘𝚗 𝚛𝚎𝚐𝚊𝚛𝚍𝚒𝚗𝚐 𝚌𝚘𝚗𝚝𝚛𝚒𝚋𝚞𝚝𝚒𝚘𝚗.
## **`𝙵𝚎𝚎𝚍𝚋𝚊𝚌𝚔`** ✍️
𝙵𝚎𝚊𝚝𝚞𝚛𝚎 𝚛𝚎𝚚𝚞𝚎𝚜𝚝𝚜 𝚊𝚛𝚎 𝚊𝚕𝚠𝚊𝚢𝚜 𝚠𝚎𝚕𝚌𝚘𝚖𝚎, [𝙵𝚒𝚕𝚎 𝚊𝚗 𝚒𝚜𝚜𝚞𝚎 𝚑𝚎𝚛𝚎](https://github.com/devrath/KotlinAlchemy/issues/new).
## **`𝙵𝚒𝚗𝚍 𝚝𝚑𝚒𝚜 𝚙𝚛𝚘𝚓𝚎𝚌𝚝 𝚞𝚜𝚎𝚏𝚞𝚕`** ? ❤️
𝚂𝚞𝚙𝚙𝚘𝚛𝚝 𝚒𝚝 𝚋𝚢 𝚌𝚕𝚒𝚌𝚔𝚒𝚗𝚐 𝚝𝚑𝚎 ⭐ 𝚋𝚞𝚝𝚝𝚘𝚗 𝚘𝚗 𝚝𝚑𝚎 𝚞𝚙𝚙𝚎𝚛 𝚛𝚒𝚐𝚑𝚝 𝚘𝚏 𝚝𝚑𝚒𝚜 𝚙𝚊𝚐𝚎. ✌️
## **`𝙻𝚒𝚌𝚎𝚗𝚜𝚎`**  :credit_card:
𝚃𝚑𝚒𝚜 𝚙𝚛𝚘𝚓𝚎𝚌𝚝 𝚒𝚜 𝚕𝚒𝚌𝚎𝚗𝚜𝚎𝚍 𝚞𝚗𝚍𝚎𝚛 𝚝𝚑𝚎 𝙰𝚙𝚊𝚌𝚑𝚎 𝙻𝚒𝚌𝚎𝚗𝚜𝚎 𝟸.𝟶 - 𝚜𝚎𝚎 𝚝𝚑𝚎 [𝙻𝙸𝙲𝙴𝙽𝚂𝙴](https://github.com/devrath/KotlinAlchemy/blob/main/LICENSE) 𝚏𝚒𝚕𝚎 𝚏𝚘𝚛 𝚍𝚎𝚝𝚊𝚒𝚕𝚜.
================================================
FILE: application/.idea/.gitignore
================================================
# Default ignored files
/shelf/
/workspace.xml
================================================
FILE: application/.idea/.name
================================================
My Application
================================================
FILE: application/.idea/compiler.xml
================================================
================================================
FILE: application/.idea/gradle.xml
================================================
================================================
FILE: application/.idea/jarRepositories.xml
================================================
================================================
FILE: application/.idea/misc.xml
================================================
================================================
FILE: application/.idea/modules.xml
================================================
================================================
FILE: application/KotlinConcepts/.gitignore
================================================
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties
================================================
FILE: application/KotlinConcepts/.idea/.gitignore
================================================
# Default ignored files
/shelf/
/workspace.xml
================================================
FILE: application/KotlinConcepts/.idea/.name
================================================
KotlinAlchemy
================================================
FILE: application/KotlinConcepts/.idea/appInsightsSettings.xml
================================================
================================================
FILE: application/KotlinConcepts/.idea/compiler.xml
================================================
================================================
FILE: application/KotlinConcepts/.idea/deploymentTargetDropDown.xml
================================================
================================================
FILE: application/KotlinConcepts/.idea/deploymentTargetSelector.xml
================================================
================================================
FILE: application/KotlinConcepts/.idea/gradle.xml
================================================
================================================
FILE: application/KotlinConcepts/.idea/inspectionProfiles/Project_Default.xml
================================================
================================================
FILE: application/KotlinConcepts/.idea/kotlinc.xml
================================================
================================================
FILE: application/KotlinConcepts/.idea/material_theme_project_new.xml
================================================
================================================
FILE: application/KotlinConcepts/.idea/migrations.xml
================================================
================================================
FILE: application/KotlinConcepts/.idea/misc.xml
================================================
================================================
FILE: application/KotlinConcepts/.idea/other.xml
================================================
================================================
FILE: application/KotlinConcepts/.idea/runConfigurations.xml
================================================
================================================
FILE: application/KotlinConcepts/app/.gitignore
================================================
/build
================================================
FILE: application/KotlinConcepts/app/build.gradle.kts
================================================
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
id("com.google.dagger.hilt.android")
kotlin("kapt")
}
android {
namespace = "com.istudio.app"
compileSdk = 34
defaultConfig {
applicationId = "com.istudio.app"
minSdk = 24
targetSdk = 34
versionCode = 1
versionName = "1.0"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
useSupportLibrary = true
}
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}
buildFeatures {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.5.14"
}
packaging {
resources {
excludes += "/META-INF/{AL2.0,LGPL2.1}"
}
}
// Allow references to generated code
kapt {
correctErrorTypes = true
}
}
dependencies {
implementation("androidx.core:core-ktx:1.13.1")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.6")
implementation("androidx.activity:activity-compose:1.9.3")
implementation(platform("androidx.compose:compose-bom:2024.10.00"))
implementation("androidx.compose.ui:ui")
implementation("androidx.compose.ui:ui-graphics")
implementation("androidx.compose.ui:ui-tooling-preview")
implementation("androidx.compose.material3:material3")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.2.1")
androidTestImplementation("androidx.test.espresso:espresso-core:3.6.1")
androidTestImplementation(platform("androidx.compose:compose-bom:2024.10.00"))
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
debugImplementation("androidx.compose.ui:ui-tooling")
debugImplementation("androidx.compose.ui:ui-test-manifest")
// Hilt
implementation("com.google.dagger:hilt-android:2.51.1")
kapt("com.google.dagger:hilt-android-compiler:2.51.1")
// Hilt-Navigation
implementation("androidx.hilt:hilt-navigation-compose:1.2.0")
// Navigation
implementation ("androidx.navigation:navigation-compose:2.8.3")
// Lifecycle
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.8.6")
implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.8.6")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.6")
implementation("androidx.lifecycle:lifecycle-runtime-compose:2.8.6")
// Retrofit
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.google.code.gson:gson:2.10.1")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
// Joda Time
implementation("joda-time:joda-time:2.10.13")
// Open CSV reader
implementation("com.opencsv:opencsv:5.5.2")
// Desugar jdk
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.2")
}
================================================
FILE: application/KotlinConcepts/app/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
================================================
FILE: application/KotlinConcepts/app/src/androidTest/java/com/istudio/app/ExampleInstrumentedTest.kt
================================================
package com.istudio.app
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.istudio.app", appContext.packageName)
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/AndroidManifest.xml
================================================
================================================
FILE: application/KotlinConcepts/app/src/main/assets/stockdata.csv
================================================
"Rank","Name","Symbol","marketcap","price (USD)","country"
"1","Apple","AAPL","2378193174528","146.94","United States"
"2","Saudi Aramco","2222.SR","2224200000000","10.11","Saudi Arabia"
"3","Microsoft","MSFT","1951727484928","260.96","United States"
"4","Alphabet (Google)","GOOG","1534749310976","2338.99","United States"
"5","Amazon","AMZN","1133733478400","111.43","United States"
"6","Tesla","TSLA","720812179456","695.5","United States"
"7","Berkshire Hathaway","BRK-B","615390314496","278.77","United States"
"8","UnitedHealth","UNH","485138137088","517.11","United States"
"9","Johnson & Johnson","JNJ","467810287616","177.78","United States"
"10","Meta Platforms (Facebook)","META","443647000576","163.93","United States"
"11","Visa","V","438732455936","207.32","United States"
"12","TSMC","TSM","414552883200","79.94","Taiwan"
"13","Tencent","TCEHY","414527651840","43.11","China"
"14","NVIDIA","NVDA","378534789120","151.9","United States"
"15","Kweichow Moutai","600519.SS","363981359625","289.75","China"
"16","Procter & Gamble","PG","351233540096","146.39","United States"
"17","Exxon Mobil","XOM","350748901376","83.25","United States"
"18","Walmart","WMT","347239546880","126.68","United States"
"19","JPMorgan Chase","JPM","333942587392","113.7","United States"
"20","Roche","ROG.SW","329940108327","334.04","Switzerland"
"21","Alibaba","BABA","323570630656","107.45","China"
"22","Nestlé","NESN.SW","321120893727","116.77","Switzerland"
"23","Mastercard","MA","316819668992","325.73","United States"
"24","Eli Lilly","LLY","312279597056","328.66","United States"
"25","LVMH","MC.PA","306576221828","609.15","France"
"26","Home Depot","HD","300447301632","292.34","United States"
"27","Samsung","005930.KS","298950483006","44.43","South Korea"
"28","Pfizer","PFE","293365907456","52.29","United States"
"29","Coca-Cola","KO","274329354240","63.28","United States"
"30","AbbVie","ABBV","271138455552","153.44","United States"
"31","Chevron","CVX","270799929344","137.83","United States"
"32","Bank of America","BAC","252113485824","31.29","United States"
"33","Novo Nordisk","NVO","248601198592","109.17","Denmark"
"34","Pepsico","PEP","237420003328","171.71","United States"
"35","Merck","MRK","236737069056","93.62","United States"
"36","ICBC","1398.HK","235530494429","0.54","China"
"37","Costco","COST","221647618048","500.38","United States"
"38","Prosus","PRX.AS","214848079027","67.54","Netherlands"
"39","Verizon","VZ","213635678208","50.87","United States"
"40","Thermo Fisher Scientific","TMO","213437136896","545.23","United States"
"41","Toyota","TM","212765818880","155.05","Japan"
"42","Astrazeneca","AZN","207878225920","67.08","United Kingdom"
"43","Reliance Industries","RELIANCE.NS","205975990364","30.44","India"
"44","Broadcom","AVGO","197727453184","489.65","United States"
"45","Abbott Laboratories","ABT","192463323136","109.92","United States"
"46","Danaher","DHR","191083102208","262.81","United States"
"47","Oracle","ORCL","189423239168","71.08","United States"
"48","McDonald","MCD","188900343808","255.43","United States"
"49","Novartis","NVS","187214659584","84.23","Switzerland"
"50","ASML","ASML","182929080320","439.8","Netherlands"
"51","CATL","300750.SZ","182810754503","74.9","China"
"52","L'Oréal","OR.PA","181052129239","337.61","France"
"53","Cisco","CSCO","180587266048","43.61","United States"
"54","Adobe","ADBE","179328237568","383.18","United States"
"55","Comcast","CMCSA","178707611648","39.89","United States"
"56","Shell","SHEL","176618078208","47.24","United Kingdom"
"57","Accenture","ACN","174998831104","276.44","Ireland"
"58","Walt Disney","DIS","171856625664","94.35","United States"
"59","T-Mobile US","TMUS","169308520448","135.06","United States"
"60","China Construction Bank","601939.SS","168015942810","0.86","China"
"61","Salesforce","CRM","166821707776","167.66","United States"
"62","Nike","NKE","165167153152","104.95","United States"
"63","Bristol-Myers Squibb","BMY","160829194240","75.54","United States"
"64","Nextera Energy","NEE","158613716992","80.74","United States"
"65","United Parcel Service","UPS","158335139840","181.21","United States"
"66","Agricultural Bank of China","601288.SS","154914093284","0.45","China"
"67","Intel","INTC","152376573952","37.27","United States"
"68","QUALCOMM","QCOM","150750658560","134.6","United States"
"69","Wells Fargo","WFC","150306324480","39.66","United States"
"70","AT&T","T","148364541952","20.72","United States"
"71","CM Bank","3968.HK","145418845079","5.99","China"
"72","Philip Morris","PM","145338318848","93.76","United States"
"73","Texas Instruments","TXN","142718681088","154.77","United States"
"74","Tata Consultancy Services","TCS.NS","141961448754","38.8","India"
"75","Raytheon Technologies","RTX","140765806592","94.65","United States"
"76","Meituan","3690.HK","140235181378","22.68","China"
"77","Linde","LIN","138571120640","275.64","United Kingdom"
"78","Royal Bank Of Canada","RY","138145038336","98.09","Canada"
"79","Bank of China","601988.SS","135173874314","0.5","China"
"80","China Mobile","0941.HK","134848291425","6.31","China"
"81","Amgen","AMGN","133353414656","249.63","United States"
"82","Morgan Stanley","MS","133269602304","76.19","United States"
"83","PetroChina","PTR","131350069248","44.55","China"
"84","Union Pacific Corporation","UNP","129662050304","206.46","United States"
"85","BHP Group","BHP","127157625000","50.25","Australia"
"86","TotalEnergies","TTE","127135703040","48.45","France"
"87","AIA","1299.HK","126843997277","10.61","Hong Kong"
"88","IBM","IBM","126609686528","141.26","United States"
"89","HSBC","HSBC","125697081344","31.17","United Kingdom"
"90","CVS Health","CVS","125439918080","95.66","United States"
"91","Sanofi","SNY","125390430208","50.21","France"
"92","BYD","002594.SZ","124273194295","45.95","China"
"93","Ping An Insurance","601318.SS","123036377112","6.77","China"
"94","AMD","AMD","121959579648","75.26","United States"
"95","S&P Global","SPGI","120256618496","353.8","United States"
"96","American Tower","AMT","119659479040","257.5","United States"
"97","Charles Schwab","SCHW","119471185920","63","United States"
"98","Medtronic","MDT","119132143616","89.66","Ireland"
"99","Honeywell","HON","118369255424","173.89","United States"
"100","Unilever","UL","118089531392","45.94","United Kingdom"
"101","Lowe's Companies","LOW","117864972288","184.42","United States"
"102","Anthem","ANTM","116342792192","482.58","United States"
"103","Toronto Dominion Bank","TD","114630156288","62.36","Canada"
"104","Hermès","RMS.PA","113668592298","1086.98","France"
"105","Intuit","INTU","112438706176","398.61","United States"
"106","Lockheed Martin","LMT","111373762560","418.53","United States"
"107","Wuliangye Yibin","000858.SZ","109674459453","28.25","China"
"108","HDFC Bank","HDB","108887891968","58.81","India"
"109","Commonwealth Bank","CBA.AX","108265977043","63.29","Australia"
"110","GlaxoSmithKline","GSK","107212218368","42.18","United Kingdom"
"111","SAP","SAP","106530742272","87.56","Germany"
"112","ConocoPhillips","COP","106476806144","82.32","United States"
"113","Dior","CDI.PA","106033417653","587.73","France"
"114","American Express","AXP","106015784960","140.78","United States"
"115","Equinor","EQNR","105215623168","32.77","Norway"
"116","China Life Insurance","LFC","103967932416","7.88","China"
"117","Sony","SONY","102031015936","82.53","Japan"
"118","Goldman Sachs","GS","101423333376","295.31","United States"
"119","Nippon Telegraph & Telephone","NPPXF","100178526208","28.15","Japan"
"120","Diageo","DEO","97791942656","171.37","United Kingdom"
"121","Anheuser-Busch Inbev","BUD","96170795008","54.6","Belgium"
"122","Deutsche Telekom","DTE.DE","95439246480","19.2","Germany"
"123","CSL","CSL.AX","95308949865","197.86","Australia"
"124","China Shenhua Energy","601088.SS","93917975546","4.42","China"
"125","Jingdong Mall","JD","93776707584","59.44","China"
"126","Rio Tinto","RIO","93689520128","57.48","United Kingdom"
"127","Caterpillar","CAT","93137764352","174.62","United States"
"128","British American Tobacco","BTI","92813344768","40.61","United Kingdom"
"129","Volkswagen","VOW3.DE","92251598834","129.97","Germany"
"130","BlackRock","BLK","92232753152","608.79","United States"
"131","Starbucks","SBUX","90919804928","79.27","United States"
"132","Deere & Company","DE","90821263360","297.16","United States"
"133","Automatic Data Processing","ADP","90730471424","217.19","United States"
"134","Prologis","PLD","90695835648","122.51","United States"
"135","Citigroup","C","89988571136","46.34","United States"
"136","Cigna","CI","89369452544","281.68","United States"
"137","ServiceNow","NOW","88252514304","440.25","United States"
"138","Estee Lauder","EL","88073527296","246.47","United States"
"139","Mondelez","MDLZ","87463747584","63.2","United States"
"140","BP","BP","87246266368","26.68","United Kingdom"
"141","Al Rajhi Bank","1120.SR","86965784828","21.74","Saudi Arabia"
"142","Keyence","6861.T","86548585173","356.86","Japan"
"143","Boeing","BA","84349542400","142.57","United States"
"144","Enbridge","ENB","84313849856","41.56","Canada"
"145","China Yangtze Power","600900.SS","84210470774","3.7","China"
"146","Zoetis","ZTS","83847266304","178.16","United States"
"147","Duke Energy","DUK","83434070016","108.37","United States"
"148","PayPal","PYPL","83043049472","71.71","United States"
"149","Chubb","CB","82276999168","193.69","Switzerland"
"150","The Saudi National Bank","1180.SR","79657426000","17.96","Saudi Arabia"
"151","Gazprom","GAZP.ME","79519488952","3.36","Russia"
"152","Marsh & McLennan Companies","MMC","78662475776","156.73","United States"
"153","Netflix","NFLX","78436573184","176.55","United States"
"154","Charter Communications","CHTR","78328422400","466.64","United States"
"155","Gilead Sciences","GILD","78325391360","62.45","United States"
"156","Airbus","AIR.PA","78078384459","99.17","Netherlands"
"157","SABIC","2010.SR","78013429632","26","Saudi Arabia"
"158","Applied Materials","AMAT","77725417472","89.35","United States"
"159","Siemens","SIE.DE","77468197840","96.55","Germany"
"160","Analog Devices","ADI","77321142272","148.75","United States"
"161","Canadian National Railway","CNI","77027328000","111.44","Canada"
"162","Altria Group","MO","76668166144","42.35","United States"
"163","Southern Company","SO","76607692800","72.1","United States"
"164","Infosys","INFY","76407988224","18.17","India"
"165","Merck KGaA","MRK.DE","76247297416","176.92","Germany"
"166","CME Group","CME","75446059008","209.91","United States"
"167","Stryker Corporation","SYK","75354742784","199.27","United States"
"168","Crown Castle","CCI","74888552448","172.94","United States"
"169","3M","MMM","74546733056","131","United States"
"170","Intuitive Surgical","ISRG","74311278592","207.02","United States"
"171","Northrop Grumman","NOC","74147258368","477","United States"
"172","Vertex Pharmaceuticals","VRTX","74020904960","289.42","United States"
"173","Inditex","IDEXY","73387630592","11.78","Spain"
"174","Petrobras","PBR","73373630464","11.25","Brazil"
"175","Brookfield Asset Management","BAM","73337307136","44.68","Canada"
"176","Allianz","ALV.DE","73295170799","177.56","Germany"
"177","Fomento Económico Mexicano","FMX","72901607424","60.37","Mexico"
"178","Hindustan Unilever","HINDUNILVR.NS","72388160781","30.81","India"
"179","LG Energy Solution","373220.KS","71759376859","306.66","South Korea"
"180","KDDI","9433.T","71515200856","32.46","Japan"
"181","Pinduoduo","PDD","70906994688","56.08","China"
"182","Booking.com","BKNG","70722723840","1740.94","United States"
"183","Progressive","PGR","69725921280","119.21","United States"
"184","Scotiabank","BNS","69618311168","57.86","Canada"
"185","Blackstone Group","BX","69571920000","96.36","United States"
"186","TJX Companies","TJX","69278605312","59.13","United States"
"187","General Electric","GE","68956348416","62.65","United States"
"188","Becton Dickinson","BDX","68917313536","241.76","United States"
"189","Target","TGT","68803215360","148.38","United States"
"190","Postal Savings Bank of China","601658.SS","68796334378","0.76","China"
"191","U.S. Bancorp","USB","68745191424","46.27","United States"
"192","Sinopec","SNP","68631175168","43.73","China"
"193","Moderna","MRNA","68466429952","172.13","United States"
"194","Mitsubishi UFJ Financial","MUFG","67919392768","5.39","Japan"
"195","Regeneron Pharmaceuticals","REGN","67411390464","613.69","United States"
"196","Air Liquide","AI.PA","67053509309","128.53","France"
"197","LONGi Green Energy Technology","601012.SS","66441263206","8.76","China"
"198","Canadian Pacific Railway","CP","66365038592","71.37","Canada"
"199","ICICI Bank","IBN","66358902784","19.08","India"
"200","Colgate-Palmolive","CL","66247692288","79.06","United States"
"201","Glencore","GLCNF","65910607872","5.03","Switzerland"
"202","PNC Financial Services","PNC","65668390912","158.78","United States"
"203","Bank of Montreal","BMO","65290514432","96.42","Canada"
"204","Sherwin-Williams","SHW","64902684672","249.5","United States"
"205","Dominion Energy","D","64836698112","79.92","United States"
"206","EssilorLuxottica","EL.PA","64815075169","145.8","France"
"207","Micron Technology","MU","64732839936","58.68","United States"
"208","Schneider Electric","SU.PA","64583495690","115.9","France"
"209","Zurich Insurance Group","ZURN.SW","63836780707","430.48","Switzerland"
"210","Waste Management","WM","63725969408","153.48","United States"
"211","Iberdrola","IBE.MC","63707956642","10.2","Spain"
"212","Nongfu Spring","9633.HK","63684359373","5.66","China"
"213","Truist Financial","TFC","63117758464","47.41","United States"
"214","America Movil","AMX","62997082112","19.71","Mexico"
"215","Vale","VALE","62857179136","13.26","Brazil"
"216","Midea","000333.SZ","62540821091","8.94","China"
"217","Humana","HUM","61536317440","486.48","United States"
"218","CSX Corporation","CSX","61488074752","28.28","United States"
"219","Kering","KER.PA","61436474433","497.79","France"
"220","National Australia Bank","NAB.AX","61399004005","19.02","Australia"
"221","General Dynamics","GD","61331398656","220.85","United States"
"222","Activision Blizzard","ATVI","61111824384","78.16","United States"
"223","Airbnb","ABNB","60882583552","95.66","United States"
"224","Edwards Lifesciences","EW","60850868224","97.87","United States"
"225","SoftBank","9984.T","60702771275","38.16","Japan"
"226","Fiserv","FISV","60696395776","93.9","United States"
"227","Industrial Bank","601166.SS","59562283228","2.87","China"
"228","CNOOC","0883.HK","59472837162","1.25","China"
"229","China Tourism Group Duty Free","601888.SS","59098487748","30.27","China"
"230","Bank Central Asia","BBCA.JK","59025566624","0.48","Indonesia"
"231","Aon","AON","58756030464","276.65","United Kingdom"
"232","Equinix","EQIX","58737278976","645.31","United States"
"233","Hong Kong Exchanges & Clearing","0388.HK","58726209021","46.32","Hong Kong"
"234","Compagnie Financière Richemont","CFR.SW","58713235001","103.47","Switzerland"
"235","Foshan Haitian Flavouring and Food","603288.SS","58332025005","12.59","China"
"236","FedEx","FDX","58248957952","224.75","United States"
"237","United Heavy Machinery","OMZZP.ME","58162943422","68.7","Russia"
"238","EOG Resources","EOG","58003161088","99.03","United States"
"239","Dollar General","DG","57786626048","254.57","United States"
"240","Bayer","BAYZF","57762664448","57.68","Germany"
"241","Fidelity National Information Services","FIS","57697112064","94.91","United States"
"242","Illinois Tool Works","ITW","57582698496","184.89","United States"
"243","Walmex","WMMVF","57335689216","3.24","Mexico"
"244","NetEase","NTES","57259651072","87.18","China"
"245","Life Insurance Corporation of India (LIC)","LICI.NS","57114731940","9.03","India"
"246","Mercedes-Benz","MBG.DE","56972073315","53.25","Germany"
"247","Rosneft","ROSN.ME","56669219081","5.97","Russia"
"248","DBS Group","D05.SI","56341976050","21.86","Singapore"
"249","Mindray","300760.SZ","56326308614","46.46","China"
"250","Lam Research","LRCX","56281530368","405.74","United States"
"251","UBS","UBS","56033374208","15.88","Switzerland"
"252","Public Storage","PSA","55115890688","313.13","United States"
"253","Canadian Natural Resources","CNQ","54877323264","47.54","Canada"
"254","Siemens Healthineers","SHL.DE","54502265629","48.55","Germany"
"255","State Bank of India","SBIN.NS","54473674788","6.1","India"
"256","Reckitt Benckiser","RKT.L","54187486436","7574.08","United Kingdom"
"257","Heineken","HEIA.AS","53953714647","93.74","Netherlands"
"258","Intercontinental Exchange","ICE","53800095744","96.37","United States"
"259","Boston Scientific","BSX","53794721792","37.63","United States"
"260","Enterprise Products","EPD","53660876800","24.61","United States"
"261","BNP Paribas","BNP.PA","53500106844","43.38","France"
"262","Investor AB","IVS.F","53287584370","18.05","Sweden"
"263","Enel","ENEL.MI","53178304161","5.22","Italy"
"264","Occidental Petroleum","OXY","53026267136","56.58","United States"
"265","Norfolk Southern","NSC","52740706304","221.29","United States"
"266","Moody's","MCO","52438589440","284.22","United States"
"267","Saudi Telecom Company","7010.SR","52147685099","26.11","Saudi Arabia"
"268","Air Products and Chemicals","APD","52090040320","234.88","United States"
"269","Thomson Reuters","TRI","51974729728","106.52","Canada"
"270","RELX","RELX","51832664064","26.97","United Kingdom"
"271","Monster Beverage","MNST","51748855808","97.7","United States"
"272","Liberty Bancshares","LBSI","51685834752","66.56","United States"
"273","Palo Alto Networks","PANW","51661709312","515","United States"
"274","ABB","ABB","51578695680","26.61","Switzerland"
"275","London Stock Exchange","LS4C.F","51571333599","91.5","United Kingdom"
"276","Keurig Dr Pepper","KDP","51500457984","36.31","United States"
"277","Eaton","ETN","51263516672","128.48","Ireland"
"278","Fast Retailing","9983.T","51152133899","500.78","Japan"
"279","Sberbank","SBER.ME","51004713573","2.26","Russia"
"280","Centene","CNC","50885165056","87","United States"
"281","Housing Development Finance Corporation","HDFC.NS","50820582823","28.01","India"
"282","Nintendo","7974.T","50580466642","434.46","Japan"
"283","MetLife","MET","50561085440","62.18","United States"
"284","Novatek","NVTK.ME","50524683940","16.87","Russia"
"285","Daiichi Sankyō","4568.T","50499079512","26.35","Japan"
"286","Hapag-Lloyd","HLAG.DE","50376528957","283.16","Germany"
"287","Muyuan Foods","002714.SZ","50257023990","9.44","China"
"288","HCA Healthcare","HCA","50209378304","169.92","United States"
"289","Pioneer Natural Resources","PXD","49988730880","206.6","United States"
"290","Recruit","6098.T","49960211199","31.05","Japan"
"291","TC Energy","TRP","49863196672","50.7","Canada"
"292","Fortinet","FTNT","49806376960","62.05","United States"
"293","Baidu","BIDU","49384947712","142.44","China"
"294","Vinci","DG.PA","49287252432","87.13","France"
"295","American Electric Power","AEP","49079398400","95.57","United States"
"296","Atlassian","TEAM","49067483136","193.57","Australia"
"297","SK Hynix","000660.KS","49064590654","71.35","South Korea"
"298","Bharti Airtel","BHARTIARTL.NS","49043471562","8.34","India"
"299","Dassault Systèmes","DSY.PA","49038131612","37.62","France"
"300","China Telecom","0728.HK","48866688441","0.35","China"
"301","AXA","CS.PA","48822738437","21.5","France"
"302","Snowflake","SNOW","48573870080","152.7","United States"
"303","BMW","BMW.DE","48400963700","73.84","Germany"
"304","Synopsys","SNPS","48324751360","315.91","United States"
"305","National Grid","NGG","47789305856","65.47","United Kingdom"
"306","McKesson","MCK","47787528192","330.95","United States"
"307","Kraft Heinz","KHC","47706955776","38.98","United States"
"308","Emerson","EMR","47603929088","80.14","United States"
"309","Shin-Etsu Chemical","4063.T","47578818234","115.33","Japan"
"310","Tokyo Electron","8035.T","47554904096","305.33","Japan"
"311","Vmware","VMW","47538995200","112.8","United States"
"312","Westpac Banking","WBC.AX","47502607558","13.59","Australia"
"313","Bank of Communications","601328.SS","47165156457","0.69","China"
"314","Ørsted","DOGEF","46992867328","111.4","Denmark"
"315","Daikin","6367.T","46857195400","160.09","Japan"
"316","Foxconn (Hon Hai Precision Industry)","2317.TW","46683448783","3.37","Taiwan"
"317","Sempra Energy","SRE","46608285696","148.29","United States"
"318","Newmont","NEM","46349221888","58.4","United States"
"319","Marriott International","MAR","46090104832","140.82","United States"
"320","Constellation Brands","STZ","46058692608","241.75","United States"
"321","Schlumberger","SLB","46008119296","32.55","United States"
"322","Atlas Copco","ATCO-B.ST","46002917355","8.55","Sweden"
"323","Adani Green Energy","ADANIGREEN.NS","45843912306","28.86","India"
"324","Kimberly-Clark","KMB","45700644864","135.64","United States"
"325","General Mills","GIS","45658701824","76.46","United States"
"326","The Hershey Company","HSY","45656645632","222.06","United States"
"327","Samsung Biologics","207940.KS","45610158120","637.8","South Korea"
"328","Hikvision","002415.SZ","45591390965","4.83","China"
"329","Hitachi","6501.T","45513616919","47.35","Japan"
"330","East Money Information","300059.SZ","45472018864","3.44","China"
"331","General Motors","GM","45467922432","31.18","United States"
"332","ITC","ITC.NS","45454863826","3.68","India"
"333","Adyen","ADYEN.AS","45439376539","1467.07","Netherlands"
"334","Pernod Ricard","RI.PA","45369874277","179.49","France"
"335","KLA","KLAC","45263466496","317.22","United States"
"336","L3Harris Technologies","LHX","45221474304","234.46","United States"
"337","Takeda Pharmaceutical","TAK","45028302848","14.5","Japan"
"338","Ford","F","44997832704","11.4","United States"
"339","Bajaj Finance","BAJFINANCE.NS","44725276759","73.87","India"
"340","WuXi AppTec","2359.HK","44569958476","13.67","China"
"341","Anglo American","AAL.L","44560876178","3213.52","United Kingdom"
"342","Sysco","SYY","44492541952","87.33","United States"
"343","Ecolab","ECL","44490768384","155.75","United States"
"344","Chugai Pharmaceutical","4519.T","44476216931","27.05","Japan"
"345","BCE","BCE","44400099328","48.7","Canada"
"346","Oriental Land","4661.T","44200711170","134.95","Japan"
"347","CIBC","CM","44183601152","48.67","Canada"
"348","Marathon Petroleum","MPC","44161421312","81.63","United States"
"349","Deutsche Post","DPW.DE","44030088945","35.98","Germany"
"350","Kuaishou Technology","1024.HK","43991504193","10.25","China"
"351","Cadence Design Systems","CDNS","43989078016","159.52","United States"
"352","Exelon Corporation","EXC","43844792320","44.73","United States"
"353","Macquarie","MQG.AX","43815332592","113.34","Australia"
"354","Nornickel","GMKN.ME","43636719546","283.99","Russia"
"355","O'Reilly Automotive","ORLY","43592699904","663.26","United States"
"356","Maersk","DP4A.F","43546093723","2306.69","Denmark"
"357","Suncor Energy","SU","43243556864","30.59","Canada"
"358","Vodafone","VOD","43209293824","15.32","United Kingdom"
"359","Lukoil","LKOH.ME","43201620616","66.43","Russia"
"360","Wanhua Chemical","600309.SS","43194032529","13.76","China"
"361","ANZ Bank","ANZ.AX","43175575215","15.35","Australia"
"362","Kotak Mahindra Bank","KOTAKBANK.NS","42924670528","21.62","India"
"363","Safran","SAF.PA","42691197361","100","France"
"364","AutoZone","AZO","42428403712","2177.2","United States"
"365","CrowdStrike","CRWD","42415800320","182.77","United States"
"366","Lonza","LONN.SW","42258575330","568.89","Switzerland"
"367","Roper Technologies","ROP","42250285056","398.92","United States"
"368","Paychex","PAYX","42198274048","117.25","United States"
"369","Capital One","COF","42174373888","107.3","United States"
"370","CITIC Securities","600030.SS","42155743279","3.01","China"
"371","Valero Energy","VLO","41993080832","102.9","United States"
"372","Uber","UBER","41992871936","21.39","United States"
"373","Realty Income","O","41883254784","69.62","United States"
"374","Bank Rakyat Indonesia","BYRA.F","41618214226","0.26","Indonesia"
"375","Ping An Bank","000001.SZ","41613961470","2.14","China"
"376","Mitsubishi Corporation","8058.T","41579827574","28.16","Japan"
"377","Nutrien","NTR","41556250624","74.92","Canada"
"378","Republic Services","RSG","41337495552","130.86","United States"
"379","IQVIA","IQV","41335693312","218.39","United States"
"380","Santander","SAN","41277276160","2.46","Spain"
"381","Archer Daniels Midland (ADM)","ADM","41027039232","72.91","United States"
"382","Honda","HMC","40985972736","23.96","Japan"
"383","Alimentation Couche-Tard","ATD.TO","40978640490","40.05","Canada"
"384","Sumitomo Mitsui Financial Group","SMFG","40955514880","5.98","Japan"
"385","American International Group","AIG","40940482560","51.68","United States"
"386","KKR & Co.","KKR","40930082816","48","United States"
"387","Itōchū Shōji","8001.T","40872562434","27.77","Japan"
"388","WuXi Biologics","WXXWY","40697753600","19.31","China"
"389","Shopify","SHOP","40466481152","32.08","Canada"
"390","Tokio Marine","8766.T","40461255380","60.07","Japan"
"391","The Travelers Companies","TRV","40441827328","168.54","United States"
"392","Denso","6902.T","40406937165","52.93","Japan"
"393","NXP Semiconductors","NXPI","40400875520","153.87","Netherlands"
"394","Sea (Garena)","SE","40400195584","71.92","Singapore"
"395","Woodside Energy","WDS","39997214720","20.56","Australia"
"396","EDF (Electricité de France)","EDF.PA","39682723459","10.26","France"
"397","Itaú Unibanco","ITUB","39643025408","4.05","Brazil"
"398","BioNTech","BNTX","39420112896","162.21","Germany"
"399","ENI","E","39257710592","22.18","Italy"
"400","Cintas","CTAS","39170519040","382.81","United States"
"401","Amphenol","APH","39064764416","65.42","United States"
"402","Xiaomi","XIACF","39041183744","1.56","China"
"403","Marvell Technology Group","MRVL","39038627840","45.93","United States"
"404","Ambev","ABEV","39033462784","2.48","Brazil"
"405","YANGHE","002304.SZ","38868666275","25.79","China"
"406","Bank of China (Hong Kong)","2388.HK","38790566845","3.67","Hong Kong"
"407","BASF","BAS.DE","38780223710","42.22","Germany"
"408","Adani Total Gas","ATGL.NS","38706103498","35.19","India"
"409","Autodesk","ADSK","38622769152","177.76","United States"
"410","Stellantis","STLA","38392586240","12.26","Netherlands"
"411","Xcel Energy","XEL","38314487808","70.35","United States"
"412","Freeport-McMoRan","FCX","38229250048","26.37","United States"
"413","Compass Group","CPG.L","38167271842","2153.24","United Kingdom"
"414","Phillips 66","PSX","38122364928","79.24","United States"
"415","Adani Transmission","ADANITRANS.NS","38047871769","34.59","India"
"416","Banco Santander Brasil","BSBR","38042787840","5.1","Brazil"
"417","Corteva","CTVA","37965299712","52.46","United States"
"418","Budweiser APAC","1876.HK","37958801916","2.87","Hong Kong"
"419","Jardine Matheson","J36.SI","37895760000","52.56","Hong Kong"
"420","Block","SQ","37703794688","64.95","United States"
"421","TE Connectivity","TEL","37691576320","113.93","Switzerland"
"422","S.F. Express","002352.SZ","37657626877","7.69","China"
"423","Southern Copper","SCCO","37641748480","48.69","United States"
"424","Welltower","WELL","37636214784","82.91","United States"
"425","Dollar Tree","DLTR","37622112256","167.54","United States"
"426","Williams Companies","WMB","37599969280","30.87","United States"
"427","Kinder Morgan","KMI","37435932672","16.51","United States"
"428","Nidec","6594.T","37264206473","64.62","Japan"
"429","Dow","DOW","37256978432","51.17","United States"
"430","Simon Property Group","SPG","37024165888","98.49","United States"
"431","Verbund AG","OEWA.F","36857014765","105.88","Austria"
"432","Digital Realty","DLR","36771905536","126.38","United States"
"433","OCBC Bank","O39.SI","36731549362","8.17","Singapore"
"434","Agilent Technologies","A","36650807296","122.09","United States"
"435","lululemon athletica","LULU","36449734656","285.56","Canada"
"436","Great Wall Motors","601633.SS","36312608778","5.01","China"
"437","Workday","WDAY","36286439424","142.86","United States"
"438","Prudential Financial","PRU","36279525376","96.75","United States"
"439","Aflac","AFL","36208513024","56.21","United States"
"440","Chipotle Mexican Grill","CMG","36164608000","1293.33","United States"
"441","Motorola Solutions","MSI","35921174528","214.72","United States"
"442","Li Auto","LI","35884945408","37.18","China"
"443","Allstate","ALL","35670794240","129.72","United States"
"444","Ferrari","RACE","35639443456","191.68","Italy"
"445","ING","ING","35577761792","9.23","Netherlands"
"446","7-Eleven","3382.T","35426306526","40.12","Japan"
"447","MSCI","MSCI","35397861376","435.57","United States"
"448","Luxshare Precision","002475.SZ","35192810072","4.97","China"
"449","Arthur J. Gallagher & Co.","AJG","35192692736","167.53","United States"
"450","Sika","SIKA.SW","35188874825","228.94","Switzerland"
"451","Fortescue","FMG.AX","35154218347","11.42","Australia"
"452","Jiangsu Hengrui Medicine","600276.SS","34975643191","5.48","China"
"453","Asian Paints","ASIANPAINT.NS","34902598884","36.39","India"
"454","Alcon","ALC","34899640320","70.44","Switzerland"
"455","SBA Communications","SBAC","34897780736","323.64","United States"
"456","Lloyds Banking Group","LYG","34818658304","1.98","United Kingdom"
"457","China State Construction Engineering","601668.SS","34740253999","0.83","China"
"458","Electronic Arts","EA","34698182656","124.23","United States"
"459","Danone","BN.PA","34626047743","54.16","France"
"460","Yili Group","600887.SS","34625138400","5.41","China"
"461","Cognizant Technology Solutions","CTSH","34590322688","66.37","United States"
"462","Shanghai Pudong Development Bank","600000.SS","34526863637","1.18","China"
"463","Wesfarmers","WES.AX","34331634779","30.27","Australia"
"464","Murata Manufacturing (Murata Seisakusho)","6981.T","34324091587","54.1","Japan"
"465","Kroger","KR","34300368896","47.94","United States"
"466","Sun Hung Kai Properties","0016.HK","34297124771","11.83","Hong Kong"
"467","Bank of New York Mellon","BK","34064840704","42.17","United States"
"468","Zijin Mining","601899.SS","33931947428","1.33","China"
"469","Adani Enterprises","ADANIENT.NS","33919113816","29.75","India"
"470","NIO","NIO","33894887424","20.29","China"
"471","Intesa Sanpaolo","ISP.MI","33770904261","1.7","Italy"
"472","Devon Energy","DVN","33706199040","51.07","United States"
"473","Manulife Financial","MFC","33578180608","17.27","Canada"
"474","China Overseas Land & Investment","0688.HK","33462832246","3.06","Hong Kong"
"475","Yum! Brands","YUM","33406963712","117.15","United States"
"476","Warner Bros. Discovery","WBD","33288810000","13.83","United States"
"477","AIER Eye Hospital","300015.SZ","33285517067","4.73","China"
"478","Brown Forman","BF-A","33279332352","68.31","United States"
"479","Prudential","PUK","33260937216","23.87","United Kingdom"
"480","Mitsui Bussan","8031.T","33228178527","20.91","Japan"
"481","Neste","NESTE.HE","33225672913","43.26","Finland"
"482","Bank of Ningbo","002142.SZ","33172618650","5.02","China"
"483","Naspers","NPSNY","33147598848","30.77","South Africa"
"484","Cenovus Energy","CVE","33133355008","16.72","Canada"
"485","MercadoLibre","MELI","33098346496","657","Argentina"
"486","Consolidated Edison","ED","33087610880","93.39","United States"
"487","Johnson Controls","JCI","33065146368","47.53","Ireland"
"488","Hoya","7741.T","33010072838","91.39","Japan"
"489","Microchip Technology","MCHP","32981719040","59.48","United States"
"490","Nordea Bank","NDA-FI.HE","32963714252","8.8","Finland"
"491","Walgreens Boots Alliance","WBA","32962762752","38.14","United States"
"492","Volvo Group","VOLVF","32942080000","15.29","Sweden"
"493","HP","HPQ","32833945600","31.75","United States"
"494","Banco Bradesco","BBD","32828178432","3.08","Brazil"
"495","MTR Corporation","0066.HK","32782946422","5.29","Hong Kong"
"496","MediaTek","2454.TW","32740699373","20.58","Taiwan"
"497","ResMed","RMD","32598441984","219.11","United States"
"498","Zoom","ZM","32526184448","109.01","United States"
"499","Baxter","BAX","32517902336","64.58","United States"
"500","Chunghwa Telecom","CHT","32468807680","41.86","Taiwan"
"501","Seagen","SGEN","32344913920","175.72","United States"
"502","Anta Sports","AS7.F","32279661659","11.9","China"
"503","Hang Seng Bank","0011.HK","32270898416","16.88","Hong Kong"
"504","Givaudan","GIVN.SW","32193741568","3491.12","Switzerland"
"505","COSCO Shipping","601919.SS","32149213756","2.16","China"
"506","Waste Connections","WCN","32144594944","125","United States"
"507","Parker-Hannifin","PH","32134080512","250.32","United States"
"508","Veeva Systems","VEEV","32056428544","207.02","United States"
"509","Maruti Suzuki India","MARUTI.NS","31989522640","105.9","India"
"510","WEC Energy Group","WEC","31940950016","101.26","United States"
"511","Maaden","1211.SR","31935271806","12.98","Saudi Arabia"
"512","UOB","U11.SI","31910380516","19.06","Singapore"
"513","Datadog","DDOG","31882868736","101.21","United States"
"514","DSV","DSV.VI","31849153319","139.37","Denmark"
"515","Dell","DELL","31847342080","43.07","United States"
"516","Constellation Software","CSU.TO","31846662697","1502.8","Canada"
"517","Biogen","BIIB","31845986304","217.45","United States"
"518","Global Payments","GPN","31816835072","113.01","United States"
"519","Hilton Worldwide","HLT","31750721536","114.08","United States"
"520","Silergy","6415.TW","31651959760","83.27","China"
"521","IDEXX Laboratories","IDXX","31643832320","376.68","United States"
"522","DMart","DMART.NS","31601242379","48.78","India"
"523","HCL Technologies","HCLTECH.NS","31592785377","11.67","India"
"524","Carrier","CARR","31427364864","37.05","United States"
"525","Grupo México","GMBXF","31385446400","3.98","Mexico"
"526","Arista Networks","ANET","31350745088","102.02","United States"
"527","Hyundai","HYMTF","31325120512","34.34","South Korea"
"528","Maybank","MLYBY","31312375808","5.23","Malaysia"
"529","Vanke","2202.HK","31180951322","2.35","China"
"530","PSEG","PEG","31133782016","62.34","United States"
"531","Lucid Motors","LCID","31071858688","18.63","United States"
"532","BAE Systems","BSP.F","31046901575","9.83","United Kingdom"
"533","Munich RE (Münchener Rück)","MUV2.DE","30964065174","221.02","Germany"
"534","Adidas","ADS.DE","30944614838","161.09","Germany"
"535","Cheniere Energy","LNG","30885513216","121.53","United States"
"536","Trane Technologies","TT","30860167168","131.96","Ireland"
"537","Apollo Global Management","APO","30780000256","51.3","United States"
"538","Japan Tobacco","2914.T","30734430180","17.32","Japan"
"539","Singtel","Z74.SI","30655097381","1.88","Singapore"
"540","Loblaw Companies","L.TO","30598907599","91.54","Canada"
"541","CITIC Bank","601998.SS","30596231300","0.71","China"
"542","Woolworths Group","WOW.AX","30576051614","25.12","Australia"
"543","Telus","TU","30549661696","22.12","Canada"
"544","Old Dominion Freight Line","ODFL","30523965440","269.28","United States"
"545","VICI Properties","VICI","30262337536","31.43","United States"
"546","Deutsche Börse","DB1.DE","30206204267","164.5","Germany"
"547","SAIC Motor","600104.SS","30179868895","2.57","China"
"548","CITIC limited","0267.HK","30165897051","1.04","China"
"549","Telstra","TLS.AX","30149384255","2.61","Australia"
"550","Tyson Foods","TSN","29923602432","82.77","United States"
"551","Illumina","ILMN","29889060864","190.26","United States"
"552","AmerisourceBergen","ABC","29886322688","142.68","United States"
"553","International Flavors & Fragrances","IFF","29810950144","116.98","United States"
"554","Barclays","BCS","29784672256","7.2","United Kingdom"
"555","Infineon","IFX.DE","29696706349","22.81","Germany"
"556","Barrick Gold","GOLD","29670825984","16.68","Canada"
"557","Otis Worldwide","OTIS","29582895104","69.97","United States"
"558","Transurban","TCL.AX","29517676004","9.61","Australia"
"559","Japan Post Bank","7182.T","29472872088","7.86","Japan"
"560","TransDigm","TDG","29429962752","538.96","United States"
"561","Fanuc","6954.T","29375321518","153.14","Japan"
"562","Mizuho Financial Group","MFG","29337997312","2.32","Japan"
"563","Fastenal","FAST","29298348032","50.9","United States"
"564","Gree Electric Appliances","000651.SZ","29252012361","5.19","China"
"565","Nucor","NUE","29234892800","109.88","United States"
"566","Larsen & Toubro","LT.NS","29226829370","20.8","India"
"567","MPLX","MPLX","29194733568","28.84","United States"
"568","Eversource Energy","ES","29185095680","84.22","United States"
"569","Energy Transfer Partners","ET","29111977984","9.44","United States"
"570","LG Chem","051910.KS","29035879627","393.08","South Korea"
"571","Royalty Pharma","RPRX","29022887936","43.05","United Kingdom"
"572","Orange","ORAN","29004179456","10.71","France"
"573","Astellas Pharma","4503.T","28922668451","15.83","Japan"
"574","Hexagon","HXGBF","28862496768","10.79","Sweden"
"575","Hess","HES","28729577472","92.3","United States"
"576","LyondellBasell","LYB","28706449408","87.63","United States"
"577","Experian","EXPGF","28630034432","30.85","Ireland"
"578","China Pacific Insurance","601601.SS","28531854609","3.25","China"
"579","M&T Bank","MTB","28490520576","158.8","United States"
"580","People’s Insurance Company of China","1339.HK","28471188635","0.3","China"
"581","Foxconn Industrial Internet","601138.SS","28448347253","1.43","China"
"582","STMicroelectronics","STM","28430168064","31.23","Switzerland"
"583","DNB","DNB.OL","28423626770","18.34","Norway"
"584","Verisk Analytics","VRSK","28386199552","179.77","United States"
"585","Kühne + Nagel","KNIN.SW","28363932345","237.19","Switzerland"
"586","Discover Financial Services","DFS","28328294400","100.83","United States"
"587","Wipro","WIT","28326803456","5.15","India"
"588","Cummins","CMI","28274628608","200.39","United States"
"589","Capgemini","CAP.PA","28252307242","165.71","France"
"590","Dupont De Nemours","DD","28197822464","55.45","United States"
"591","SMC corp","6273.T","28004967723","428.6","Japan"
"592","Cellnex Telecom","CLNX.MC","27956886588","41.23","Spain"
"593","Equity Residential","EQR","27933915136","71.61","United States"
"594","Cerner","CERN","27915780096","94.92","United States"
"595","Paccar","PCAR","27910254592","80.28","United States"
"596","Swisscom","SCMN.SW","27897225615","538.54","Switzerland"
"597","Telefónica","TEF","27778904064","4.81","Spain"
"598","Mettler-Toledo","MTD","27673141248","1220.14","United States"
"599","Airports of Thailand","AOT.BK","27633442380","1.93","Thailand"
"600","American Water Works","AWK","27611004928","151.92","United States"
"601","Corning","GLW","27610363904","32.69","United States"
"602","Baker Hughes","BKR","27569195008","27.15","United States"
"603","Imperial Oil","IMO","27543427072","42.58","Canada"
"604","PPG Industries","PPG","27504791552","116.45","United States"
"605","NatWest Group","NWG","27461072896","5.27","United Kingdom"
"606","Banco Bilbao Vizcaya Argentaria","BBVA","27244232704","4.11","Spain"
"607","First Republic Bank","FRC","27220330496","151.49","United States"
"608","Copart","CPRT","27108980736","114.06","United States"
"609","Naturgy","NTGY.MC","26867509156","27.96","Spain"
"610","AvalonBay Communities","AVB","26862393344","192.12","United States"
"611","Samsung SDI","006405.KS","26815211489","206.1","South Korea"
"612","Naver","035420.KS","26775127887","178.57","South Korea"
"613","Enphase Energy","ENPH","26746345472","198.08","United States"
"614","Cement Roadstone Holding","CRH","26737291264","34.65","Ireland"
"615","Riyad Bank","1010.SR","26697219874","8.9","Saudi Arabia"
"616","Telkom Indonesia","TLK","26648188928","26.65","Indonesia"
"617","Sun Life Financial","SLF","26643374080","45.3","Canada"
"618","PTT PCL","PTT-R.BK","26638697971","0.93","Thailand"
"619","Anhui Conch Cement","AHCHF","26614216704","4.41","China"
"620","Saudi Electricity","5110.SR","26576832484","6.38","Saudi Arabia"
"621","Ross Stores","ROST","26468403200","75.64","United States"
"622","Formosa Petrochemical","6505.TW","26431737677","2.77","Taiwan"
"623","Thales","HO.PA","26430091777","124.13","France"
"624","Ahold Delhaize","AD.AS","26414101108","26.46","Netherlands"
"625","Hormel Foods","HRL","26407268352","48.36","United States"
"626","Rivian","RIVN","26367723520","29.85","United States"
"627","T. Rowe Price","TROW","26282350592","115.63","United States"
"628","D. R. Horton","DHI","26279041024","74.65","United States"
"629","Nasdaq","NDAQ","26251321344","159.41","United States"
"630","Henkel","HEN3.DE","26190993697","60.98","Germany"
"631","Japan Post Holdings","6178.T","26183242730","7.19","Japan"
"632","ENGIE","ENGI.PA","26171415682","10.81","France"
"633","China Securities","601066.SS","26052228978","4.01","China"
"634","SMIC","MKN2.F","26031375316","2.17","China"
"635","Weyerhaeuser","WY","26020204544","34.95","United States"
"636","Ametek","AME","26003929088","112.62","United States"
"637","Axis Bank","AXISBANK.BO","25997195827","8.5","India"
"638","Nokia","NOK","25982339072","4.59","Finland"
"639","CK Hutchison Holdings","0001.HK","25889638320","6.75","Hong Kong"
"640","GoTo","GOTO.JK","25856055572","0.02","Indonesia"
"641","Keysight","KEYS","25805156352","143.41","United States"
"642","Coupang","CPNG","25793163264","14.64","South Korea"
"643","Sartorius","SRT.DE","25773409689","369.53","Germany"
"644","CK Asset Holdings","1113.HK","25761081560","7.08","Hong Kong"
"645","Twitter","TWTR","25730052096","33.67","United States"
"646","Sun Pharmaceutical","SUNPHARMA.NS","25698914226","10.71","India"
"647","Intact Financial","IFC.TO","25692246045","146.04","Canada"
"648","Crédit Agricole","ACA.PA","25636079397","8.48","France"
"649","Ameriprise Financial","AMP","25622743040","233.14","United States"
"650","Fujitsu","6702.T","25605668899","130.3","Japan"
"651","Bridgestone","5108.T","25577604040","36.65","Japan"
"652","Ericsson","ERIC","25555001344","7.27","Sweden"
"653","Halliburton","HAL","25507880960","28.28","United States"
"654","Longfor Group","RLF.F","25398904728","4.06","China"
"655","Holcim","HOLN.SW","25313110640","41.63","Switzerland"
"656","Franco-Nevada","FNV","25291442176","131.29","Canada"
"657","DoorDash","DASH","25244338176","71.87","United States"
"658","CBRE Group","CBRE","25119266816","76.85","United States"
"659","JD Health","6618.HK","25104054724","7.9","China"
"660","Kellogg's","K","24879278080","73.64","United States"
"661","Koninklijke DSM","DSM.AS","24845271328","143.64","Netherlands"
"662","Wolters Kluwer","WOSB.F","24830662468","96.57","Netherlands"
"663","XPeng","XPEV","24785737728","29.01","China"
"664","Galaxy Entertainment","0027.HK","24784435898","5.68","Hong Kong"
"665","Olympus","7733.T","24757929786","19.65","Japan"
"666","RWE","RWE.DE","24750538200","36.6","Germany"
"667","Las Vegas Sands","LVS","24722745344","32.36","United States"
"668","Lindt","LISN.SW","24704239857","101637.61","Switzerland"
"669","Sirius XM","SIRI","24581068800","6.25","United States"
"670","W. W. Grainger","GWW","24539037696","480.2","United States"
"671","eBay","EBAY","24526678016","43.81","United States"
"672","DTE Energy","DTE","24502171648","126.47","United States"
"673","Shenzhen Inovance","300124.SZ","24420329463","9.26","China"
"674","Oneok","OKE","24313774080","54.44","United States"
"675","CoStar Group","CSGP","24169723904","61","United States"
"676","Extra Space Storage","EXR","24167462912","171.65","United States"
"677","UDR Apartments","UDR","24161243136","44.93","United States"
"678","Kia","000270.KS","24130306176","60.19","South Korea"
"679","KONE","KNEBV.HE","24014860356","46.34","Finland"
"680","EDP Renováveis","EDPR.LS","24001878363","24.99","Spain"
"681","SVB Financial Group","SIVB","23977744384","407.43","United States"
"682","Aptiv","APTV","23966556160","88.46","Ireland"
"683","Generali","G.MI","23944707346","15.15","Italy"
"684","Edison International","EIX","23939358720","62.8","United States"
"685","Tesco","TSCDF","23826530304","3.13","United Kingdom"
"686","Sany Heavy Industry","600031.SS","23820871685","2.8","China"
"687","Titan Company","TITAN.NS","23783569719","26.79","India"
"688","Bajaj Finserv","BAJAJFINSV.NS","23772328336","149.23","India"
"689","Partners Group","PGHN.SW","23771629395","901.5","Switzerland"
"690","Assa Abloy","ASAZF","23745069056","21.28","Sweden"
"691","Canon","CAJ","23717197824","22.98","Japan"
"692","Coca-Cola European Partners","CCEP","23624986624","50.75","United Kingdom"
"693","Restaurant Brands International","QSR","23607676928","51.75","Canada"
"694","Alexandria Real Estate Equities","ARE","23528689664","144.16","United States"
"695","Amadeus IT Group","AMS.MC","23523713094","52.29","Spain"
"696","Goodman Group","GMG.AX","23477461827","12.57","Australia"
"697","Ferguson","FERG","23458136064","110.72","United Kingdom"
"698","Coloplast","CBHD.F","23457927916","110.21","Denmark"
"699","Rockwell Automation","ROK","23446556672","201.67","United States"
"700","Vestas Wind Systems","VWSB.F","23412830729","23.2","Denmark"
"701","Kakao","035720.KS","23402079836","53.76","South Korea"
"702","West Pharmaceutical","WST","23391221760","315.78","United States"
"703","Equifax","EFX","23363536896","190.98","United States"
"704","Terumo","4543.T","23332181238","30.85","Japan"
"705","Church & Dwight","CHD","23298734080","95.97","United States"
"706","Snap","SNAP","23217743872","14.15","United States"
"707","ON Semiconductor","ON","23211309056","53.42","United States"
"708","Bank Mandiri","PPERF","23191015424","0.5","Indonesia"
"709","Fifth Third Bank","FITB","23182878720","33.79","United States"
"710","Z Holdings","4689.T","23163886115","3.09","Japan"
"711","State Street Corporation","STT","23124574208","62.99","United States"
"712","Rogers Communication","RCI","23093321728","45.66","Canada"
"713","Zscaler","ZS","23051321344","162.49","United States"
"714","Sociedad Química y Minera","SQM","23026708480","80.62","Chile"
"715","BT Group","BT-A.L","23007427089","230.78","United Kingdom"
"716","Albemarle","ALB","22982256640","196.24","United States"
"717","China Railway Group","0390.HK","22880204154","0.66","China"
"718","Roblox","RBLX","22859640832","38.54","United States"
"719","Ameren","AEE","22811772928","88.34","United States"
"720","Tractor Supply","TSCO","22786447360","203.67","United States"
"721","Entergy","ETR","22775853056","111.99","United States"
"722","SSE","SCT.F","22759997522","21.32","United Kingdom"
"723","Southwest Airlines","LUV","22757652480","38.38","United States"
"724","The Saudi British Bank","1060.SR","22747661805","11.07","Saudi Arabia"
"725","ČEZ Group","CEZ.F","22710548979","42.31","Czech Republic"
"726","Interactive Brokers","IBKR","22703095808","54.47","United States"
"727","Vonovia","VNA.DE","22702915057","28.14","Germany"
"728","GlobalFoundries","GFS","22693701632","42.05","United States"
"729","Great-West Lifeco","GWO.TO","22690573390","24.29","Canada"
"730","Continental Resources","CLR","22652895232","62.41","United States"
"731","China Tower","0788.HK","22646308620","0.13","China"
"732","LabCorp","LH","22597478400","243.77","United States"
"733","Lennar","LEN","22571474944","79.3","United States"
"734","National Bank of Canada","NA.TO","22542125874","67.01","Canada"
"735","Sampo","SAMPO.HE","22517163825","42.45","Finland"
"736","Brookfield Renewable Partners","BEP","22513283072","34.53","Bermuda"
"737","China Minsheng Bank","600016.SS","22473901979","0.55","China"
"738","KBC","KBCSF","22430013440","53.79","Belgium"
"739","China Everbright Bank","601818.SS","22394563412","0.44","China"
"740","Duke Realty","DRE","22389692416","57.62","United States"
"741","Mitsubishi Electric","6503.T","22355433967","10.59","Japan"
"742","Willis Towers Watson","WTW","22321012736","200.21","United Kingdom"
"743","Beiersdorf","BEI.DE","22250841452","98.1","Germany"
"744","McCormick & Company","MKC","22244671488","82.91","United States"
"745","Compagnie de Saint-Gobain","SGO.PA","22184780324","41.54","France"
"746","Fortis","FTS","22180380672","46.49","Canada"
"747","EnBW Energie","EBK.DE","22060588533","81.45","Germany"
"748","The Trade Desk","TTD","22006251520","45.25","United States"
"749","Nestlé India","NESTLEIND.NS","21979536178","227.97","India"
"750","BOE Technology","000725.SZ","21885115912","0.57","China"
"751","Invitation Homes","INVH","21863745536","35.68","United States"
"752","Ball Corporation","BALL","21851183104","68.33","United States"
"753","CaixaBank","CABK.MC","21822400676","2.71","Spain"
"754","Fujifilm","4901.T","21804731399","54.4","Japan"
"755","Genmab","GMAB","21745997824","33.25","Denmark"
"756","China Resources Beer","0291.HK","21716867019","6.69","Hong Kong"
"757","Geely","0175.HK","21701759883","2.17","China"
"758","Zimmer Biomet","ZBH","21699602432","103.54","United States"
"759","Central Japan Railway","9022.T","21666951653","110.1","Japan"
"760","CDW Corporation","CDW","21655042048","160.27","United States"
"761","The Hartford","HIG","21517635584","65.43","United States"
"762","BTG Pactual","BPAC3.SA","21487048166","2.19","Brazil"
"763","Unicharm","8113.T","21454739104","35.94","Japan"
"764","FirstEnergy","FE","21444204544","37.56","United States"
"765","Swiss Re","SREN.SW","21423107838","74.14","Switzerland"
"766","Volvo Car","VOLCAR-B.ST","21364076742","6.94","Sweden"
"767","Polestar","PSNY","21343750310","10.04","Sweden"
"768","CLP Group","0002.HK","21338696040","8.45","Hong Kong"
"769","Ansys","ANSS","21332580352","245.23","United States"
"770","ZTO Express","ZTO","21295976448","26.3","China"
"771","Steris","STE","21149906944","211.33","Ireland"
"772","Chongqing Changan","000625.SZ","21146246120","2.46","China"
"773","E.ON","EOAN.DE","21136869486","8.11","Germany"
"774","Waters Corporation","WAT","21025130496","349.05","United States"
"775","UltraTech Cement","ULTRACEMCO.NS","20960215181","72.68","India"
"776","Coterra Energy","CTRA","20942872576","25.99","United States"
"777","Aker BP","AKRBP.OL","20913513005","33.11","Norway"
"778","H&M","HM-B.ST","20883314697","12.62","Sweden"
"779","Standard Chartered","STAN.L","20864153669","682.29","United Kingdom"
"780","Skandinaviska Enskilda Banken","SEBA.F","20819181337","9.79","Sweden"
"781","Tata Motors","TTM","20750245888","27.1","India"
"782","EQT","EQT.ST","20747167276","20.84","Sweden"
"783","MongoDB","MDB","20713164800","304.09","United States"
"784","FirstRand","FSRA.F","20701610281","3.62","South Africa"
"785","Daimler Truck","DTG.F","20642371700","24.08","Germany"
"786","Ventas","VTR","20484419584","51.25","United States"
"787","WEG ON","WEGE3.SA","20470792735","4.88","Brazil"
"788","CRRC","1766.HK","20397071466","0.37","China"
"789","Pacific Gas and Electric","PCG","20312047616","10.22","United States"
"790","Ecopetrol","EC","20311601152","9.88","Colombia"
"791","Match Group","MTCH","20311373824","71.12","United States"
"792","Sandvik","SAND.ST","20276365497","16.16","Sweden"
"793","Agnico Eagle Mines","AEM","20240758784","44.18","Canada"
"794","Sonova","SOON.SW","20237726055","331.29","Switzerland"
"795","PPL","PPL","20215255040","27.47","United States"
"796","Mid-America Apartment Communities","MAA","20171931648","170.04","United States"
"797","Porsche SE","PAH3.DE","20164152889","65.84","Germany"
"798","Imperial Brands","ITBA.F","20135464414","20.92","United Kingdom"
"799","Delta Electronics","2308.TW","20107628977","7.74","Taiwan"
"800","Fortive","FTV","20083841024","56.03","United States"
"801","Kaō","4452.T","20070685821","42.41","Japan"
"802","Ashtead","0LC.F","20054034534","44.85","United Kingdom"
"803","ULTA Beauty","ULTA","20029769728","386.54","United States"
"804","Sun Communities","SUI","19984195584","160.95","United States"
"805","Komatsu","6301.T","19932904156","21.09","Japan"
"806","Northern Trust","NTRS","19923212288","95.61","United States"
"807","Hong Kong and China Gas","0003.HK","19896578186","1.07","Hong Kong"
"808","Take 2 Interactive","TTWO","19878430720","122.72","United States"
"809","Gartner","IT","19850043392","246.47","United States"
"810","Garmin","GRMN","19828142080","102.67","Switzerland"
"811","Celltrion","068270.KS","19824424666","143.39","South Korea"
"812","ORIX","IX","19809046528","83.16","Japan"
"813","Vulcan Materials","VMC","19801503744","149","United States"
"814","CGI","GIB","19801077760","80.86","Canada"
"815","Constellation Energy","CEG","19765288960","60.5","United States"
"816","Align Technology","ALGN","19754176512","250.67","United States"
"817","Cheniere Energy","CQP","19748300800","40.8","United States"
"818","Martin Marietta","MLM","19711240192","316.06","United States"
"819","Mitsui Fudosan","8801.T","19710824291","20.87","Japan"
"820","Otsuka Holdings","4578.T","19637872929","36.21","Japan"
"821","Oil & Natural Gas","ONGC.NS","19635950838","1.56","India"
"822","ArcelorMittal","MT","19621896192","21.82","Luxembourg"
"823","Schindler Group","SCHN.SW","19616270099","181.07","Switzerland"
"824","Raymond James","RJF","19607640064","90.5","United States"
"825","Delta Air Lines","DAL","19574706176","30.54","United States"
"826","Genuine Parts Company","GPC","19562766336","138.16","United States"
"827","Techtronic Industries","TIB1.F","19545939017","10.65","Hong Kong"
"828","Legrand","LR.PA","19523276131","73.32","France"
"829","Palantir","PLTR","19483332608","9.52","United States"
"830","Adani Ports & SEZ","ADANIPORTS.NS","19453325749","9.21","India"
"831","VeriSign","VRSN","19405895680","177.15","United States"
"832","NTT Data","9613.T","19393753755","13.83","Japan"
"833","Yum China","YUMC","19373137920","45.97","China"
"834","Cathay Financial Holding","2882.TW","19329478745","1.47","Taiwan"
"835","CMS Energy","CMS","19322591232","66.6","United States"
"836","M3, Inc","2413.T","19301553259","28.43","Japan"
"837","Spotify","SPOT","19250487296","99.92","Sweden"
"838","Catalent","CTLT","19249268736","107.41","United States"
"839","Pembina Pipeline","PBA","19238918144","34.71","Canada"
"840","Endesa","ELE.MC","19234511220","18.17","Spain"
"841","KE Holdings","BEKE","19225354240","15.21","China"
"842","Polyus","PLZL.ME","19206824475","142.27","Russia"
"843","Philips","PHG","19200432128","20.82","Netherlands"
"844","Diamondback Energy","FANG","19155331072","109.09","United States"
"845","Fubon Financial","2881.TW","19135916837","1.87","Taiwan"
"846","Argenx","ARGX","19129954304","352.7","Netherlands"
"847","Paycom","PAYC","19109857280","317.16","United States"
"848","Horizon Therapeutics","HZNP","19020601344","82.74","Ireland"
"849","Panasonic","6752.T","19015356946","8.15","Japan"
"850","Live Nation","LYV","18992029696","83.28","United States"
"851","Huatai Securities","206G.F","18983843845","20.92","China"
"852","Mengniu Dairy","2319.HK","18967403746","4.8","China"
"853","Straumann","STMN.SW","18956581000","119.31","Switzerland"
"854","Chow Tai Fook","1929.HK","18955993037","1.9","Hong Kong"
"855","Ferrovial","FER.MC","18939261490","25.19","Spain"
"856","Amcor","AMCR","18927388672","12.6","Switzerland"
"857","Mitsubishi Estate","8802.T","18884756047","14.28","Japan"
"858","Cincinnati Financial","CINF","18878595072","117.73","United States"
"859","Liberty Broadband","LBRDA","18799249408","113.93","United States"
"860","CenterPoint Energy","CNP","18738698240","29.77","United States"
"861","Powergrid Corporation of India","POWERGRID.NS","18730926309","2.69","India"
"862","Teleperformance","TEP.PA","18702646958","313.62","France"
"863","Quanta Services","PWR","18687916032","130.04","United States"
"864","Evolution Gaming","EVO.ST","18663730583","86.32","Sweden"
"865","Air China","601111.SS","18654770747","1.49","China"
"866","EDP Group","EDP.F","18588014560","4.71","Portugal"
"867","Centrais Electricas Brasileiras","EBR","18524712960","7.73","Brazil"
"868","UniCredit","UCG.MI","18522628891","8.97","Italy"
"869","Michelin","ML.PA","18494210188","25.93","France"
"870","Kyocera","6971.T","18466953297","51.45","Japan"
"871","Atlantia","ATL.MI","18443093591","22.52","Italy"
"872","Nu Holdings","NU","18439960576","4","Brazil"
"873","East Japan Railway","9020.T","18416384740","48.82","Japan"
"874","EPAM Systems","EPAM","18415513600","322.23","United States"
"875","Nippon Paint","4612.T","18375762176","7.83","Japan"
"876","Carlsberg","CBGA.F","18350518637","139.27","Denmark"
"877","Rollins","ROL","18255527936","37.07","United States"
"878","Wilmar International","F34.SI","18242552352","2.91","Singapore"
"879","Avantor","AVTR","18224723968","29.86","United States"
"880","Formosa Plastics","1301.TW","18217693590","2.86","Taiwan"
"881","Kubota","6326.T","18206599682","15.23","Japan"
"882","Nexon","3659.T","18205920368","21.04","Japan"
"883","Telenor","TEL.OL","18205067649","13.01","Norway"
"884","China Communications Construction","601800.SS","18182136995","1.35","China"
"885","Monolithic Power Systems","MPWR","18156720128","389.27","United States"
"886","Toyota Industries","6201.T","18114193856","58.34","Japan"
"887","PerkinElmer","PKI","18108545024","143.55","United States"
"888","United Rentals","URI","18093363200","252.66","United States"
"889","American Campus Communities","ACC","17999226880","64.96","United States"
"890","Citizens Financial Group","CFG","17979736064","36.29","United States"
"891","Hologic","HOLX","17965406208","72.04","United States"
"892","Teledyne","TDY","17960036352","383.41","United States"
"893","NTPC Limited","NTPC.NS","17940082850","1.85","India"
"894","Mahindra & Mahindra","M&M.NS","17920560235","14.41","India"
"895","Fox Corporation","FOX","17914306560","30.69","United States"
"896","Ares Management","ARES","17878687744","60.91","United States"
"897","CF Industries","CF","17877190656","85.7","United States"
"898","Dai-ichi Life Holdings","8750.T","17867513716","17.37","Japan"
"899","Markel","MKL","17826592768","1313.88","United States"
"900","Essex Property Trust","ESS","17822771200","263.59","United States"
"901","Incyte","INCY","17784635392","80.29","United States"
"902","Huntington Bancshares","HBAN","17744965632","12.33","United States"
"903","Alinma Bank","1150.SR","17744857039","8.87","Saudi Arabia"
"904","Regions Financial","RF","17736808448","18.98","United States"
"905","W. R. Berkley","WRB","17730803712","66.86","United States"
"906","Orient Overseas Container Line","0316.HK","17716729106","26.83","Hong Kong"
"907","BeiGene","BGNE","17694849024","171.14","China"
"908","Epiroc","EPI-A.ST","17679608871","15.46","Sweden"
"909","Aena","AENA.MC","17667000510","117.78","Spain"
"910","Dover","DOV","17658525696","122.49","United States"
"911","Chewy","CHWY","17648668672","41.96","United States"
"912","Avangrid","AGR","17606201344","45.53","United States"
"913","VF Corporation","VFC","17598144512","45.3","United States"
"914","Alnylam Pharmaceuticals","ALNY","17589309440","145.59","United States"
"915","Power Corporation of Canada","POW.TO","17587120168","25.91","Canada"
"916","Essity","ESWB.F","17577744329","25.2","Sweden"
"917","PhosAgro","PHOR.ME","17576778390","135.73","Russia"
"918","Henderson Land Development","0012.HK","17575829085","3.63","Hong Kong"
"919","Clorox","CLX","17567823872","142.74","United States"
"920","PTT Exploration and Production","PTTEP.BK","17545462847","4.42","Thailand"
"921","Brookfield Infrastructure Partners","BIP","17520183296","38.25","Bermuda"
"922","Broadridge Financial Solutions","BR","17503162368","149.31","United States"
"923","Dollarama","DOL.TO","17475489586","59.41","Canada"
"924","Rocket Companies","RKT","17458429952","8.79","United States"
"925","JSW Steel","JSWSTEEL.NS","17401834953","7.22","India"
"926","George Weston","WN.TO","17346409303","118.73","Canada"
"927","MS&AD Insurance","8725.T","17321001855","31.64","Japan"
"928","Repsol","REP.MC","17305690510","12.37","Spain"
"929","Hewlett Packard Enterprise","HPE","17294084096","13.31","United States"
"930","Conagra Brands","CAG","17286674432","35.77","United States"
"931","J. B. Hunt","JBHT","17281859584","164.93","United States"
"932","Renesas Electronics","6723.T","17238178383","8.83","Japan"
"933","Legal & General","LGEN.L","17236211332","288.69","United Kingdom"
"934","ICON plc","ICLR","17197533184","211","Ireland"
"935","Banco do Brasil","BZLA.F","17196063061","6.03","Brazil"
"936","Link REIT","0823.HK","17177434006","8.14","Hong Kong"
"937","Ingersoll Rand","IR","17093711872","42.11","Ireland"
"938","Copel","ELP","17076070400","6.24","Brazil"
"939","Toshiba","6502.T","17002873627","39.3","Japan"
"940","SGS","SGSN.SW","16960433109","2263.91","Switzerland"
"941","Cloudflare","NET","16931700736","51.9","United States"
"942","Magna International","MGA","16925381632","55.78","Canada"
"943","Brown & Brown","BRO","16913797120","59.92","United States"
"944","Sumitomo","8053.T","16880528264","13.5","Japan"
"945","Saudi Arabian Fertilizer Company","2020.SR","16868979627","35.44","Saudi Arabia"
"946","Molina Healthcare","MOH","16852183040","287.09","United States"
"947","Geberit","GEBN.SW","16845247416","479.1","Switzerland"
"948","Svenska Handelsbanken","SVHH.F","16842764548","8.46","Sweden"
"949","Coles Group","COL.AX","16839072753","12.58","Australia"
"950","Tourmaline Oil","TOU.TO","16822056242","50.14","Canada"
"951","Fleetcor","FLT","16809248768","217.34","United States"
"952","Principal","PFG","16765583360","66.35","United States"
"953","Arch Capital","ACGL","16754078720","44.6","Bermuda"
"954","Freddie Mac","FMCCT","16750811136","5.2","United States"
"955","Nomura Research Institute","4307.T","16682763555","28.3","Japan"
"956","Advanced Info Service (AIS)","ADVANC.BK","16666609286","5.6","Thailand"
"957","Société Générale","GLE.PA","16662235693","20.05","France"
"958","Tradeweb","TW","16613964800","71.36","United States"
"959","China Merchants Securities","600999.SS","16534660315","2.06","China"
"960","Novozymes","NZYM.VI","16504899060","58.9","Denmark"
"961","Astra International","ASII.JK","16479809757","0.41","Indonesia"
"962","United Microelectronics","UMC","16475988992","6.6","Taiwan"
"963","Snam","SRG.MI","16453529353","5.03","Italy"
"964","Zhongsheng Group","0881.HK","16423793799","6.81","China"
"965","Hannover Rück","HNR1.DE","16407054399","136.05","Germany"
"966","NIBE Industrier","NIBE-B.ST","16397239893","7.95","Sweden"
"967","Stanley Black & Decker","SWK","16393892864","108.59","United States"
"968","BioMarin Pharmaceutical","BMRN","16348009472","88.37","United States"
"969","Shiseido","4911.T","16342537951","40.91","Japan"
"970","Aeon","8267.T","16334468739","19.29","Japan"
"971","UCB","UCB.VI","16291460474","86.12","Belgium"
"972","Sunny Optical","2382.HK","16279603370","14.17","China"
"973","Jacobs Engineering","J","16275174400","126.53","United States"
"974","Seagate Technology","STX","16242205696","75.6","Ireland"
"975","KeyCorp (KeyBank)","KEY","16234319872","17.41","United States"
"976","Tsingtao","600600.SS","16228974486","14.23","China"
"977","The Mosaic Company","MOS","16217285632","44.8","United States"
"978","Flutter Entertainment","PPBA.F","16179559984","43.99","Ireland"
"979","Check Point Software","CHKP","16179517440","126.29","Israel"
"980","Deutsche Bank","DB","16162776064","7.8","Germany"
"981","Best Buy","BBY","16119776256","71.59","United States"
"982","Aristocrat","ALL.AX","16117585561","24.18","Australia"
"983","Veolia","VIE.PA","16114174713","23.42","France"
"984","Nan Ya Plastics","1303.TW","16102917739","2.03","Taiwan"
"985","Hydro One","H.TO","16099800949","26.89","Canada"
"986","Insulet","PODD","16096494592","232.14","United States"
"987","Quest Diagnostics","DGX","16087221248","137.07","United States"
"988","Expeditors","EXPD","16076704768","95.84","United States"
"989","HEICO","HEI","16068281344","133.87","United States"
"990","Trip.com","TCOM","16058397696","24.46","China"
"991","Bandai Namco","7832.T","16051378774","72.97","Japan"
"992","TransUnion","TRU","16023071744","83.28","United States"
"993","Bayan Resources","BYAN.JK","16015999506","4.8","Indonesia"
"994","W. P. Carey","WPC","15948861440","82.69","United States"
"995","Shionogi","4507.T","15859047659","52.6","Japan"
"996","ZTE","000063.SZ","15847459024","3.57","China"
"997","Huaneng Power","HNP","15840093184","21.51","China"
"998","International Paper","IP","15833271296","42.72","United States"
"999","Santos","STO.AX","15809833170","4.71","Australia"
"1000","Surgutneftegas","SNGS.ME","15773744352","0.44","Russia"
"1001","Okta","OKTA","15769223168","99.95","United States"
"1002","UPM-Kymmene","UPM.HE","15685999590","29.41","Finland"
"1003","Twilio","TWLO","15644379136","86.11","United States"
"1004","Wheaton Precious Metals","WPM","15619410944","34.22","Canada"
"1005","CK Infrastructure","1038.HK","15615641002","6.2","Hong Kong"
"1006","Atmos Energy","ATO","15611385856","112.3","United States"
"1007","Icahn Enterprises","IEP","15578626048","50.75","United States"
"1008","CP All","CPALL.BK","15576524330","1.73","Thailand"
"1009","Tatneft","TATN.ME","15567219405","6.96","Russia"
"1010","Fairfax Financial","FFH.TO","15559306954","530.34","Canada"
"1011","Zebra Technologies","ZBRA","15555111936","296.21","United States"
"1012","Skyworks Solutions","SWKS","15555107840","96.66","United States"
"1013","Telia Company","TELIA.ST","15541533516","3.81","Sweden"
"1014","Splunk","SPLK","15507542016","96.38","United States"
"1015","Fresenius","FRE.DE","15477714180","27.66","Germany"
"1016","Banque Saudi Fransi","1050.SR","15437674705","12.87","Saudi Arabia"
"1017","Daiwa House","1925.T","15421327016","23.52","Japan"
"1018","FactSet","FDS","15408513024","405.71","United States"
"1019","Banorte","GFNORTEO.MX","15388265745","5.34","Mexico"
"1020","MTN Group","MTN.JO","15381611979","8.29","South Africa"
"1021","Evergreen Marine","2603.TW","15266223685","2.89","Taiwan"
"1022","Swedish Match","SWMA.ST","15247164069","10.02","Sweden"
"1023","MFHC","2886.TW","15244573811","1.12","Taiwan"
"1024","Ryanair","RYAAY","15236452352","67.11","Ireland"
"1025","Weichai Power","2338.HK","15208417276","1.54","China"
"1026","Paramount Global","PARA","15201156096","24.58","United States"
"1027","China Railway Construction","601186.SS","15199983421","1.2","China"
"1028","Sompo Holdings","8630.T","15189017150","44.41","Japan"
"1029","Synchrony","SYF","15185087488","30.28","United States"
"1030","Ubiquiti","UI","15183143936","251.3","United States"
"1031","POOLCORP","POOL","15178914816","379.24","United States"
"1032","Bio-Rad Laboratories","BIO","15154044928","513.74","United States"
"1033","Wabtec","WAB","15142431744","82.91","United States"
"1034","SS&C Technologies","SSNC","15105965056","59.29","United States"
"1035","Suzuki Motor","7269.T","15104701680","31.1","Japan"
"1036","Cooper Companies","COO","15074274304","305.54","United States"
"1037","China Steel","2002A.TW","15067551283","1.7","Taiwan"
"1038","Terna","TRN.MI","15048704000","7.5","Italy"
"1039","Evergy","EVRG","15035398144","65.52","United States"
"1040","Coal India","COALINDIA.NS","15029345882","2.44","India"
"1041","CNH Industrial","CNHI","15022291968","11.09","United Kingdom"
"1042","Symrise","SY1.DE","15017232346","107.44","Germany"
"1043","CTBC Financial Holding","2891.TW","14994677868","0.77","Taiwan"
"1044","Swiss Life","SLHN.SW","14967219162","484.26","Switzerland"
"1045","Telefonica Brasil","VIV","14887016448","8.89","Brazil"
"1046","China Merchants Shekou Industrial Zone","001979.SZ","14869384537","1.92","China"
"1047","Associated British Foods","ABF.L","14867805927","1870.94","United Kingdom"
"1048","Grupo Bimbo","BIMBOA.MX","14848312640","3.38","Mexico"
"1049","Tenaris","TS","14843764736","25.15","Luxembourg"
"1050","SolarEdge","SEDG","14797271040","267.16","Israel"
"1051","Eurofins Scientific","ERF.PA","14794644915","76.88","Luxembourg"
"1052","Trimble","TRMB","14788395008","59.12","United States"
"1053","Shimano","7309.T","14784310375","162.22","Japan"
"1054","Campbell Soup","CPB","14776315904","49.16","United States"
"1055","Standard Bank Group","SBK.JO","14750515537","8.94","South Africa"
"1056","ZoomInfo","ZI","14697624576","36.44","United States"
"1057","DiDi","DIDIY","14659201024","3.02","China"
"1058","Alliant Energy","LNT","14640013312","58.37","United States"
"1059","Marubeni","8002.T","14637211177","8.64","Japan"
"1060","NVR","NVR","14624325632","4445.53","United States"
"1061","Expedia Group","EXPE","14581633024","92.82","United States"
"1062","Darden Restaurants","DRI","14573920256","116.84","United States"
"1063","Akamai","AKAM","14566915072","90.87","United States"
"1064","Cardinal Health","CAH","14558498816","53.44","United States"
"1065","Teradyne","TER","14544030720","90.79","United States"
"1066","China Unicom","0762.HK","14539415144","0.48","Hong Kong"
"1067","SEGRO","SGRO.L","14501205187","1199.35","United Kingdom"
"1068","Nissan","7201.T","14487917643","3.7","Japan"
"1069","Shanghai Airport","600009.SS","14485512375","7.52","China"
"1070","CarMax","KMX","14455455744","90.82","United States"
"1071","Shinhan Financial Group","SHG","14441759744","27.13","South Korea"
"1072","China Southern Airlines","ZNH","14436993024","27.61","China"
"1073","Domino's Pizza","DPZ","14436080640","400.5","United States"
"1074","NetApp","NTAP","14421586944","65.2","United States"
"1075","Marathon Oil","MRO","14419204096","20.38","United States"
"1076","Healthpeak Properties","PEAK","14406171648","26.7","United States"
"1077","Pidilite","PIDILITIND.NS","14389167297","28.31","India"
"1078","LKQ Corporation","LKQ","14387714048","50.87","United States"
"1079","Equity LifeStyle Properties","ELS","14378648576","73.62","United States"
"1080","CNP Assurances","CNP.PA","14366616004","20.94","France"
"1081","American Homes 4 Rent","AMH","14356146176","35.92","United States"
"1082","HDFC Life","HDFCLIFE.NS","14345518944","6.79","India"
"1083","SBI Life Insurance","SBILIFE.NS","14341915239","14.34","India"
"1084","Loews Corporation","L","14311180288","58.15","United States"
"1085","Western Digital","WDC","14285158400","45.62","United States"
"1086","LPL Financial","LPLA","14277698560","178.55","United States"
"1087","AES","AES","14272167936","21.37","United States"
"1088","IDEX","IEX","14261310464","187.64","United States"
"1089","Bio-Techne","TECH","14247841792","363.16","United States"
"1090","J.M. Smucker Company","SJM","14231353344","133.56","United States"
"1091","Swedbank","SWED-A.ST","14230920599","12.67","Sweden"
"1092","Hindustan Zinc","HINDZINC.NS","14229125536","3.37","India"
"1093","Credit Suisse","CS","14221350912","5.47","Switzerland"
"1094","Albertsons","ACI","14217375744","26.75","United States"
"1095","Hyundai Mobis","012330.KS","14204180135","156.01","South Korea"
"1096","Adani Power","ADANIPOWER.NS","14201327880","3.68","India"
"1097","Xylem","XYL","14189527040","78.79","United States"
"1098","Exor","EYX.F","14189486142","61.64","Netherlands"
"1099","Camden Property Trust","CPT","14179010560","133.11","United States"
"1100","Generac Power Systems","GNRC","14153025536","221.73","United States"
"1101","Tyler Technologies","TYL","14126564352","340.62","United States"
"1102","KPN","KPN.F","14122638351","3.39","Netherlands"
"1103","Coinbase","COIN","14087601152","53.79","United States"
"1104","Novolipetsk Steel","NLMK.ME","14047824989","2.34","Russia"
"1105","Iron Mountain","IRM","14022520832","48.26","United States"
"1106","Swire Properties","1972.HK","13980809066","2.39","Hong Kong"
"1107","Bajaj Auto","BAJAJ-AUTO.NS","13971421060","48.4","India"
"1108","Leidos","LDOS","13947723776","102.06","United States"
"1109","Fresenius Medical Care","FMS","13923907584","23.28","Germany"
"1110","Wharf REIC","1997.HK","13904145256","4.58","Hong Kong"
"1111","Bank Leumi","LUMI.TA","13878871318","9.3","Israel"
"1112","Power Financial","PWF-PS.TO","13865844361","15.09","Canada"
"1113","Secom","9735.T","13856154169","64.07","Japan"
"1114","Tata Steel","TATASTEEL.NS","13855541995","11.35","India"
"1115","JDE Peet's","JDE.F","13841255095","27.41","Netherlands"
"1116","Howmet Aerospace","HWM","13820414976","33.07","United States"
"1117","Boston Properties","BXP","13782819840","87.95","United States"
"1118","Teck Resources","TECK","13781452800","25.74","Canada"
"1119","Formula One Group","FWONK","13778725888","59.85","United States"
"1120","Jack Henry & Associates","JKHY","13758493696","188.83","United States"
"1121","Ono Pharmaceutical","4528.T","13754910551","28.17","Japan"
"1122","Power Assets","0006.HK","13689588651","6.41","Hong Kong"
"1123","Almarai","2280.SR","13639170346","13.72","Saudi Arabia"
"1124","Entegris","ENTG","13623327744","91.57","United States"
"1125","Avery Dennison","AVY","13593991168","166.36","United States"
"1126","Sasol","SSL","13552975872","21.33","South Africa"
"1127","Ajinomoto","2802.T","13547678676","25.25","Japan"
"1128","Itaúsa","ITSA3.SA","13531824768","1.6","Brazil"
"1129","OMV","OMV.F","13529297022","39.72","Austria"
"1130","3i Group","III.L","13506805748","1381.21","United Kingdom"
"1131","Brookfield Property Partners","BPYPP","13500818432","20.43","Bermuda"
"1132","OBIC","4684.T","13482780249","152.04","Japan"
"1133","Grupo Elektra","XEKT.MC","13467905416","53.8","Mexico"
"1134","HubSpot","HUBS","13454645248","281.66","United States"
"1135","Bolloré","BOP.F","13436910496","4.48","France"
"1136","Shaw Communications","SJR","13434424320","26.9","Canada"
"1137","Prada","1913.HK","13430141644","5.25","Italy"
"1138","NortonLifeLock","NLOK","13411080192","23.12","United States"
"1139","Kirin Holdings","2503.T","13410732720","16.16","Japan"
"1140","Aviva","AV.L","13392562603","473.68","United Kingdom"
"1141","Warner Music Group","WMG","13380925440","25.99","United States"
"1142","Capitec Bank","CPI.JO","13378098430","115.23","South Africa"
"1143","Inpex","1605.T","13328633653","10.17","Japan"
"1144","Vodacom","5VD.F","13280862986","7.84","South Africa"
"1145","Uni-President Enterprises","1216.TW","13233483245","2.33","Taiwan"
"1146","Textron","TXT","13227604992","61.5","United States"
"1147","Targa Resources","TRGP","13216464896","57.97","United States"
"1148","Bunge","BG","13215128576","87.1","United States"
"1149","WSP Global","WSP.TO","13207427636","111.86","Canada"
"1150","Omnicom","OMC","13193656320","64.13","United States"
"1151","Carlisle Companies","CSL","13167866880","254.71","United States"
"1152","AppLovin","APP","13167343616","34.83","United States"
"1153","Bill.com","BILL","13152355328","126.14","United States"
"1154","Sysmex","6869.T","13137419376","62.79","Japan"
"1155","Metro","MRU.TO","13133462642","54.73","Canada"
"1156","FMC","FMC","13108989952","104.09","United States"
"1157","POSCO","PKX","13066746880","43.03","South Korea"
"1158","Jerónimo Martins","JEM.F","13063726592","20.43","Portugal"
"1159","Chandra Asri Petrochemical","TPIA.JK","13061895079","0.6","Indonesia"
"1160","NN Group","NN.AS","13052732879","43.63","Netherlands"
"1161","Cboe","CBOE","13034169344","122.75","United States"
"1162","Packaging Corporation of America","PKG","13023529984","138.99","United States"
"1163","Antofagasta","ANTO.L","12957025749","1259.97","United Kingdom"
"1164","Continental","CON.DE","12935531471","64.68","Germany"
"1165","Nippon Steel","5401.T","12932667763","14.04","Japan"
"1166","Eisai","4523.T","12926204690","45.09","Japan"
"1167","NICE","NICE","12850889728","200.14","Israel"
"1168","Citrix Systems","CTXS","12830148608","101.36","United States"
"1169","IHH Healthcare","Q0F.SI","12773078392","1.45","Malaysia"
"1170","Subaru","7270.T","12766507488","16.65","Japan"
"1171","Formosa Chemicals & Fibre","1326.TW","12661997290","2.16","Taiwan"
"1172","Masco","MAS","12653462528","53.63","United States"
"1173","DocuSign","DOCU","12638459904","63.21","United States"
"1174","First Quantum Minerals","FM.TO","12622978263","16.73","Canada"
"1175","bioMérieux","BIM.PA","12576296414","105.18","France"
"1176","Steel Dynamics","STLD","12572413952","66.63","United States"
"1177","Indian Oil","IOC.NS","12547954267","0.89","India"
"1178","Sino Biopharmaceutical","1177.HK","12535859929","0.67","China"
"1179","JBS","JBSS3.SA","12524485424","5.65","Brazil"
"1180","EQT Corporation","EQT","12492164096","33.81","United States"
"1181","kyowa Kirin","4151.T","12488499398","23.24","Japan"
"1182","Carrefour","CA.PA","12480119698","16.87","France"
"1183","Siam Cement","SCC.BK","12435061205","10.36","Thailand"
"1184","Unilever Indonesia","UNVR.JK","12423890639","0.33","Indonesia"
"1185","Dassault Aviation","AM.PA","12416147757","149.22","France"
"1186","Siemens Gamesa","GCTAF","12404151296","18.13","Spain"
"1187","Kimco Realty","KIM","12403399680","20.07","United States"
"1188","Molson Coors","TAP","12396820480","57.13","United States"
"1189","Stora Enso","STEAV.HE","12392199851","15.99","Finland"
"1190","Israel Chemicals","ICL","12369510400","9.61","Israel"
"1191","KB Financial Group","KB","12346183680","35.03","South Korea"
"1192","Westlake Chemical","WLK","12326000640","96.05","United States"
"1193","MGM Resorts","MGM","12321424384","28.92","United States"
"1194","Emera","EMA.TO","12316344557","46.81","Canada"
"1195","Divis Laboratories","DIVISLAB.NS","12312013796","46.38","India"
"1196","Pinterest","PINS","12301011968","18.54","United States"
"1197","PTC","PTC","12298856448","105.14","United States"
"1198","Booz Allen Hamilton","BAH","12295330816","92.89","United States"
"1199","Essential Utilities","WTRG","12275265536","46.84","United States"
"1200","Viatris","VTRS","12226348032","10.09","United States"
"1201","China Eastern Airlines","CEA","12224380928","18.95","China"
"1202","Celanese","CE","12221587456","112.84","United States"
"1203","Tech Mahindra","TECHM.NS","12199824985","12.54","India"
"1204","Gaming and Leisure Properties","GLPI","12199317504","47.95","United States"
"1205","New China Life Insurance","601336.SS","12155254149","4.59","China"
"1206","Huazhu Hotels","HTHT","12135794688","37.71","China"
"1207","C. H. Robinson","CHRW","12128450560","95.3","United States"
"1208","Abiomed","ABMD","12126881792","265.79","United States"
"1209","Liberty Media","LSXMB","12117979136","37.02","United States"
"1210","Dabur","DABUR.NS","12110060417","6.84","India"
"1211","United Airlines Holdings","UAL","12069442560","36.94","United States"
"1212","Lufax","LU","12057647104","5.28","China"
"1213","Franklin Resources","BEN","12045668352","24.1","United States"
"1214","Mowi","MNHVF","12041125888","23.2","Norway"
"1215","CNA Financial","CNA","12027173888","44.33","United States"
"1216","Bank Hapoalim","POLI.TA","12006175256","8.99","Israel"
"1217","Nordson","NDSN","12000412672","208.66","United States"
"1218","Arab National Bank","1080.SR","11989768594","7.99","Saudi Arabia"
"1219","Shinkin Central Bank","8421.T","11986768808","1786.88","Japan"
"1220","Mitsubishi Heavy Industries","7011.T","11982530775","35.69","Japan"
"1221","Signature Bank","SBNY","11966388224","190.16","United States"
"1222","Aéroports de Paris","ADP.PA","11953905199","120.81","France"
"1223","Barry Callebaut","BARN.SW","11922940329","2175.33","Switzerland"
"1224","Newcrest Mining","NCM.AX","11905265031","12.99","Australia"
"1225","Unity Software","U","11902682112","40.21","United States"
"1226","Suntory","2587.T","11897926500","38.5","Japan"
"1227","Smith & Nephew","SNN","11863567360","26.92","United Kingdom"
"1228","E.SUN Bank","2884.TW","11859419025","0.89","Taiwan"
"1229","Bangkok Dusit Medical Services (BDMS)","BDMS.BK","11857079249","0.75","Thailand"
"1230","Hua Xia Bank","600015.SS","11853029104","0.77","China"
"1231","Siemens India","SIEMENS.NS","11849540238","33.27","India"
"1232","Swatch","UHR.SW","11843308978","236.17","Switzerland"
"1233","Vifor Pharma","VIFN.SW","11812897246","182.04","Switzerland"
"1234","American Financial Group","AFG","11801094144","138.67","United States"
"1235","B3","B3SA3.SA","11796704623","1.94","Brazil"
"1236","Campari","CPR.MI","11794060292","10.44","Italy"
"1237","Roku","ROKU","11792837632","86.73","United States"
"1238","LG Electronics","LGLG.F","11788304475","16.69","South Korea"
"1239","Suzano","SUZ","11779824640","8.73","Brazil"
"1240","AspenTech","AZPN","11753614336","189.06","United States"
"1241","NiSource","NI","11747853312","28.95","United States"
"1242","QBE Insurance","QBE.AX","11741347502","7.92","Australia"
"1243","Texas Pacific Land Trust","TPL","11734085632","1515.7","United States"
"1244","GoDaddy","GDDY","11709195264","72.25","United States"
"1245","GBL","GBLB.VI","11700485534","81.15","Belgium"
"1246","Severstal","CHMF.ME","11687513808","13.95","Russia"
"1247","Eastman Chemical","EMN","11685730304","90.67","United States"
"1248","Teleflex","TFX","11682111488","249.09","United States"
"1249","Country Garden","2007.HK","11675332374","0.51","China"
"1250","First Horizon National","FHN","11670993920","21.82","United States"
"1251","Carlyle Group","CG","11664633856","32.29","United States"
"1252","New Hope Liuhe","000876.SZ","11637060963","2.58","China"
"1253","ESR","1821.HK","11632630399","2.61","Hong Kong"
"1254","Bunzl","BNZL.L","11591576783","3434.01","United Kingdom"
"1255","Host Hotels & Resorts","HST","11585006592","15.98","United States"
"1256","ENEOS Holdings","5020.T","11582446786","3.66","Japan"
"1257","Hasbro","HAS","11575080960","83.01","United States"
"1258","Sekisui House","1928.T","11570607733","17.29","Japan"
"1259","Hansoh Pharma","3692.HK","11558365822","1.95","China"
"1260","SG Holdings","9143.T","11556028399","18.18","Japan"
"1261","Sumitomo Mitsui Trust Holdings","8309.T","11547624293","30.8","Japan"
"1262","Hai Di Lao Hot Pot","6862.HK","11531787448","2.07","China"
"1263","Edenred","EDEN.PA","11511885225","46.19","France"
"1264","Taiwan Cooperative Financial","5880.TW","11485630372","0.84","Taiwan"
"1265","Carl Zeiss Meditec","AFXA.F","11453254146","122.67","Germany"
"1266","Nippon Yūsen","9101.T","11438941809","67.71","Japan"
"1267","Dynatrace","DT","11430693888","39.85","United States"
"1268","Grasim Industries","GRASIM.NS","11426271397","17.36","India"
"1269","South32","S32.AX","11413226559","2.4","Australia"
"1270","Arca Continental","AC.MX","11403721308","6.46","Mexico"
"1271","Coca-Cola FEMSA","KOF","11401204736","54.27","Mexico"
"1272","Wharf Holdings","0004.HK","11368000881","3.72","Hong Kong"
"1273","Charles River Laboratories","CRL","11362515968","223.65","United States"
"1274","Croda International","CRDA.L","11331553400","8011.51","United Kingdom"
"1275","Sino Land","0083.HK","11307203946","1.47","Hong Kong"
"1276","Britannia Industries","BRITANNIA.NS","11290034531","46.86","India"
"1277","Danske Bank","DANS.VI","11277905601","13.25","Denmark"
"1278","Poste Italiane","PST.MI","11246046793","8.5","Italy"
"1279","Alleghany","Y","11226768384","834.4","United States"
"1280","Nitori Holdings","9843.T","11204827157","99.23","Japan"
"1281","Advance Auto Parts","AAP","11193846784","184.6","United States"
"1282","Toyota Tsusho","8015.T","11178168900","31.77","Japan"
"1283","Publicis Groupe","PUB.PA","11176023521","44.71","France"
"1284","Nomura Holdings","NMR","11156177920","3.68","Japan"
"1285","Service Corporation International","SCI","11151204352","70.25","United States"
"1286","ASX","ASX.AX","11149481317","57.16","Australia"
"1287","AkzoNobel","AKZA.AS","11142298964","62.99","Netherlands"
"1288","Rentokil Initial","RTO.L","11139247736","597.65","United Kingdom"
"1289","Norsk Hydro","NHY.OL","11137382595","5.39","Norway"
"1290","Thai Beverage","TBVPF","11135013888","0.44","Thailand"
"1291","Ally","ALLY","11119243264","34.42","United States"
"1292","Lumen","LUMN","11100229632","10.75","United States"
"1293","Hongkong Land","H78.SI","11095524352","4.95","Hong Kong"
"1294","Interpublic Group","IPG","11059989504","28.1","United States"
"1295","Bureau Veritas","BVI.PA","11048024036","24.28","France"
"1296","Everest Re","RE","11017793536","279.37","BM"
"1297","Etsy","ETSY","11017403392","86.67","United States"
"1298","Godrej","GODREJCP.NS","11015100355","10.77","India"
"1299","Moncler","MONC.MI","11001975441","40.94","Italy"
"1300","Singapore Airlines","C6L.SI","10975850231","3.7","Singapore"
"1301","Apache Corporation","APA","10968863744","32.43","United States"
"1302","Fortum","FORTUM.HE","10964111638","12.34","Finland"
"1303","Sodexo","SW.PA","10960084625","74.75","France"
"1304","FICO","FICO","10950176768","422.27","United States"
"1305","Lamb Weston","LW","10933194752","75.69","United States"
"1306","Crown Holdings","CCK","10917250048","88.8","United States"
"1307","Shandong Gold Mining","600547.SS","10914485022","2.63","China"
"1308","Sonic Healthcare","SHL.AX","10904565824","22.71","Australia"
"1309","Bank Albilad","1140.SR","10897368057","10.9","Saudi Arabia"
"1310","ASE Group","ASX","10894992384","5.09","Taiwan"
"1311","Hotai Motor","2207.TW","10890268722","19.94","Taiwan"
"1312","Reliance Steel & Aluminum","RS","10880253952","175.64","United States"
"1313","Bouygues","EN.PA","10867331539","28.3","France"
"1314","Kikkoman","2801.T","10866350570","56.73","Japan"
"1315","Lasertec","6920.T","10859081532","120.42","Japan"
"1316","UiPath","PATH","10855202816","19.93","United States"
"1317","Korea Electric Power","KEP","10849208320","8.45","South Korea"
"1318","Lenovo","0992.HK","10830191639","0.9","Hong Kong"
"1319","United Therapeutics","UTHR","10827033600","239.01","United States"
"1320","DLF","DLF.NS","10807991997","4.36","India"
"1321","Ramsay Health Care","RHC.AX","10801225098","47.19","Australia"
"1322","Kanzhun","BZ","10795334656","24.82","China"
"1323","NEC Corp","6701.T","10791446662","39.6","Japan"
"1324","Vedanta","VEDL.NS","10788145242","2.9","India"
"1325","First Citizens BancShares","FCNCA","10784381952","676.82","United States"
"1326","Qiagen","QGEN","10758479872","47.3","Netherlands"
"1327","TDK","6762.T","10751439126","28.37","Japan"
"1328","Snap-on","SNA","10744760320","201.31","United States"
"1329","Hong Kong Telecom","6823.HK","10731822017","1.42","Hong Kong"
"1330","Nexi","NEXI.MI","10720400668","8.17","Italy"
"1331","Builders FirstSource","BLDR","10689772544","61.88","United States"
"1332","Rede D'Or Sao Luiz","RDOR3.SA","10679800796","5.41","Brazil"
"1333","PulteGroup","PHM","10676581376","44.93","United States"
"1334","Fidelity National Financial","FNF","10658331648","37.97","United States"
"1335","Henry Schein","HSIC","10645112832","77.11","United States"
"1336","First Financial Holding","2892.TW","10643842732","0.82","Taiwan"
"1337","SK Innovation","096775.KS","10638275958","82.21","South Korea"
"1338","Acciona","ANA.MC","10616869068","194.27","Spain"
"1339","Adani Wilmar","AWL.NS","10599575523","8.15","India"
"1340","OpenText","OTEX","10565862400","38.94","Canada"
"1341","James Hardie Industries","JHX","10556738560","23.7","Ireland"
"1342","WPP","WPP","10555172864","46.88","United Kingdom"
"1343","Plug Power","PLUG","10552829952","17.89","United States"
"1344","Agilon Health","AGL","10550602752","25.94","United States"
"1345","RPM International","RPM","10539679744","81.39","United States"
"1346","Liberty Global","LBTYB","10539267072","21.75","United Kingdom"
"1347","AMEC","688012.SS","10520456461","17.07","China"
"1348","Regency Centers","REG","10470418432","60.48","United States"
"1349","REA Group","REA.AX","10457364472","79.15","Australia"
"1350","Asahi Kasei","3407.T","10449841203","7.53","Japan"
"1351","ASM International","ASM.AS","10436029329","214.93","Netherlands"
"1352","Yara International","YAR.OL","10399024330","40.53","Norway"
"1353","Ryan Specialty Group","RYAN","10348439552","39.93","United States"
"1354","Brambles","BXB.AX","10340000076","7.46","Australia"
"1355","Lundbergföretagen","LUND-B.ST","10335889668","41.98","Sweden"
"1356","Siemens Energy","ENR.F","10322812718","14.39","Germany"
"1357","Enel Américas","ENIA","10320480256","4.81","Chile"
"1358","Westrock","WRK","10320231424","40.5","United States"
"1359","Biohaven Pharmaceutical","BHVN","10319734784","145.26","United States"
"1360","Erie Indemnity","ERIE","10279932928","196.6","United States"
"1361","Amundi","AMUN.PA","10278610309","50.68","France"
"1362","Ovintiv","OVV","10258245632","39.74","United States"
"1363","Paylocity","PCTY","10247700480","185.9","United States"
"1364","Tenaga Nasional","TNABY","10235984896","6.83","Malaysia"
"1365","Carnival","CCL","10234935296","8.67","United States"
"1366","Morningstar","MORN","10207912960","238.89","United States"
"1367","Amdocs","DOX","10204318720","83.07","United States"
"1368","Qorvo","QRVO","10196364288","98.3","United States"
"1369","Alfa Laval","ALFA.ST","10183201813","24.64","Sweden"
"1370","Rexford Industrial","REXR","10173134848","59.83","United States"
"1371","InterContinental Hotels Group","IHG","10166884352","55.25","United Kingdom"
"1372","Graco","GGG","10166312960","60.08","United States"
"1373","Eicher Motors","EICHERMOT.NS","10159014338","37.15","India"
"1374","Red Eléctrica","REE.MC","10140251383","18.8","Spain"
"1375","Magellan Midstream Partners","MMP","10140118016","47.93","United States"
"1376","Western Midstream","WES","10131750912","25.12","United States"
"1377","Aluminum Corporation of China","ACH","10112157696","8.98","China"
"1378","Black Knight","BKI","10092559360","64.71","United States"
"1379","SBI Card","SBICARD.NS","10083582988","10.69","India"
"1380","CIMB Group","1023.KL","10070020753","1.15","Malaysia"
"1381","Gjensidige Forsikring","XGJ.F","10060795367","20.01","Norway"
"1382","GameStop","GME","10060446720","132.15","United States"
"1383","Getlink","GET.PA","10040153709","18.6","France"
"1384","Computershare","CPU.AX","10023378971","16.6","Australia"
"1385","Hubbell","HUBB","10011589632","186.57","United States"
"1386","Worldline","WLN.PA","10003468871","35.33","France"
"1387","HF Sinclair","DINO","9987310592","44.74","United States"
"1388","Bentley Systems","BSY","9983181824","34.72","United States"
"1389","MarketAxess","MKTX","9972191232","264.22","United States"
"1390","Yonyou","600588.SS","9962793782","2.9","China"
"1391","Globe Life","GL","9945988096","100.87","United States"
"1392","Quanta Computer","2382.TW","9920148808","2.57","Taiwan"
"1393","Omron","6645.T","9878232474","49.44","Japan"
"1394","Equitable Holdings","EQH","9875676160","25.92","United States"
"1395","Watsco","WSO","9872649216","254.1","United States"
"1396","Burlington Stores","BURL","9869189120","149.37","United States"
"1397","INWIT","INW.MI","9862284549","10.28","Italy"
"1398","Advantest","6857.T","9856308302","51.9","Japan"
"1399","CapitaLand Mall Trust","C38U.SI","9855451910","1.49","Singapore"
"1400","Chesapeake Energy","CHK","9848011776","77.43","United States"
"1401","Taiwan Mobile","3045.TW","9829762012","3.49","Taiwan"
"1402","Jazz Pharmaceuticals","JAZZ","9784427520","156.7","Ireland"
"1403","Bruker","BRKR","9750830080","65.33","United States"
"1404","Hindalco Industries","HINDALCO.NS","9733426828","4.36","India"
"1405","Life Storage","LSI","9727062016","114","United States"
"1406","Grifols","GRFS","9720487936","10.68","Spain"
"1407","Next plc","NXT.L","9712928289","7505.14","United Kingdom"
"1408","Comerica","CMA","9708930048","74.25","United States"
"1409","Halma","HLMA.L","9702204339","2555.6","United Kingdom"
"1410","AerCap","AER","9694582784","39.47","Ireland"
"1411","Vistra","VST","9693583360","22.45","United States"
"1412","Elbit Systems","ESLT","9663606784","218.18","Israel"
"1413","Assurant","AIZ","9659328512","178.6","United States"
"1414","Industrivarden","INDU-A.ST","9653890071","22.7","Sweden"
"1415","Credicorp","BAP","9634506752","121.14","Bermuda"
"1416","PUMA","PUM.DE","9630745227","64.37","Germany"
"1417","Vivendi","VIV.PA","9627847755","9.3","France"
"1418","Saputo","SAP.TO","9625415168","23.09","Canada"
"1419","Havells India","HAVELLS.NS","9623609439","15.36","India"
"1420","Erste Group Bank","EBO.F","9622037366","23.73","Austria"
"1421","XP Inc.","XP","9621108736","17.18","Brazil"
"1422","Scentre Group","SCG.AX","9613764435","1.85","Australia"
"1423","Yang Ming","2609.TW","9607634481","2.75","Taiwan"
"1424","Localiza","RENT3.SA","9607092445","9.85","Brazil"
"1425","Evonik Industries","EVK.DE","9605074695","19.72","Germany"
"1426","Chailease Holding","5871.TW","9594419010","6.3","Taiwan"
"1427","Anaplan","PLAN","9593149440","63.73","United States"
"1428","Kasikornbank","KBANK.BK","9591766234","4.05","Thailand"
"1429","Annaly Capital Management","NLY","9545636864","6.12","United States"
"1430","Elanco","ELAN","9535255552","20.11","United States"
"1431","Suncorp","SUN.AX","9516655759","7.54","Australia"
"1432","ICICI Prulife","ICICIPRULI.NS","9512760065","6.61","India"
"1433","CubeSmart","CUBE","9499011072","42.05","United States"
"1434","Cipla","CIPLA.NS","9496695058","11.77","India"
"1435","WH Group","0288.HK","9479928220","0.74","Hong Kong"
"1436","Hua Nan Financial Holdings","2880.TW","9461939263","0.72","Taiwan"
"1437","MTU Aero Engines","MTX.DE","9454061209","176.92","Germany"
"1438","SK Telecom","SKM","9428099072","23.34","South Korea"
"1439","Ares Capital","ARCC","9418213376","19.04","United States"
"1440","Antero Resources","AR","9409792000","30.25","United States"
"1441","Medical Properties Trust","MPW","9400565760","15.67","United States"
"1442","Informa plc","INF.L","9392071547","635.69","United Kingdom"
"1443","LG Corp","003550.KS","9386466483","58.81","South Korea"
"1444","East West Bancorp","EWBC","9380829184","66.11","United States"
"1445","Brenntag","BNR.DE","9380302319","60.71","Germany"
"1446","Repligen","RGEN","9375139840","169.13","United States"
"1447","Spirax-Sarco Engineering","SPX.L","9364439164","12694.79","United Kingdom"
"1448","Yandex","YNDX.ME","9355487462","28.94","Netherlands"
"1449","Darling Ingredients","DAR","9329048576","57.76","United States"
"1450","Full Truck Alliance","YMM","9327185920","8.42","China"
"1451","Yakult","2267.T","9324382803","59.51","Japan"
"1452","Juniper Networks","JNPR","9321290752","28.85","United States"
"1453","Julius Bär","BAER.SW","9320319896","44.55","Switzerland"
"1454","Pan Pacific","7532.T","9318984756","15.63","Japan"
"1455","Lamar Advertising","LAMR","9275454464","91.4","United States"
"1456","Delivery Hero","DHER.F","9272773567","38.09","Germany"
"1457","Bank Negara Indonesia","BBNI.JK","9271459590","0.5","Indonesia"
"1458","BJ's Wholesale Club","BJ","9265374208","68.54","United States"
"1459","American Airlines","AAL","9265332224","14.27","United States"
"1460","Ambuja Cements","AMBUJACEM.NS","9264148927","4.66","India"
"1461","Whirlpool","WHR","9259486208","164.75","United States"
"1462","Dr. Reddy's","RDY","9257973760","55.78","India"
"1463","Saudi International Petrochemical Company (Sipchem)","2310.SR","9251656110","12.62","Saudi Arabia"
"1464","AECOM","ACM","9216833536","65.35","United States"
"1465","Bilibili","BILI","9212935168","24.06","China"
"1466","Clarivate","CLVT","9197121536","13.68","United Kingdom"
"1467","F5 Networks","FFIV","9194162176","152.04","United States"
"1468","Dish Network","DISH","9192797184","17.35","United States"
"1469","News Corp","NWS","9189396480","15.87","United States"
"1470","Adevinta","ADE.OL","9185834844","7.02","Norway"
"1471","Zendesk","ZEN","9162733568","74.33","United States"
"1472","Wan Hai Lines","2615.TW","9158357870","3.75","Taiwan"
"1473","Rémy Cointreau","RCO.PA","9157875515","180.49","France"
"1474","Neurocrine Biosciences","NBIX","9154336768","95.78","United States"
"1475","Amerco","UHAL","9136254976","465.95","United States"
"1476","Cochlear","COH.AX","9115079273","138.58","Australia"
"1477","Kesko","KESKOA.HE","9111499487","21.67","Finland"
"1478","Grab Holdings","GRAB","9099851776","2.37","Singapore"
"1479","HMM","011200.KS","9097479796","18.01","South Korea"
"1480","HeidelbergCement","HEI.DE","9096390210","47.11","Germany"
"1481","Far EasTone","4904.TW","9085057300","2.79","Taiwan"
"1482","Olaplex","OLPX","9084991488","14","United States"
"1483","KEPCO","9503.T","9081179935","10.18","Japan"
"1484","WiseTech Global","WTC.AX","9071416849","27.8","Australia"
"1485","ABN AMRO","ABN.AS","9069981410","10.11","Netherlands"
"1486","Algonquin Power & Utilities","AQN","9066323968","13.42","Canada"
"1487","Impala Platinum","IMP.JO","9062835638","10.1","South Africa"
"1488","Mizrahi-Tefahot","MZTF.TA","9060288693","35.31","Israel"
"1489","Shree Cement","SHREECEM.NS","9058792965","251.07","India"
"1490","ST Engineering","SJX.F","9048355395","2.9","Singapore"
"1491","Talanx","TLX.DE","9034741189","35.7","Germany"
"1492","NRG Energy","NRG","9033401344","38.07","United States"
"1493","Knorr-Bremse","KBX.DE","9031447296","55.87","Germany"
"1494","Kingdom Holding","4280.SR","9005306789","2.43","Saudi Arabia"
"1495","Williams-Sonoma","WSM","9004171264","130.95","United States"
"1496","Nitto Denko","6988.T","9003904186","60.83","Japan"
"1497","Recordati","REC.MI","8995928036","43.76","Italy"
"1498","Azrieli Group","AZRG.TA","8932622104","73.6","Israel"
"1499","A. O. Smith","AOS","8930933760","57.25","United States"
"1500","Schroders","SDR.L","8927620621","3228.38","United Kingdom"
"1501","Tata Power","TATAPOWER.NS","8906439987","2.79","India"
"1502","Embracer Group","EMBRAC-B.ST","8891998066","7.9","Sweden"
"1503","SK Group","034730.KS","8863366892","157.92","South Korea"
"1504","Logitech","LOGI","8857518080","53.48","Switzerland"
"1505","Resona Holdings","8308.T","8837456067","3.71","Japan"
"1506","Toray Industries","3402.T","8812004839","5.22","Japan"
"1507","Alstom","ALO.PA","8806193038","23.56","France"
"1508","Synnex","SNX","8796947456","91.78","United States"
"1509","Doosan Enerbility","034020.KS","8771925823","13.88","South Korea"
"1510","Tata Consumer Products","TATACONSUM.NS","8767771527","9.51","India"
"1511","Larsen & Toubro Infotech","LTI.BO","8753932871","50.15","India"
"1512","Randstad","RAND.AS","8743292975","47.82","Netherlands"
"1513","Elisa","ELISA.HE","8695454826","54.26","Finland"
"1514","Allegion","ALLE","8685220864","98.92","Ireland"
"1515","Deutsche Wohnen","DWNI.DE","8677090783","21.86","Germany"
"1516","Demant","WDH1.F","8675608068","36.6","Denmark"
"1517","New World Development Company","0017.HK","8672219286","3.45","Hong Kong"
"1518","Huntington Ingalls Industries","HII","8670618624","216.51","United States"
"1519","Jones Lang LaSalle","JLL","8662467584","177.28","United States"
"1520","Cameco","CCJ","8637496320","21.21","Canada"
"1521","SIG Combibloc","SIGN.SW","8634821704","22.59","Switzerland"
"1522","Robert Half","RHI","8626722816","78.06","United States"
"1523","Ascendas Reit","A17U.SI","8605646763","2.05","Singapore"
"1524","Rolls-Royce Holdings","RR.L","8598143213","102.3","United Kingdom"
"1525","Nippon Building Fund","8951.T","8579224827","5043.67","Japan"
"1526","Mondi","MNDI.L","8576854764","1748.51","United Kingdom"
"1527","GFL Environmental","GFL","8556924928","25","Canada"
"1528","Xero","XRO.AX","8554251508","56.97","New Zealand"
"1529","Vail Resorts","MTN","8535533568","211.9","United States"
"1530","Eiffage","FGR.PA","8510386260","86.78","France"
"1531","Krafton","259960.KS","8501239218","181.25","South Korea"
"1532","Admiral Group","ADM.L","8481681152","2805.22","United Kingdom"
"1533","Galp Energia","GZ5.F","8479003672","10.05","Portugal"
"1534","United Utilities","UU.L","8478108733","1243.33","United Kingdom"
"1535","Americold","COLD","8474674176","31.45","United States"
"1536","West Japan Railway","9021.T","8471918240","34.75","Japan"
"1537","UGI Corporation","UGI","8466917376","40.32","United States"
"1538","Dropbox","DBX","8454845952","22.51","United States"
"1539","AEGON","AEG","8451020800","4.14","Netherlands"
"1540","Rheinmetall","RHM.F","8425587322","194.57","Germany"
"1541","Bharat Petroleum","BPCL.NS","8423627586","3.88","India"
"1542","Taiwan Cement","1101.TW","8403303692","1.37","Taiwan"
"1543","Nielsen","NLSN","8400324096","23.35","United States"
"1544","Gold Fields","GFI","8388414976","9.11","South Africa"
"1545","Hapvida","HAPV3.SA","8386664748","1.18","Brazil"
"1546","Zillow","ZG","8385399808","34.03","United States"
"1547","Euronext","ENX.PA","8379058904","78.43","Netherlands"
"1548","Sealed Air","SEE","8376456704","57.34","United States"
"1549","Nykaa","NYKAA.NS","8361292226","17.62","India"
"1550","AVEVA","AVV.L","8360927927","2771.93","United Kingdom"
"1551","Caesars Entertainment","CZR","8358130688","38.99","United States"
"1552","Royal Caribbean","RCL","8354908160","32.77","United States"
"1553","Legend Biotech","LEGN","8349132288","54.14","United States"
"1554","Swire Pacific","0019.HK","8347702852","5.9","Hong Kong"
"1555","Hyatt Hotels","H","8340312576","75.61","United States"
"1556","Wolfspeed","WOLF","8335471616","67.42","United States"
"1557","ANA Holdings","9202.T","8316568454","17.68","Japan"
"1558","Penske Automotive","PAG","8300968960","109.38","United States"
"1559","Organon","OGN","8286320128","32.67","United States"
"1560","Isuzu","7202.T","8284326968","10.69","Japan"
"1561","Keppel","BN4.SI","8282496428","4.64","Singapore"
"1562","Advantech","2395.TW","8277735851","10.62","Taiwan"
"1563","Sumitomo Denki Kōgyō","5802.T","8269398382","10.6","Japan"
"1564","Banco de Chile","BCH","8258139648","16.35","Chile"
"1565","IndusInd Bank","INDUSINDBK.NS","8257671693","10.65","India"
"1566","Fortune Brands Home & Security","FBHS","8255229952","63.11","United States"
"1567","Boliden","BOL.ST","8251548977","30.17","Sweden"
"1568","China Gas","0384.HK","8247391615","1.52","China"
"1569","Dentsu","4324.T","8245411324","30.67","Japan"
"1570","Chr. Hansen","51C.F","8242232117","62.68","Denmark"
"1571","Monotaro","3064.T","8225576905","16.29","Japan"
"1572","The Toro Company","TTC","8225555456","78.66","United States"
"1573","Intertek","ITRK.L","8216503018","5090.99","United Kingdom"
"1574","BorgWarner","BWA","8215027200","34.29","United States"
"1575","GitLab","GTLB","8207688704","55.57","United States"
"1576","Largan Precision","3008.TW","8207291404","61.49","Taiwan"
"1577","InterGlobe Aviation","INDIGO.NS","8205590242","21.3","India"
"1578","SRF Limited","SRF.NS","8201087259","27.67","India"
"1579","Ocado","OCDO.L","8199938437","994.19","United Kingdom"
"1580","Empire Company","EMP-A.TO","8167087810","31.18","Canada"
"1581","Lincoln National Corporation","LNC","8164903936","47.49","United States"
"1582","Mitsui O.S.K. Lines","9104.T","8161909494","22.62","Japan"
"1583","HK Electric Investments","2638.HK","8161069819","0.92","Hong Kong"
"1584","New Fortress Energy","NFE","8156950528","39.3","United States"
"1585","Japan Exchange Group","8697.T","8154068605","15.46","Japan"
"1586","Genpact","G","8148406784","44.01","Bermuda"
"1587","Aisin Seiki","7259.T","8148139004","30.23","Japan"
"1588","Switch","SWCH","8147959808","33.73","United States"
"1589","Sage Group","SGE.L","8147350245","799.72","United Kingdom"
"1590","Samsung Life Insurance","032830.KS","8129916196","45.27","South Korea"
"1591","Orkla","ORKLF","8127648768","8.08","Norway"
"1592","Marico","MARICO.NS","8122892959","6.29","India"
"1593","Solvay","SOLB.VI","8111790270","77.24","Belgium"
"1594","Lithia Motors","LAD","8108931072","280.26","United States"
"1595","Canadian Utilities","CU.TO","8101373397","30.19","Canada"
"1596","Advanced Drainage Systems","WMS","8095749632","95.36","United States"
"1597","Genscript Biotech","1548.HK","8084348089","3.83","China"
"1598","Commerce Bancshares","CBSH","8081934336","66.94","United States"
"1599","Pinnacle West Capital","PNW","8077312000","71.48","United States"
"1600","Tōkyō Gas","9531.T","8070803767","18.49","Japan"
"1601","Hang Lung Properties","0101.HK","8069790408","1.79","Hong Kong"
"1602","Bank Jago","ARTO.JK","8067757319","0.58","Indonesia"
"1603","Hana Financial Group","086790.KS","8038150359","27.57","South Korea"
"1604","Mattel","MAT","8035101184","22.8","United States"
"1605","Knight-Swift","KNX","8031188480","49.1","United States"
"1606","Exact Sciences","EXAS","8023091200","45.6","United States"
"1607","S-OIL","010950.KS","8021236756","69.75","South Korea"
"1608","Umicore","UMI.VI","8020689794","32.5","Belgium"
"1609","Disco Corp.","6146.T","8018321522","222.17","Japan"
"1610","Ipsen","IPN.PA","8009014443","97.03","France"
"1611","Cleveland-Cliffs","CLF","7970754560","15.19","United States"
"1612","Lifco","LIFCO-B.ST","7951126241","16.23","Sweden"
"1613","Tele2","TEL2-A.ST","7930454578","11.37","Sweden"
"1614","Canadian Tire","CTC.TO","7929058974","205.35","Canada"
"1615","Burberry","BRBY.L","7928591644","1992.18","United Kingdom"
"1616","dLocal","DLO","7927402496","26.87","Uruguay"
"1617","Mohawk Industries","MHK","7920186368","124.65","United States"
"1618","Newell Brands","NWL","7910254592","19.13","United States"
"1619","Aramark","ARMK","7906890240","30.73","United States"
"1620","Owens Corning","OC","7885176832","81.23","United States"
"1621","Yaskawa","6506.T","7874549809","30.12","Japan"
"1622","Western Alliance Bancorporation","WAL","7871906304","72.7","United States"
"1623","Doximity","DOCS","7870616576","41.14","United States"
"1624","Lennox","LII","7860164608","218.89","United States"
"1625","AMC Entertainment","AMC","7859031040","15.31","United States"
"1626","Federal Realty Investment Trust","FRT","7853151232","98.07","United States"
"1627","National Retail Properties","NNN","7852667392","44.64","United States"
"1628","Melrose Industries","MRO.L","7850835854","186.74","United Kingdom"
"1629","DaVita","DVA","7844231680","82.92","United States"
"1630","Pentair","PNR","7830035968","47.34","United Kingdom"
"1631","Reinsurance Group of America","RGA","7824420352","116.8","United States"
"1632","Floor & Decor","FND","7820788736","73.88","United States"
"1633","Tapestry","TPR","7813416448","31.03","United States"
"1634","IMCD","IMCD.AS","7811278447","137.2","Netherlands"
"1635","OGE Energy","OGE","7807316992","39","United States"
"1636","TFI International","TFII","7807016960","85.23","Canada"
"1637","Petro Rabigh","2380.SR","7773625663","4.72","Saudi Arabia"
"1638","Yuanta Financial Holding","2885.TW","7768651957","0.64","Taiwan"
"1639","Cognex","CGNX","7759138816","44.66","United States"
"1640","Alcoa","AA","7757943296","42.06","United States"
"1641","CAE","CAE","7746366464","24.42","Canada"
"1642","Chubu Electric Power","9502.T","7738168029","10.23","Japan"
"1643","Cable One","CABO","7736752128","1291.01","United States"
"1644","LG Household & Health Care","051905.KS","7723371470","244.34","South Korea"
"1645","Manhattan Associates","MANH","7709629440","122.16","United States"
"1646","Pure Storage","PSTG","7702493184","26.02","United States"
"1647","DexCom","DXCM","7700670000","79.23","United States"
"1648","JD Sports Fashion","JD.L","7698195600","147.45","United Kingdom"
"1649","Lear Corporation","LEA","7689594368","128.64","United States"
"1650","Zions Bancorporation","ZION","7673901568","50.7","United States"
"1651","GAIL","GAIL.NS","7663286209","1.75","India"
"1652","Teva Pharmaceutical Industries","TEVA","7659096064","6.84","Israel"
"1653","Jardine Cycle & Carriage","C07.SI","7641023322","19.33","Singapore"
"1654","Sinopharm","1099.HK","7632930564","2.45","China"
"1655","ASUS","2357.TW","7628964919","10.27","Taiwan"
"1656","Webster Financial","WBS","7626199552","42.82","United States"
"1657","Regal Rexnord","RRX","7622420480","113.76","United States"
"1658","Novocure","NVCR","7612814848","72.79","Jersey"
"1659","ARC Resources","ARX.TO","7604524891","11.17","Canada"
"1660","Oracle Corp Japan","4716.T","7602290457","59.37","Japan"
"1661","ICICI Lombard","ICICIGI.NS","7600271651","15.48","India"
"1662","Ceridian","CDAY","7597141504","49.77","United States"
"1663","Confluent","CFLT","7586880000","27.26","United States"
"1664","Churchill Downs","CHDN","7549582336","198.54","United States"
"1665","Dentsply Sirona","XRAY","7541897728","35.01","United States"
"1666","China Oilfield Services","2883.HK","7541790995","0.93","China"
"1667","Mitsubishi Chemical Holdings","4188.T","7536800989","5.3","Japan"
"1668","Avalara","AVLR","7529575424","85.7","United States"
"1669","Universal Health Services","UHS","7525880320","101.18","United States"
"1670","Tetra Tech","TTEK","7525324800","140.18","United States"
"1671","KT&G (Korea Tobacco)","033780.KS","7523867621","62.71","South Korea"
"1672","Indus Towers","INDUSTOWER.NS","7515129586","2.79","India"
"1673","AGC","5201.T","7510722739","33.89","Japan"
"1674","TPG Telecom","TPG.AX","7502688028","3.99","Australia"
"1675","Becle","CUERVO.MX","7501366476","2.09","Mexico"
"1676","Performance Food Group","PFGC","7495896576","48.36","United States"
"1677","Cullen/Frost Bankers","CFR","7493580288","116.91","United States"
"1678","Sampoerna","HSZ.F","7492542102","0.06","Indonesia"
"1679","Commerzbank","CBK.F","7491998439","5.97","Germany"
"1680","Entain","ENT.L","7491819962","1247.49","Isle of Man"
"1681","HELLA","HLE.F","7490914204","65.76","Germany"
"1682","Qualtrics","XM","7488699392","12.86","United States"
"1683","Chemed","CHE","7486943744","500.2","United States"
"1684","Central Pattana","CPN.BK","7474478322","1.67","Thailand"
"1685","Meridian Energy","MEZ.AX","7472737084","2.87","New Zealand"
"1686","Samsung Electro-Mechanics","009155.KS","7469770876","55.9","South Korea"
"1687","Globant","GLOB","7461611520","178.61","Luxembourg"
"1688","Arrow Electronics","ARW","7455577600","112.9","United States"
"1689","STORE Capital","STOR","7451886080","26.56","United States"
"1690","West Fraser Timber","WFG","7417688064","82.93","Canada"
"1691","SEI Investments","SEIC","7413736448","54.01","United States"
"1692","Tencent Music","TME","7399023616","4.37","China"
"1693","Dolby","DLB","7387531776","73.22","United States"
"1694","Fisher & Paykel Healthcare","FPH.NZ","7386256024","12.79","New Zealand"
"1695","Magnit","MGNT.ME","7383510057","75.4","Russia"
"1696","Casey's General Stores","CASY","7362167808","197.97","United States"
"1697","Insurance Australia Group","IAG.AX","7348807679","2.98","Australia"
"1698","Meggitt","MGGT.L","7347825325","938.56","United Kingdom"
"1699","Syneos Health","SYNH","7344369664","71.6","United States"
"1700","Unimicron","3037.TW","7341446884","4.98","Taiwan"
"1701","Hess Midstream","HESM","7339876864","27.84","United States"
"1702","Fosun","0656.HK","7333350922","0.88","China"
"1703","Osaka Gas","9532.T","7332728689","17.64","Japan"
"1704","Singapore Exchange","S68.SI","7328224426","6.86","Singapore"
"1705","Change Healthcare","CHNG","7328150016","23.01","United States"
"1706","DiaSorin","DIA.MI","7328018405","135.19","Italy"
"1707","Hindustan Aeronautics","HAL.NS","7326986838","21.91","India"
"1708","Nissin Foods","2897.T","7326811561","71.89","Japan"
"1709","Konami Holdings","9766.T","7324033380","54.83","Japan"
"1710","Masimo","MASI","7318810112","131.86","United States"
"1711","Daifuku","6383.T","7315253637","58.05","Japan"
"1712","Trend Micro","4704.T","7313405194","52.34","Japan"
"1713","Shanghai Commercial and Savings Bank","5876.TW","7310285934","1.64","Taiwan"
"1714","FinecoBank","FBK.MI","7302008084","11.97","Italy"
"1715","Toast","TOST","7299408896","14.26","United States"
"1716","Ritchie Bros. Auctioneers","RBA","7298430464","65.91","Canada"
"1717","Rational AG","RAA.F","7293734741","625.94","Germany"
"1718","Meiji Holdings","2269.T","7277732600","51.68","Japan"
"1719","Avis Budget Group","CAR","7269411328","150.55","United States"
"1720","Sibanye-Stillwater","SBSW","7262510592","9.94","South Africa"
"1721","Indofood CBP","ICBP.JK","7257071270","0.62","Indonesia"
"1722","First Solar","FSLR","7254106624","68.06","United States"
"1723","SentinelOne","S","7250560512","25.99","United States"
"1724","Lincoln Electric","LECO","7249236992","123.66","United States"
"1725","Maravai LifeSciences","MRVI","7241498624","28.38","United States"
"1726","United Spirits","UNITDSPR.BO","7241261190","10.21","India"
"1727","Telus International","TIXT","7239633920","27.2","Canada"
"1728","WillScot","WSC","7234189824","32.51","United States"
"1729","Invesco","IVZ","7230347264","15.89","United States"
"1730","Rakuten","4755.T","7227569904","4.56","Japan"
"1731","Pilgrim's Pride","PPC","7226722816","30.07","United States"
"1732","Hero MotoCorp","HEROMOTOCO.NS","7226688110","36.17","India"
"1733","Deckers Brands","DECK","7215457280","269.34","United States"
"1734","WEX","WEX","7209920512","160.26","United States"
"1735","Jabil","JBL","7203755520","52.37","United States"
"1736","Olin","OLN","7202956800","47.44","United States"
"1737","Omega Healthcare","OHI","7188016640","29.75","United States"
"1738","Yanbu National Petrochemical","2290.SR","7186367175","12.78","Saudi Arabia"
"1739","Hainan Airlines","900945.SS","7170642944","0.19","China"
"1740","Ciena","CIEN","7152904192","47.78","United States"
"1741","US Foods","USFD","7151110656","31.94","United States"
"1742","Japan Airlines","9201.T","7143387321","16.35","Japan"
"1743","Gerdau","GGB","7142145536","4.18","Brazil"
"1744","Etihad Etisalat (Mobily)","7020.SR","7139507416","9.27","Saudi Arabia"
"1745","Indutrade","INDT.ST","7119296662","19.54","Sweden"
"1746","Bharat Electronics","BEL.NS","7117497991","2.92","India"
"1747","PKO Bank Polski","P9O.F","7114598580","5.6","Poland"
"1748","SKF (Svenska Kullagerfabriken)","SKF-B.ST","7109230090","15.45","Sweden"
"1749","Bâloise","BALN.SW","7108920710","157.45","Switzerland"
"1750","Apollo Hospitals","APOLLOHOSP.NS","7106603624","49.43","India"
"1751","Bank of Baroda","BANKBARODA.NS","7105838702","1.37","India"
"1752","Traton","8TRA.DE","7104072334","14.21","Germany"
"1753","Elastic NV","ESTC","7098194432","74.83","United States"
"1754","OTE Group","OTE.F","7097878910","15.88","Greece"
"1755","Phoenix Group","PHNX.L","7096174304","709.62","United Kingdom"
"1756","Berger Paints","BERGEPAINT.NS","7090545211","7.3","India"
"1757","ShockWave Medical","SWAV","7085364736","197.96","United States"
"1758","Royal Gold","RGLD","7085073920","107.94","United States"
"1759","Zoomlion","1157.HK","7054232600","0.55","China"
"1760","Motherson Sumi Systems","MOTHERSUMI.NS","7039944148","1.56","India"
"1761","Prysmian Group","PRY.MI","7023777657","26.66","Italy"
"1762","AGCO","AGCO","7017543680","94.14","United States"
"1763","Old Republic International","ORI","7010810368","22.74","United States"
"1764","Grupo Aeroportuario del Pacífico","PAC","7006988288","139.32","Mexico"
"1765","Quidel","QDEL","7000135168","104.59","United States"
"1766","PGNiG","7GG.F","6998561207","1.15","Poland"
"1767","Nemetschek","NEM.F","6997511465","59.95","Germany"
"1768","Idemitsu Kosan","5019.T","6996927139","23.53","Japan"
"1769","Indorama Ventures","I93A.F","6991415859","1.23","Thailand"
"1770","Dino Polska","DNP.WA","6989006553","71.29","Poland"
"1771","Sofina","SOF.VI","6988384531","207.94","Belgium"
"1772","Dick's Sporting Goods","DKS","6987756032","86.78","United States"
"1773","Mobile TeleSystems","MBT","6986429952","5.5","Russia"
"1774","Accor","AC.PA","6985480366","26.57","France"
"1775","Plains All American Pipeline","PAA","6981007360","9.94","United States"
"1776","Spring Airlines","601021.SS","6979264823","7.62","China"
"1777","Varun Beverages","VBL.NS","6972360665","10.73","India"
"1778","Robinhood","HOOD","6965351424","8.34","United States"
"1779","QNB Finansbank","QNBFB.IS","6961211883","2.08","Turkey"
"1780","Range Resources","RRC","6958064640","25.79","United States"
"1781","Samsara","IOT","6955699200","13.66","United States"
"1782","China Development Financial","2883.TW","6946629325","0.41","Taiwan"
"1783","Berry Global","BERY","6946293248","53.31","United States"
"1784","Sarepta Therapeutics","SRPT","6931829248","79.22","United States"
"1785","Bajaj Holdings & Investment","BAJAJHLDNG.NS","6918500441","62.16","India"
"1786","Bangkok Bank","BBL.BK","6909971015","3.62","Thailand"
"1787","Tokyu","9005.T","6909335995","11.47","Japan"
"1788","Cathay Pacific","0293.HK","6904825780","1.07","Hong Kong"
"1789","Sagax","SAGA-B.ST","6889612294","20.64","Sweden"
"1790","Middleby","MIDD","6887924224","126.64","United States"
"1791","MISC Berhad","3816.KL","6874168840","1.54","Malaysia"
"1792","Bancolombia","CIB","6857833472","28.52","Colombia"
"1793","Starwood Property Trust","STWD","6853733888","21.64","United States"
"1794","Zalando","ZAL.DE","6850421510","26.38","Germany"
"1795","Ivanhoe Mines","IVN.TO","6849753347","5.44","Canada"
"1796","Clearway Energy","CWEN","6849362944","34.99","United States"
"1797","Futu Holdings","FUTU","6841007616","46.54","Hong Kong"
"1798","United Tractors","UTY.F","6834905516","1.78","Indonesia"
"1799","Copenhagen Airport","KLH.F","6830854822","854.7","Denmark"
"1800","Elang Mahkota Teknologi","EMTK.JK","6818239310","0.11","Indonesia"
"1801","Ternium","TX","6805998080","34.67","Luxembourg"
"1802","Yamaha","7951.T","6793559099","39.6","Japan"
"1803","Pearson","PSO","6778295296","9.19","United Kingdom"
"1804","Banco Santander-Chile","BSAC","6774633984","14.38","Chile"
"1805","Nexstar Media Group","NXST","6774588928","167.67","United States"
"1806","ABB India","ABB.NS","6774337403","31.96","India"
"1807","Persimmon","PSN.L","6767511797","2119.36","United Kingdom"
"1808","Dexus","DXS.AX","6754576873","6.28","Australia"
"1809","CACI","CACI","6750817792","288.34","United States"
"1810","IAC/InterActiveCorp","IAC","6748615680","75.09","United States"
"1811","Halozyme Therapeutics","HALO","6745755136","48.9","United States"
"1812","Concentrix","CNXC","6741843968","129.54","United States"
"1813","Unum","UNM","6740704768","33.52","United States"
"1814","KBR","KBR","6739352576","48.29","United States"
"1815","Renault","RNO.PA","6731336849","23.2","France"
"1816","Hertz","HTZ","6729772544","16.33","United States"
"1817","Five Below","FIVE","6725955072","121.21","United States"
"1818","Levi Strauss","LEVI","6724302336","16.95","United States"
"1819","EastGroup Properties","EGP","6722254336","154.36","United States"
"1820","Procore","PCOR","6718552064","49.56","United States"
"1821","KT Corporation","KT","6704936960","14.2","South Korea"
"1822","Nippon Prologis REIT","3283.T","6704854476","2510.85","Japan"
"1823","Flex","FLEX","6703276032","14.63","Singapore"
"1824","Unibail-Rodamco-Westfield","URW.AS","6694862576","48.25","France"
"1825","Credit Acceptance","CACC","6691867136","509.29","United States"
"1826","DXC Technology","DXC","6689850368","29.13","United States"
"1827","AutoNation","AN","6689324032","114.69","United States"
"1828","Axon Enterprise","AXON","6686078464","94.16","United States"
"1829","Lufthansa","LHA.DE","6680078673","5.59","Germany"
"1830","Acadia Healthcare","ACHC","6679059968","73.78","United States"
"1831","Getinge","GETI-B.ST","6669309323","22.95","Sweden"
"1832","MinebeaMitsumi","6479.T","6668658964","16.42","Japan"
"1833","Nissan Chemical","4021.T","6662229953","47.14","Japan"
"1834","Gentex","GNTX","6662152704","28.42","United States"
"1835","Daiwa Securities Group","8601.T","6652368873","4.48","Japan"
"1836","Jefferies Financial Group","JEF","6643506688","28.58","United States"
"1837","Lodha Group","LODHA.NS","6640579114","13.79","India"
"1838","Planet Fitness","PLNT","6636835840","72.88","United States"
"1839","Atacadão","CRFB3.SA","6628580140","3.15","Brazil"
"1840","Shoprite","SHP.JO","6628522511","12.16","South Africa"
"1841","Rohm","6963.T","6623684189","67.49","Japan"
"1842","OCI","OCI.AS","6623057472","31.55","Netherlands"
"1843","Kakao Pay","377300.KS","6607407285","49.86","South Korea"
"1844","Coherent","COHR","6605557248","266.22","United States"
"1845","Inter & Co","INTR","6604856832","2.55","Brazil"
"1846","Exelixis","EXEL","6594434560","20.56","United States"
"1847","Great Eastern","G07.SI","6581823914","13.91","Singapore"
"1848","Healthcare Trust of America","HTA","6576714240","28.71","United States"
"1849","Auckland Airport","AIA.AX","6574795755","4.45","New Zealand"
"1850","Lattice Semiconductor","LSCC","6571613696","47.76","United States"
"1851","Wacker Chemie","WCH.F","6568785472","132.23","Germany"
"1852","AptarGroup","ATR","6563867136","100.1","United States"
"1853","FTI Consulting","FCN","6554144768","190.14","United States"
"1854","Southwestern Energy","SWN","6551976448","5.87","United States"
"1855","Five9","FIVN","6547438080","94.13","United States"
"1856","Arabian Internet and Communications Services","7202.SR","6545838423","55.1","Saudi Arabia"
"1857","Swedish Orphan Biovitrum","SOBI.ST","6544897571","22.17","Sweden"
"1858","Airtel Africa","AAF.L","6535408052","173.9","United Kingdom"
"1859","PLDT","PHI","6533372928","30.02","Philippines"
"1860","Makita","6586.T","6531540781","24.05","Japan"
"1861","RenaissanceRe","RNR","6531134464","147.8","Bermuda"
"1862","Apartment Income REIT","AIRC","6530522112","41.57","United States"
"1863","Autoliv","ALV","6511502848","74.55","Sweden"
"1864","Holmen","HOLM-B.ST","6500435649","40.22","Sweden"
"1865","CPFL Energia","CPFE3.SA","6499729863","5.64","Brazil"
"1866","Trex","TREX","6489189376","57.33","United States"
"1867","Origin Energy","ORG.AX","6486661010","3.77","Australia"
"1868","National Storage","NSA","6474109440","50.25","United States"
"1869","Murphy USA","MUSA","6473928192","267.5","United States"
"1870","Polaris","PII","6466761728","108.69","United States"
"1871","Ralph Lauren","RL","6446697984","92.48","United States"
"1872","Graphic Packaging","GPK","6443616256","20.9","United States"
"1873","Sanlam","SLM.JO","6423670230","3.13","South Africa"
"1874","UPL","UPL.NS","6421536986","8.56","India"
"1875","Restoration Hardware","RH","6421307904","260.17","United States"
"1876","Gecina","GFC.PA","6418259531","87.03","France"
"1877","TIS","3626.T","6414349128","26.1","Japan"
"1878","Hankyu Hanshin Holdings","9042.T","6411588217","26.61","Japan"
"1879","Cholamandalam Investment and Finance","CHOLAFIN.NS","6407254049","7.8","India"
"1880","Arkema","AKE.PA","6392182283","86.44","France"
"1881","CDK Global","CDK","6390491648","54.76","United States"
"1882","T&D Holdings","8795.T","6385589124","11.42","Japan"
"1883","PKN Orlen","PKY1.F","6380186707","14.62","Poland"
"1884","First Industrial Realty Trust","FR","6379608576","48.33","United States"
"1885","Japan Real Estate Investment","8952.T","6378129629","4604.45","Japan"
"1886","Israel Discount Bank","ISDAY","6378023936","51.56","Israel"
"1887","R1 RCM","RCM","6374476800","22.79","United States"
"1888","Hitachi Metals","5486.T","6372294057","14.9","Japan"
"1889","Woori Financial Group","WF","6370507264","26.25","South Korea"
"1890","Pershing Square Holdings","PSHZF","6367568384","29.53","United States"
"1891","Sensata Technologies","ST","6362240000","40.55","United States"
"1892","Axfood","AXFO.ST","6361844331","28.93","Sweden"
"1893","AngloGold Ashanti","AU","6357632000","14.48","South Africa"
"1894","Prosperity Bancshares","PB","6346290688","68.85","United States"
"1895","Coty","COTY","6344283648","7.56","United States"
"1896","Vipshop","VIPS","6341003264","9.67","China"
"1897","Japan Post Insurance","7181.T","6335035439","15.86","Japan"
"1898","Western Union","WU","6325167104","16.39","United States"
"1899","Siam Commercial Bank","NVPI.F","6323279799","1.86","Thailand"
"1900","Torrent Pharmaceuticals","TORNTPHARM.NS","6314662651","18.66","India"
"1901","Banco Santander México","BSMX","6306609152","4.65","Mexico"
"1902","Choice Hotels International","CHH","6302801408","113.02","United States"
"1903","NextEra Energy Partners","NEP","6300876288","75.1","United States"
"1904","Amorepacific","090430.KS","6296771396","99.42","South Korea"
"1905","Hamamatsu","6965.T","6279345644","40.55","Japan"
"1906","Dun & Bradstreet","DNB","6272470016","14.45","United States"
"1907","HashiCorp","HCP","6268133888","34","United States"
"1908","UnipolSai","US.MI","6266451660","2.22","Italy"
"1909","ENGIE Brasil","EGIE3.SA","6264316880","7.68","Brazil"
"1910","Korean Air Lines","003495.KS","6262805863","24.13","South Korea"
"1911","Avast","AV2.F","6262734576","6.01","Czech Republic"
"1912","Dongfeng Motor","0489.HK","6256482208","0.73","China"
"1913","Affirm","AFRM","6252767232","21.83","United States"
"1914","Wynn Resorts","WYNN","6249353728","53.89","United States"
"1915","II-VI Incorporated","IIVI","6249213440","48.43","United States"
"1916","Bath & Body Works","BBWI","6249067520","27.32","United States"
"1917","International Consolidated Airlines","BABWF","6240389632","1.26","Spain"
"1918","Envista","NVST","6239652352","38.37","United States"
"1919","Teladoc Health","TDOC","6234558976","38.68","United States"
"1920","Tata Elxsi","TATAELXSI.NS","6233279253","100.09","India"
"1921","Genting Singapore","G13.SI","6225335856","0.52","Singapore"
"1922","ZOZO","3092.T","6224016135","20.76","Japan"
"1923","Guidewire Software","GWRE","6223367680","74.25","United States"
"1924","Orion Corporation","ORNAV.HE","6221763765","44.24","Finland"
"1925","Bumble","BMBL","6219173888","33.69","United States"
"1926","Investec","INVR.L","6211083569","704.28","United Kingdom"
"1927","Info Edge","NAUKRI.NS","6210562805","48.15","India"
"1928","FAW Car","000800.SZ","6188283336","1.32","China"
"1929","Skanska","SKA-B.ST","6183449587","14.99","Sweden"
"1930","Huntsman Corporation","HUN","6176453120","29.44","United States"
"1931","Yamaha Motor","7272.T","6171587141","18.18","Japan"
"1932","Bid Corp","BID.JO","6171544204","18.47","South Africa"
"1933","Brookfield Renewable","BEPC","6169135104","35.82","United States"
"1934","Endeavor Group","EDR","6168892416","21.72","United States"
"1935","Wyndham Hotels & Resorts","WH","6162857984","66.92","United States"
"1936","Medibank","MPL.AX","6162197753","2.24","Australia"
"1937","UWM Holdings","UWMC","6155827200","3.84","United States"
"1938","POSCO Chemical","003670.KS","6154962401","79.53","South Korea"
"1939","Kongsberg Gruppen","KOG.OL","6134975536","34.57","Norway"
"1940","Kilroy Realty","KRC","6130262528","52.01","United States"
"1941","Korea Zinc","010130.KS","6129647729","346.81","South Korea"
"1942","Charoen Pokphand Indonesia","CPIN.JK","6128048043","0.37","Indonesia"
"1943","BOSCH India","BOSCHLTD.NS","6127683771","207.69","India"
"1944","Brixmor Property Group","BRX","6117982208","20.43","United States"
"1945","Beijer Ref","BEIJ-B.ST","6108584646","14.5","Sweden"
"1946","Daito Trust Construction","1878.T","6104857063","89.53","Japan"
"1947","Sumitomo Chemical","4005.T","6103894702","3.73","Japan"
"1948","Stockland","SGP.AX","6099846100","2.56","Australia"
"1949","ADT","ADT","6090457088","6.72","United States"
"1950","ENKA","ENKAI.IS","6090305722","1.04","Turkey"
"1951","Adaro Energy","ADRO.JK","6080205827","0.19","Indonesia"
"1952","Grupo ACS","ACS.MC","6077484790","21.58","Spain"
"1953","Covestro","1COV.F","6074775232","31.44","Germany"
"1954","TIM S.A.","TIMB","6068154368","12.36","Brazil"
"1955","Vornado Realty Trust","VNO","6058548224","29.41","United States"
"1956","Frontier Communications","FYBR","6057934848","24.73","United States"
"1957","Voya Financial","VOYA","6056933888","59.28","United States"
"1958","Pandora","3P7.F","6055758898","65.18","Denmark"
"1959","Capri Holdings","CPRI","6050817024","42.37","United Kingdom"
"1960","RaiaDrogasil","RADL3.SA","6048463474","3.67","Brazil"
"1961","Page Industries","PAGEIND.NS","6044784542","541.94","India"
"1962","Merdeka Copper Gold","MDKA.JK","6031606762","0.25","Indonesia"
"1963","Donaldson","DCI","6004461056","48.87","United States"
"1964","NOV","NOV","6001953792","15.28","United States"
"1965","Fresnillo","FNLPF","6001483264","7.92","Mexico"
"1966","Sekisui Chemical","4204.T","5998992579","13.73","Japan"
"1967","Littelfuse","LFUS","5995547648","242.36","United States"
"1968","Whitbread","WTB.L","5993764281","2966.87","United Kingdom"
"1969","AGNC Investment","AGNC","5992472064","11.45","United States"
"1970","DCP Midstream","DCP","5991782400","28.75","United States"
"1971","Française des Jeux","FDJ.VI","5988643395","31.37","France"
"1972","First American","FAF","5973329408","55.62","United States"
"1973","Jabal Omar Development","4250.SR","5972804399","6.43","Saudi Arabia"
"1974","GEA Group","G1A.F","5971306956","33.11","Germany"
"1975","Reece Group","REH.AX","5969445830","9.24","Australia"
"1976","Nedbank","NED.JO","5968057256","12.09","South Africa"
"1977","Rightmove","3JDA.F","5967868911","6.79","United Kingdom"
"1978","M&G plc","MNG.L","5964617119","231.64","United Kingdom"
"1979","Informatica","INFA","5944803328","21.23","United States"
"1980","TopBuild","BLD","5942305280","181.29","United States"
"1981","National Fuel Gas","NFG","5940505088","64.96","United States"
"1982","Indian Railway Catering & Tourism","IRCTC.NS","5939024619","7.42","India"
"1983","Itochu Techno-Solutions","4739.T","5937274836","25.69","Japan"
"1984","Leonardo","LDO.MI","5926616487","10.3","Italy"
"1985","Sainsbury's","SBRY.L","5922772961","252.71","United Kingdom"
"1986","Mindtree","MINDTREE.NS","5921531153","35.89","India"
"1987","Hualan Biological Engineering","002007.SZ","5919808795","3.24","China"
"1988","Kingfisher","KFI1.F","5916239541","2.93","United Kingdom"
"1989","H&R Block","HRB","5916149760","37.07","United States"
"1990","AltaGas","ALA.TO","5913716405","21.07","Canada"
"1991","SailPoint","SAIL","5912243712","62.67","United States"
"1992","Sinopac Financial Holdings","2890.TW","5911085965","0.52","Taiwan"
"1993","LEG Immobilien","LEG.DE","5907843668","79.18","Germany"
"1994","Centrica","CNA.L","5899916176","99.87","United Kingdom"
"1995","Banco Popular","BPOP","5896886784","77.01","United States"
"1996","Cosan","CSAN","5890811392","12.61","Brazil"
"1997","Stifel","SF","5887846400","55.25","United States"
"1998","GlobalWafers","6488.TWO","5885128847","13.52","Taiwan"
"1999","Washington H. Soul Pattinson and Company (WHSP)","SOL.AX","5868505720","16.26","Australia"
"2000","Saudi Kayan Petrochemical Company","2350.SR","5866993431","3.91","Saudi Arabia"
"2001","FS KKR Capital","FSK","5864950784","20.65","United States"
"2002","Clariant","CLN.SW","5862227929","17.81","Switzerland"
"2003","Cemex","CX","5859665920","3.81","Mexico"
"2004","Megacable Holdings","MEGACPO.MX","5852535964","2.28","Mexico"
"2005","Hulic","3003.T","5852175948","7.68","Japan"
"2006","Chart Industries","GTLS","5849596416","159.76","United States"
"2007","Zomato","ZOMATO.NS","5848085056","0.74","India"
"2008","Dutch Bros","BROS","5840140288","35.68","United States"
"2009","Temenos","TEMN.SW","5833099430","81.41","Switzerland"
"2010","Reynolds Consumer","REYN","5832093184","27.79","United States"
"2011","Mapletree Logistics Trust","M44U.SI","5824010379","1.22","Singapore"
"2012","Datto","MSP","5821586432","35.18","United States"
"2013","Tenet Healthcare","THC","5810040320","53.94","United States"
"2014","Flowers Foods","FLO","5803589632","27.37","United States"
"2015","RBC Bearings","ROLL","5803556352","200.95","United States"
"2016","Yuhan","000100.KS","5798557863","43.9","South Korea"
"2017","GPT Group","GPT.AX","5788306924","3.02","Australia"
"2018","First Financial Bankshares","FFIN","5785828864","40.54","United States"
"2019","Metso Outotec (Mo Group)","MOCORP.HE","5781122510","6.98","Finland"
"2020","Land Securities Group","LAND.L","5778349268","779.28","United Kingdom"
"2021","Kintetsu GHD","9041.T","5777561324","30.38","Japan"
"2022","Southwest Gas","SWX","5775344128","86.39","United States"
"2023","Globus Medical","GMED","5760262144","56.62","United States"
"2024","CCC Intelligent Solutions","CCCS","5759926272","9.37","United States"
"2025","Skechers","SKX","5758817280","36.97","United States"
"2026","GMO Payment Gateway","3769.T","5757302334","75.91","Japan"
"2027","HelloFresh","HFG.DE","5743172215","33.06","Germany"
"2028","Fastighets AB Balder","BALD-B.ST","5738583994","5.13","Sweden"
"2029","Charoen Pokphand Foods","CPF.BK","5734081719","0.72","Thailand"
"2030","BOC Aviation","2588.HK","5733493113","8.26","Singapore"
"2031","Klépierre","LI.PA","5732071932","20.09","France"
"2032","Mineral Resources","MIN.AX","5731154530","30.29","Australia"
"2033","Ingredion","INGR","5729319424","86.52","United States"
"2034","Bandhan Bank","BANDHANBNK.NS","5721274120","3.55","India"
"2035","Tomra","TOM.OL","5719903950","19.34","Norway"
"2036","Procter & Gamble India","PGHH.NS","5717836094","176.15","India"
"2037","RTL Group","RRTL.F","5716700090","36.94","Luxembourg"
"2038","NCsoft","036570.KS","5712717641","273.78","South Korea"
"2039","South State Corp","SSB","5697652736","75.49","United States"
"2040","MOL Group","MOL.BD","5695291712","7.02","Hungary"
"2041","Paytm","PAYTM.NS","5691954452","8.77","India"
"2042","Sonoco","SON","5682067456","58.28","United States"
"2043","Taishin Financial Holdings","2887.TW","5677745324","0.5","Taiwan"
"2044","CRISPR Therapeutics","CRSP","5668311040","73.18","Switzerland"
"2045","Spark New Zealand","NZTCF","5664342528","3.03","New Zealand"
"2046","Azenta","AZTA","5659029504","75.47","United States"
"2047","Otsuka","4768.T","5655846191","29.83","Japan"
"2048","FirstService","FSV","5653104640","127.92","Canada"
"2049","Perrigo","PRGO","5649838592","41.99","Ireland"
"2050","SiteOne Landscape Supply","SITE","5643245568","125.6","United States"
"2051","Bausch + Lomb","BLCO","5631071232","16.08","Canada"
"2052","Barratt Developments","BDEV.L","5621652767","549.04","United Kingdom"
"2053","Delhivery","DELHIVERY.NS","5615471747","7.75","India"
"2054","Capcom","9697.T","5610703986","26.28","Japan"
"2055","EVA Air","2618.TW","5607812036","1.06","Taiwan"
"2056","XPO Logistics","XPO","5600318464","48.69","United States"
"2057","Toll Brothers","TOL","5599379968","48.7","United States"
"2058","Woodward","WWD","5592691200","92.22","United States"
"2059","Agree Realty","ADC","5589313024","74.01","United States"
"2060","Balkrishna Industries","BALKRISIND.NS","5588122494","28.91","India"
"2061","Grupo Aeroportuario del Sureste","ASR","5581799936","186.06","Mexico"
"2062","Allegro.eu","ALE.WA","5568354194","5.44","Poland"
"2063","TMX Group","X.TO","5564062491","99.57","Canada"
"2064","STAG Industrial","STAG","5549997056","30.31","United States"
"2065","Celsius Holdings","CELH","5545866752","73.59","United States"
"2066","Shell Midstream Partners","SHLX","5545389056","14.1","United States"
"2067","WESCO International","WCC","5545254400","109.34","United States"
"2068","Descartes Systems","DSGX","5542297088","63.32","Canada"
"2069","Elm Company","7203.SR","5541600000","69.27","Saudi Arabia"
"2070","ITT","ITT","5537302528","66.32","United States"
"2071","Tenable","TENB","5531311616","50.02","United States"
"2072","Boyd Gaming","BYD","5530704384","50.47","United States"
"2073","Northern Star","NST.AX","5529591347","4.6","Australia"
"2074","Commercial International Bank","CIN1.F","5525632531","2.06","Egypt"
"2075","TOTO","5332.T","5523027448","32.58","Japan"
"2076","Kobe Bussan","3038.T","5521861677","25.33","Japan"
"2077","GLP J-REIT","3281.T","5518993305","1229.07","Japan"
"2078","Mirvac Group","MGR.AX","5517578920","1.4","Australia"
"2079","Dai Nippon Printing","7912.T","5515766566","20.58","Japan"
"2080","Nomura Real Estate Master Fund","3462.T","5512319626","1202.72","Japan"
"2081","Ashland","ASH","5505043456","101.71","United States"
"2082","Treasury Wine Estates","TWE.AX","5504255429","7.63","Australia"
"2083","MKS Instruments","MKSI","5502488064","98.86","United States"
"2084","Saia","SAIA","5498228736","208.2","United States"
"2085","OTP Bank","OTP.F","5493497951","19.67","Hungary"
"2086","MDU Resources","MDU","5488443904","26.99","United States"
"2087","Rayonier","RYN","5483023360","36.65","United States"
"2088","Spirit Realty Capital","SRC","5481109504","40.81","United States"
"2089","Pinnacle Financial Partners","PNFP","5478361088","71.72","United States"
"2090","MasTec","MTZ","5478177792","72.05","United States"
"2091","KION Group","KGX.DE","5461594868","41.66","Germany"
"2092","Landstar System","LSTR","5457341952","146.99","United States"
"2093","On Holding","ONON","5454020096","17.34","Switzerland"
"2094","Square Enix","9684.T","5445863959","45.53","Japan"
"2095","CyberArk","CYBR","5435625984","133.5","Israel"
"2096","Sotera Health","SHC","5432913920","19.21","United States"
"2097","Kajima","1812.T","5424778855","11","Japan"
"2098","Inspire Medical Systems","INSP","5419168256","196.41","United States"
"2099","Qantas Airways","QAN.AX","5417987946","2.87","Australia"
"2100","GDS Holdings","GDS","5412130816","27.48","China"
"2101","PI Industries","PIIND.NS","5403216240","35.63","India"
"2102","Houlihan Lokey","HLI","5400423424","78.5","United States"
"2103","Lumentum","LITE","5397870080","78.23","United States"
"2104","Ampol","ALD.AX","5396550260","22.65","Australia"
"2105","United Breweries","UBL.NS","5388164259","20.38","India"
"2106","Realtek","2379.TW","5387974565","10.51","Taiwan"
"2107","Unite Group (Unite Students)","UTG.L","5383594585","1341.99","United Kingdom"
"2108","SCSK Corporation","9719.T","5379269168","17.23","Japan"
"2109","Texas Roadhouse","TXRH","5379137024","78.91","United States"
"2110","Oak Street Health","OSH","5375949824","22.3","United States"
"2111","Brunswick Corporation","BC","5373793792","70.96","United States"
"2112","Playtika","PLTK","5373545984","13.03","Israel"
"2113","Koei Tecmo","3635.T","5372097517","34.11","Japan"
"2114","10x Genomics","TXG","5365897216","47.33","United States"
"2115","Idacorp","IDA","5360033792","106.02","United States"
"2116","Toppan","7911.T","5351560757","16.05","Japan"
"2117","Trent Limited","TRENT.NS","5348983446","15.04","India"
"2118","Alfamart","AMRT.JK","5348166687","0.13","Indonesia"
"2119","Mimecast","MIME","5346544128","79.92","United Kingdom"
"2120","Seek Limited","SEK.AX","5343844337","14.36","Australia"
"2121","Glacier Bancorp","GBCI","5335453696","48.17","United States"
"2122","Valley Bank","VLY","5331391488","10.53","United States"
"2123","Coca-Cola Consolidated","COKE","5330267136","579.29","United States"
"2124","ASR Nederland","ASRNL.AS","5329311469","39.25","Netherlands"
"2125","Rumo","RAIL3.SA","5327313960","2.88","Brazil"
"2126","Oshkosh Corporation","OSK","5325439488","80.94","United States"
"2127","ZIM Integrated Shipping Services","ZIM","5324447232","44.39","Israel"
"2128","AMN Healthcare Services","AMN","5318022656","118.92","United States"
"2129","Sabesp","SBS","5317708288","7.78","Brazil"
"2130","Option Care Health","OPCH","5315134976","29.52","United States"
"2131","Valvoline","VVV","5304954368","29.77","United States"
"2132","Selective Insurance","SIGI","5304761856","87.9","United States"
"2133","“K” Line","9107.T","5303173583","56.37","Japan"
"2134","Atlas Arteria","ALX.AX","5303026588","5.53","Australia"
"2135","Ashok Leyland","ASHOKLEY.NS","5294498426","1.8","India"
"2136","X5 Retail Group","FIVE.ME","5292727990","19.49","Netherlands"
"2137","iA Financial","IAG.TO","5277396132","49.03","Canada"
"2138","Synovus","SNV","5270791168","36.27","United States"
"2139","PDC Energy","PDCE","5268898816","53.08","United States"
"2140","RLI Corp.","RLI","5266851840","116.23","United States"
"2141","Colgate-Palmolive India","COLPAL.NS","5259703137","19.33","India"
"2142","Emcor","EME","5257898496","102.81","United States"
"2143","Convatec Group","CTEC.L","5251897101","257.22","United Kingdom"
"2144","nVent Electric","NVT","5243257856","31.52","United Kingdom"
"2145","Alaska Airlines","ALK","5240383488","41.56","United States"
"2146","Telecom Italia","TIT.MI","5232328012","0.25","Italy"
"2147","Kosé","4922.T","5228665461","91.65","Japan"
"2148","MP Materials","MP","5225507328","29.44","United States"
"2149","Hyundai Glovis","086280.KS","5220539983","136.51","South Korea"
"2150","Barito Pacific","OB8.F","5219346019","0.04","Indonesia"
"2151","Mandiant","MNDT","5217666048","22.12","United States"
"2152","SAIC","SAIC","5217562624","93.7","United States"
"2153","Koç Holding","KCHOL.IS","5212080720","2.06","Turkey"
"2154","Acuity Brands","AYI","5209234432","159.24","United States"
"2155","Industrial Bank of Korea (IBK)","024110.KS","5208206012","7","South Korea"
"2156","Ginkgo Bioworks","DNA","5205555200","2.93","United States"
"2157","Abbott India","ABBOTINDIA.NS","5204939102","244.8","India"
"2158","Saudi Investment Bank","1030.SR","5200895236","5.2","Saudi Arabia"
"2159","Hanover Insurance Group","THG","5195848704","145.99","United States"
"2160","Erdemir","EREGL.IS","5192630325","1.53","Turkey"
"2161","Kinsale Capital Group","KNSL","5190494720","226.58","United States"
"2162","Sunrun","RUN","5187689984","24.69","United States"
"2163","Groupe SEB","SK.PA","5186068851","94.37","France"
"2164","Ionis Pharmaceuticals","IONS","5182716928","36.55","United States"
"2165","PS Business Parks","PSB","5177590784","187.38","United States"
"2166","Matador Resources","MTDR","5167968768","43.75","United States"
"2167","Nan Ya PCB","8046.TW","5164390971","7.99","Taiwan"
"2168","Container Corporation of India","CONCOR.NS","5163534410","8.47","India"
"2169","Omnicell","OMCL","5149090304","116.5","United States"
"2170","Gland Pharma","GLAND.NS","5148968749","31.27","India"
"2171","Gildan","GIL","5148507648","26.7","Canada"
"2172","BOK Financial","BOKF","5143214080","75.52","United States"
"2173","Axalta","AXTA","5138057728","23.2","United States"
"2174","United Internet","UTDI.F","5135972135","27.01","Germany"
"2175","Piramal Group","PEL.NS","5134211445","21.51","India"
"2176","Quebecor","QBR-B.TO","5133172220","21.43","Canada"
"2177","EXL Service","EXLS","5132731904","154.2","United States"
"2178","BWX Technologies","BWXT","5127771136","56.23","United States"
"2179","Muthoot Finance","MUTHOOTFIN.NS","5126253950","12.77","India"
"2180","Mphasis","MPHASIS.NS","5121211070","27.23","India"
"2181","Bombardier Recreational Products","DOOO","5119842816","65.13","Canada"
"2182","ACC","ACC.NS","5118747330","27.26","India"
"2183","Ubisoft","UBI.PA","5118254206","41.14","France"
"2184","Turquoise Hill Resources","TRQ","5115258880","24.36","Canada"
"2185","American National Insurance","ANAT","5109105664","190.02","United States"
"2186","KOBAYASHI Pharmaceutical","4967.T","5108344936","66.1","Japan"
"2187","Post Holdings","POST","5100125184","83.96","United States"
"2188","Intra-Cellular Therapies","ITCI","5097285632","54.04","United States"
"2189","Bright Horizons","BFAM","5088478208","85.66","United States"
"2190","DWS Group","DWS.F","5083655980","25.04","Germany"
"2191","Curtiss-Wright","CW","5082097664","132.19","United States"
"2192","Obayashi","1802.T","5074692052","7.08","Japan"
"2193","Magnolia Oil & Gas","MGY","5073658368","19.15","United States"
"2194","Crane Co.","CR","5072986624","90.5","United States"
"2195","TVS Motor","TVSMOTOR.NS","5072163754","10.68","India"
"2196","Terminix Global","TMX","5070320128","41.73","United States"
"2197","Santander Polska","BZI.F","5069079554","48.69","Poland"
"2198","Covivio","COV.PA","5052763511","53.9","France"
"2199","Alkermes","ALKS","5052136960","30.78","Ireland"
"2200","Enagás","ENG.MC","5047526130","19.32","Spain"
"2201","COSCO SHIPPING Development","601866.SS","5044811340","0.44","China"
"2202","Mapletree Industrial Trust","ME8U.SI","5028539953","1.87","Singapore"
"2203","HealthEquity","HQY","5024518144","59.56","United States"
"2204","Qualys","QLYS","5024355840","129.38","United States"
"2205","Euronet Worldwide","EEFT","5023455744","99.38","United States"
"2206","Jarir","4190.SR","5019716645","41.83","Saudi Arabia"
"2207","Bechtle","BC8.F","5015046950","38.36","Germany"
"2208","Endava","DAVA","5013929984","89.54","United Kingdom"
"2209","Braskem","BAK","5008943616","12.57","Brazil"
"2210","Novavax","NVAX","5006865408","64.08","United States"
"2211","DraftKings","DKNG","4999223808","11.43","United States"
"2212","Discovery Limited","DSY.JO","4997401484","7.56","South Africa"
"2213","Owl Rock Capital","ORCC","4997368320","12.67","United States"
"2214","Marriott Vacations Worldwide","VAC","4996504064","120.6","United States"
"2215","Ascendis Pharma","ASND","4994980352","89.51","Denmark"
"2216","Universal Display Corporation","OLED","4993856512","105.77","United States"
"2217","TriNet","TNET","4993131520","80.2","United States"
"2218","British Land","BLDA.F","4986823883","5.38","United Kingdom"
"2219","Penn National Gaming","PENN","4981655040","29.87","United States"
"2220","CTS Eventim","EVD.F","4975717937","51.84","Germany"
"2221","Cabot Microelectronics","CCMP","4969444864","173.69","United States"
"2222","Keyera","KEY.TO","4969002983","22.48","Canada"
"2223","Sharp Corporation","6753.T","4961848772","7.64","Japan"
"2224","Apellis Pharmaceuticals","APLS","4955403264","46.52","United States"
"2225","DAQO New Energy","DQ","4951355904","66.46","China"
"2226","Mercury NZ","MCY.AX","4950822989","3.58","New Zealand"
"2227","Canara Bank","CANBK.NS","4948996089","2.73","India"
"2228","CyberAgent","4751.T","4943289026","9.78","Japan"
"2229","Stantec","STN","4940787712","44.6","Canada"
"2230","Savola Group","2050.SR","4938134959","9.26","Saudi Arabia"
"2231","Chemours","CC","4937695232","31.76","United States"
"2232","HYBE","352820.KS","4933490277","119.3","South Korea"
"2233","OneMain Financial","OMF","4930183168","39.38","United States"
"2234","City Developments","C09.SI","4915417415","5.42","Singapore"
"2235","Nanya Technology","2408.TW","4914333610","1.59","Taiwan"
"2236","MSA Safety","MSA","4902040064","124.62","United States"
"2237","Wintrust Financial","WTFC","4901893632","80.73","United States"
"2238","RingCentral","RNG","4900553216","51.64","United States"
"2239","Biocon","BIOCON.NS","4899314498","4.08","India"
"2240","Medpace","MEDP","4898356224","152.76","United States"
"2241","Offcn Education","002607.SZ","4897600814","0.79","China"
"2242","New York Times","NYT","4896395776","29.37","United States"
"2243","Vonage Holdings Corp.","VG","4895584768","19.08","United States"
"2244","Penumbra","PEN","4894320128","129.9","United States"
"2245","GXO Logistics","GXO","4890125312","41.23","United States"
"2246","Leggett & Platt","LEG","4889631744","36.61","United States"
"2247","Endeavour Mining","EDV.TO","4886655668","19.25","United Kingdom"
"2248","LHC Group","LHCG","4884070400","157.41","United States"
"2249","Rogers Corporation","ROG","4874969600","259.26","United States"
"2250","Gelsenwasser","WWG.F","4873680378","1417.8","Germany"
"2251","Iridium Communications","IRDM","4871375872","38.06","United States"
"2252","Mapfre","MAP.MC","4870921911","1.58","Spain"
"2253","Hanwha Solutions","009830.KS","4867695064","25.47","South Korea"
"2254","IPG Photonics","IPGP","4866168320","93.81","United States"
"2255","Komerční banka","KONN.F","4865249496","25.76","Czech Republic"
"2256","McDonald's Japan","2702.T","4861612131","36.56","Japan"
"2257","Nippon Express","9147.T","4861333402","53.66","Japan"
"2258","Falabella","FALABELLA.SN","4856128420","1.94","Chile"
"2259","Exponent","EXPO","4855165952","93.69","United States"
"2260","Colliers International","CIGI","4853089280","112.37","Canada"
"2261","SoFi","SOFI","4845757952","6.06","United States"
"2262","Odakyu Electric Railway","9007.T","4835752163","13.31","Japan"
"2263","Tube Investments of India","TIINDIA.NS","4833998993","25.05","India"
"2264","Weibo","WB","4830729216","20.2","China"
"2265","Nuvei","NVEI","4823290368","31.63","Canada"
"2266","Soitec","SOI.PA","4822940638","136.9","France"
"2267","Harley-Davidson","HOG","4813365248","32.66","United States"
"2268","Sanderson Farms","SAFM","4813350912","215.65","United States"
"2269","Thoughtworks","TWKS","4813140480","15.51","United States"
"2270","Blackstone Mortgage Trust","BXMT","4808876544","28.24","United States"
"2271","HealthSouth","EHC","4805211648","48.15","United States"
"2272","JSW Energy","JSWENERGY.NS","4801996740","2.93","India"
"2273","Ruchi Soya","RUCHI.NS","4800975470","13.27","India"
"2274","Lynas","LYI.F","4800024969","5.03","Malaysia"
"2275","United Bankshares","UBSI","4798807552","35.47","United States"
"2276","Jubilant FoodWorks","JUBLFOOD.NS","4798540579","7.27","India"
"2277","Eurazeo","RF.PA","4786145625","62.44","France"
"2278","Valmont Industries","VMI","4786114048","224.58","United States"
"2279","BlueScope Steel","BSL.AX","4784596563","10.17","Australia"
"2280","Novatek Microelectronics","3034.TW","4781879668","7.86","Taiwan"
"2281","Worley","WOR.AX","4770135756","9.09","Australia"
"2282","Bank AlJazira","1020.SR","4767238384","5.81","Saudi Arabia"
"2283","Louisiana-Pacific","LPX","4767071744","58.42","United States"
"2284","Intermediate Capital Group (ICG)","ICP.L","4767048699","1621.91","United Kingdom"
"2285","Clean Harbors","CLH","4746805248","87.21","United States"
"2286","Mazda","7261.T","4744501554","7.53","Japan"
"2287","Lechwerke","LEC.F","4740203085","133.74","Germany"
"2288","ERG","ERG.MI","4736296543","31.81","Italy"
"2289","Guardant Health","GH","4725150208","46.36","United States"
"2290","Columbia Sportswear","COLM","4718931968","75.06","United States"
"2291","Cemig","CIG","4717636096","1.93","Brazil"
"2292","Paycor","PYCR","4712075264","26.94","United States"
"2293","Wayfair","W","4711031808","50.11","United States"
"2294","Kingsoft","3888.HK","4710582108","3.46","China"
"2295","Rockwool","R90.F","4709838834","217.6","Denmark"
"2296","Dechra Pharmaceuticals","DPH.L","4709236377","4210.2","United Kingdom"
"2297","World Wrestling Entertainment","WWE","4708281856","63.33","United States"
"2298","Norwegian Cruise Line","NCLH","4693428224","11.2","United States"
"2299","Marqeta","MQ","4687636992","8.61","United States"
"2300","Yancoal","YAL.AX","4687065288","3.52","Australia"
"2301","HomeServe","HSV.L","4684410807","1391.39","United Kingdom"
"2302","Black Hills","BKH","4676568064","72.13","United States"
"2303","ASGN","ASGN","4669517824","91.38","United States"
"2304","AXIS Capital","AXS","4664280064","54.69","Bermuda"
"2305","Driven Brands","DRVN","4660072448","27.82","United States"
"2306","Hargreaves Lansdown","HL.L","4659582803","977.31","United Kingdom"
"2307","DS Smith","SMDS.L","4657589369","338.41","United Kingdom"
"2308","Coupa","COUP","4654306816","61.61","United States"
"2309","Topicus","TOI.V","4651137791","58.19","Canada"
"2310","Hikari Tsushin","9435.T","4648351828","103.73","Japan"
"2311","Alkem Laboratories","ALKEM.NS","4647227005","38.87","India"
"2312","Welcia Holdings","3141.T","4646974971","21.91","Japan"
"2313","Douglas Emmett","DEI","4629547520","22.41","United States"
"2314","Independence Realty Trust","IRT","4627657728","20.29","United States"
"2315","monday.com","MNDY","4626013184","105.81","Israel"
"2316","Lundbeck","LDB.F","4620411560","23.15","Denmark"
"2317","Tobu Railway","9001.T","4619642677","22.14","Japan"
"2318","Macy's","M","4616480256","17.12","United States"
"2319","DT Midstream","DTM","4614212096","47.7","United States"
"2320","Rexel","RXL.PA","4613460819","15.14","France"
"2321","Richter Gedeon","RGEDF","4610442240","24.81","Hungary"
"2322","Proximus","PROX.VI","4608267712","14.28","Belgium"
"2323","Cadila Healthcare","CADILAHC.NS","4603836898","4.5","India"
"2324","National Beverage","FIZZ","4600640000","49.29","United States"
"2325","Primerica","PRI","4598443520","119.5","United States"
"2326","Reply","REY.MI","4592011391","122.98","Italy"
"2327","U.S. Steel","X","4587176448","17.6","United States"
"2328","Argo Investments","ARG.AX","4584055442","6.11","Australia"
"2329","IDP Education","IEL.AX","4581546494","16.46","Australia"
"2330","ZhongAn Insurance","6060.HK","4578083675","3.11","China"
"2331","Banca Mediolanum","BMED.MI","4576060364","6.21","Italy"
"2332","AU Small Finance Bank","AUBANK.NS","4573342396","7.26","India"
"2333","Synaptics","SYNA","4569934336","115.38","United States"
"2334","Yamana Gold","AUY","4569740288","4.76","Canada"
"2335","Equatorial Energia","EQTL3.SA","4562086198","4.15","Brazil"
"2336","Godrej Properties","GODREJPROP.NS","4548951033","16.36","India"
"2337","Silicon Labs","SLAB","4546968576","124.3","United States"
"2338","Chord Energy","CHRD","4540237312","107.37","United States"
"2339","Wärtsilä","WRT1V.HE","4537451600","7.69","Finland"
"2340","Ultragenyx","RARE","4533575168","64.83","United States"
"2341","Schaeffler India","SCHAEFFLER.NS","4530787025","28.99","India"
"2342","Hexcel","HXL","4526582272","53.86","United States"
"2343","Bank OZK","OZK","4513997312","37.58","United States"
"2344","Italgas","IG.MI","4509701148","5.54","Italy"
"2345","Simpson Manufacturing Company","SSD","4507188224","104.43","United States"
"2346","Lantheus Holdings","LNTH","4506514944","65.66","United States"
"2347","Universal Forest Products","UFPI","4505570304","71.82","United States"
"2348","Lundin Mining","LUN.TO","4504049772","5.78","Canada"
"2349","Intellia Therapeutics","NTLA","4500412416","59.33","United States"
"2350","GOL Airlines","GOL","4496665600","2.81","Brazil"
"2351","Neoen","NEOEN.PA","4495958234","41.97","France"
"2352","Novanta","NOVT","4493373440","125.85","United States"
"2353","ScottsMiracle-Gro","SMG","4491769344","81.09","United States"
"2354","Ebos Group","EBO.NZ","4491615827","23.72","New Zealand"
"2355","Affiliated Managers Group","AMG","4487471616","116.03","United States"
"2356","Somfy","SO.PA","4480352660","129.11","France"
"2357","Hilton Grand Vacations","HGV","4479046144","37.25","United States"
"2358","Ollie's Bargain Outlet","OLLI","4478682624","71.67","United States"
"2359","Valmet","VALMT.HE","4474592209","24.29","Finland"
"2360","Jindal Steel & Power","JINDALSTEL.NS","4471906589","4.38","India"
"2361","Grupo Simec","SIM","4470770688","29.25","Mexico"
"2362","Phillips Edison & Company","PECO","4469711872","34.8","United States"
"2363","New Residential Investment","NRZ","4469485568","9.58","United States"
"2364","China Airlines","2610.TW","4467350627","0.75","Taiwan"
"2365","IAA-Insurance Auto Auctions","IAA","4466453504","33.33","United States"
"2366","Thor Industries","THO","4463916032","81.86","United States"
"2367","Kinnevik","KINV-A.ST","4455503808","16.24","Sweden"
"2368","Blue Owl Capital","OWL","4451295232","10.41","United States"
"2369","Mainfreight","MFT.NZ","4447910142","44.17","New Zealand"
"2370","Lendlease","LLC.AX","4447415853","6.46","Australia"
"2371","Asahi Intecc","7747.T","4446007556","16.37","Japan"
"2372","Hikma Pharmaceuticals","H5P.F","4442694789","20.11","United Kingdom"
"2373","Televisa","TV","4434362368","7.82","Mexico"
"2374","Premier","PINC","4432771584","37.57","United States"
"2375","Autohome","ATHM","4430652416","34.67","China"
"2376","Merlin Properties","MRL.MC","4429421917","9.49","Spain"
"2377","Husqvarna","HUSQ-A.ST","4427072900","8.13","Sweden"
"2378","Air Canada","AC.TO","4421153860","12.35","Canada"
"2379","Tegna","TGNA","4414697984","19.81","United States"
"2380","LOTTE Chemical","011170.KS","4403624283","128.48","South Korea"
"2381","Portland General Electric","POR","4401444352","49.33","United States"
"2382","Old National Bank","ONB","4400244224","15.02","United States"
"2383","Evotec","EVO","4394646528","12.4","Germany"
"2384","Home BancShares","HOMB","4392449536","21.36","United States"
"2385","ALD Automotive","ALD.PA","4392138329","10.74","France"
"2386","UOL Group","U14.SI","4384247733","5.19","Singapore"
"2387","Silgan Holdings","SLGN","4383248384","39.56","United States"
"2388","Royal Unibrew","0R1.F","4378999312","88.25","Denmark"
"2389","Element Solutions","ESI","4377106432","17.67","United States"
"2390","Topdanmarks","TQ71.F","4374923391","48.43","Denmark"
"2391","IDBI Bank","IDBI.NS","4374907411","0.41","India"
"2392","KGHM Polska Miedź","KGHA.F","4374551167","21.37","Poland"
"2393","Indian Hotels Company","INDHOTEL.NS","4370824805","3.08","India"
"2394","Hawaiian Electric Industries","HE","4369580032","39.93","United States"
"2395","Leroy Seafood","LSG.OL","4367028099","7.33","Norway"
"2396","Lyft","LYFT","4363694592","12.54","United States"
"2397","BlackLine","BL","4359446528","73.5","United States"
"2398","Eagle Materials","EXP","4358941184","114.41","United States"
"2399","Bezeq","BEZQ.TA","4353882816","1.57","Israel"
"2400","Astral Poly Technik","ASTRAL.NS","4343225799","21.62","India"
"2401","Orica","ORI.AX","4340507775","10.6","Australia"
"2402","Tower Bersama Infrastructure","TBIG.JK","4339378496","0.19","Indonesia"
"2403","Bankinter","BKT.MC","4336267262","4.76","Spain"
"2404","AAK","AAK.ST","4332788700","16.51","Sweden"
"2405","Iida Group","3291.T","4331862259","15.37","Japan"
"2406","Sallie Mae","SLM","4328961536","16.08","United States"
"2407","Ormat Technologies","ORA","4328735232","77.2","United States"
"2408","Integra LifeSciences","IART","4328429056","52.07","United States"
"2409","ServisFirst Bancshares","SFBS","4326944768","79.7","United States"
"2410","ONE Gas","OGS","4320160256","79.87","United States"
"2411","The Bidvest Group","BVT.JO","4316541101","12.59","South Africa"
"2412","Antero Midstream","AM","4305932800","9","United States"
"2413","Hitachi Construction Machinery","6305.T","4305728838","20.25","Japan"
"2414","Seaboard","SEB","4300701696","3705.01","United States"
"2415","Terreno Realty","TRNO","4295713280","56.87","United States"
"2416","UMB Financial","UMBF","4290055168","88.63","United States"
"2417","New York Community Bank","NYCB","4285073920","9.18","United States"
"2418","Mapletree Commercial Trust","N2IU.SI","4284636256","1.29","Singapore"
"2419","Smartsheet","SMAR","4282206208","33.08","United States"
"2420","Cadence Bancorp","CADE","4281405184","23.33","United States"
"2421","Onex","ONEX.TO","4279266694","49.42","Canada"
"2422","Murphy Oil","MUR","4277391360","27.53","United States"
"2423","Scout24","G24.F","4277333462","53.33","Germany"
"2424","Aroundtown","AT1.F","4273095626","2.96","Luxembourg"
"2425","Avnet","AVT","4271620608","43.73","United States"
"2426","Grocery Outlet","GO","4269075712","44.3","United States"
"2427","Punjab National Bank","PNB.NS","4265467537","0.39","India"
"2428","Pepkor","PPH.JO","4263933637","1.15","South Africa"
"2429","Gujarat Fluorochemicals","FLUOROCHEM.NS","4262695932","38.77","India"
"2430","Asset World Corp","AWC.BK","4262292982","0.13","Thailand"
"2431","Power Integrations","POWI","4261702144","73.09","United States"
"2432","The Weir Group","WEIR.L","4259942973","1591.01","United Kingdom"
"2433","Parsons","PSN","4257597696","41.05","United States"
"2434","Element Fleet Management","EFN.TO","4256169003","10.68","Canada"
"2435","Remgro Limited","REM.JO","4252842149","7.6","South Africa"
"2436","Sixt","SIX2.F","4251389812","103.87","Germany"
"2437","Wendy’s Company","WEN","4239948544","19.79","United States"
"2438","First Interstate BancSystem","FIBK","4239607808","38.72","United States"
"2439","Light & Wonder","LNW","4235107328","44.27","United States"
"2440","Indian Overseas Bank","IOB.NS","4232089579","0.22","India"
"2441","PCCW","0008.HK","4229817802","0.55","Hong Kong"
"2442","New Jersey Resources","NJR","4229757696","43.99","United States"
"2443","Valeo","FR.PA","4228569902","17.72","France"
"2444","GN Store Nord","GNN.F","4228184036","31.49","Denmark"
"2445","Carsales","CAR.AX","4227807898","12.71","Australia"
"2446","Kinross Gold","KGC","4227567616","3.25","Canada"
"2447","Essent Group","ESNT","4222801152","39.25","Bermuda"
"2448","Netmarble","251270.KS","4210707211","51.39","South Korea"
"2449","Watts Water Technologies","WTS","4207663616","125.78","United States"
"2450","Yes Bank","YESBANK.NS","4206925876","0.17","India"
"2451","Shriram Transport Finance","SRTRANSFIN.NS","4206418127","15.55","India"
"2452","Ryman Hospitality Properties","RHP","4198257152","76.13","United States"
"2453","Cousins Properties","CUZ","4196632320","28.21","United States"
"2454","Johnson Matthey","JMAT.L","4195659523","2237.04","United Kingdom"
"2455","Helmerich & Payne","HP","4194633984","39.84","United States"
"2456","Ortho Clinical Diagnostics","OCDX","4191268096","17.63","United States"
"2457","Howden Joinery","HWDN.L","4189074588","732.92","United Kingdom"
"2458","WeWork","WE","4185350656","5.28","United States"
"2459","Olam","VC2.SI","4181822184","1.09","Singapore"
"2460","Bank Pekao (Bank Polska Kasa Opieki)","PEO.WA","4179436116","15.92","Poland"
"2461","Hindustan Petroleum","HINDPETRO.NS","4174934339","2.94","India"
"2462","Rapid7","RPD","4171516672","71.6","United States"
"2463","Polycab India","POLYCAB.NS","4170635775","27.85","India"
"2464","Mediclinic International","MEI.JO","4169852943","5.62","South Africa"
"2465","NHPC Limited","NHPC.NS","4169202783","0.42","India"
"2466","Arrowhead Pharmaceuticals","ARWR","4164941056","39.39","United States"
"2467","Royal Boskalis Westminster","BOKA.AS","4161287079","32.18","Netherlands"
"2468","National Instruments","NATI","4159527424","31.71","United States"
"2469","South Jersey Industries","SJI","4153269504","33.93","United States"
"2470","Viper Energy Partners","VNOM","4150819328","24.76","United States"
"2471","MSC Industrial Direct","MSM","4147339264","74.08","United States"
"2472","Parkland Corp","PKI.TO","4141618864","26.26","Canada"
"2473","Schneider","SNDR","4131348736","23.22","United States"
"2474","Balchem","BCPC","4130978304","128.62","United States"
"2475","Indofood","INDF.JK","4130933203","0.47","Indonesia"
"2476","A1 Telekom Austria","TA1.F","4128085333","6.06","Austria"
"2477","Empresas CMPC","CMPC.SN","4127796363","1.65","Chile"
"2478","Banco de Crédito e Inversiones","BCI.SN","4123182445","26.45","Chile"
"2479","Fomento de Construcciones y Contratas","FCC.MC","4120598910","9.5","Spain"
"2480","China Lesso Group","2128.HK","4118242743","1.33","China"
"2481","AllianceBernstein","AB","4115712512","41.32","United States"
"2482","Altair Engineering","ALTR","4109740032","51.52","United States"
"2483","Grupo Aval","AVAL","4107608320","3.46","Colombia"
"2484","Nippon Shinyaku","4516.T","4107071377","60.98","Japan"
"2485","51job","JOBS","4106925568","60.9","China"
"2486","Univar Solutions","UNVR","4103876096","24.25","United States"
"2487","NCR Corporation","NCR","4101414912","30.03","United States"
"2488","MGIC Investment","MTG","4099117056","13.24","United States"
"2489","Hera Group","HER.MI","4090951819","2.8","Italy"
"2490","LG Display","LPL","4089831168","5.72","South Korea"
"2491","Madras Rubber Factory","MRF.NS","4089468748","964.24","India"
"2492","K+S","SDF.F","4086068127","21.3","Germany"
"2493","PNM Resources","PNM","4085312000","47.6","United States"
"2494","Commercial Metals Company","CMC","4084611072","33.9","United States"
"2495","COSMOS Pharmaceutical","3349.T","4084353713","103.14","Japan"
"2496","Petronet LNG","PETRONET.NS","4082607943","2.72","India"
"2497","Evoqua Water Technologies","AQUA","4082385664","33.66","United States"
"2498","Stericycle","SRCL","4080423680","44.31","United States"
"2499","ManpowerGroup","MAN","4079446528","77.35","United States"
"2500","Gruma (Maseca)","GRUMAB.MX","4078801838","10.96","Mexico"
"2501","Tecan","TECN.SW","4076772886","320.39","Switzerland"
"2502","EVN Group","EVN.F","4074292642","21.77","Austria"
"2503","Atotech","ATC","4071093248","20.91","United Kingdom"
"2504","The Ensign Group","ENSG","4070354944","73.37","United States"
"2505","Capital Power","CPX.TO","4065553079","34.95","Canada"
"2506","Tokyo Century","8439.T","4061264250","33.23","Japan"
"2507","First International Bank of Israel","FIBI.TA","4060711361","40.47","Israel"
"2508","SPS Commerce","SPSC","4058893824","112.45","United States"
"2509","Teradata","TDC","4055554560","38.74","United States"
"2510","Seven Group Holdings
(SGH)","SVW.AX","4055287468","11.03","Australia"
"2511","Amkor Technology","AMKR","4053540352","16.56","United States"
"2512","Petco","WOOF","4052948480","15.27","United States"
"2513","Pirelli","PIRC.MI","4049271055","4.05","Italy"
"2514","Gudang Garam","GGG.F","4043900589","1.88","Indonesia"
"2515","Strabag","XD4.F","4041790295","38.11","Austria"
"2516","Virtu Financial","VIRT","4038326973","22.17","United States"
"2517","Dairy Farm","D01.SI","4032774400","2.98","Hong Kong"
"2518","Braze","BRZE","4029495552","42.86","United States"
"2519","Toyo Suisan","2875.T","4022112094","39.38","Japan"
"2520","Clicks Group","CLS.JO","4019518055","16.48","South Africa"
"2521","iRhythm","IRTC","4018995968","134.91","United States"
"2522","ChargePoint","CHPT","4018284032","11.93","United States"
"2523","Alight","ALIT","4016128768","7.21","United States"
"2524","Pershing Square Tontine","PSTH","4016000000","20.08","United States"
"2525","Cirrus Logic","CRUS","4012207360","71.79","United States"
"2526","Cerevel Therapeutics","CERE","4009734400","27.04","United States"
"2527","Signify","LIGHT.AS","4004091495","32.28","Netherlands"
"2528","Aalberts","AALB.AS","4003483222","36.06","Netherlands"
"2529","YETI Holdings","YETI","4002581504","46.46","United States"
"2530","EnLink Midstream","ENLC","4001947904","8.29","United States"
"2531","Andritz","AZ2.F","3993560358","40.26","Austria"
"2532","Civitas Resources","CIVI","3991620352","46.98","United States"
"2533","Tempur Sealy","TPX","3988359680","22.72","United States"
"2534","QuantumScape","QS","3985920768","9.26","United States"
"2535","Voltas","VOLTAS.NS","3982080893","12.03","India"
"2536","Chiba Bank","CHBAY","3975372800","26.32","Japan"
"2537","Stevanato","STVN","3973147136","15.01","Italy"
"2538","Physicians Realty Trust","DOC","3972064768","16.75","United States"
"2539","Frasers Group","FRAS.L","3968091593","825.52","United Kingdom"
"2540","Timken Company","TKR","3966728192","53.51","United States"
"2541","Sweco","SWEC-A.ST","3966032351","11.22","Sweden"
"2542","Pegasystems","PEGA","3965757440","48.47","United States"
"2543","ATCO","ACO-X.TO","3957520820","34.49","Canada"
"2544","Altice USA","ATUS","3955498496","8.7","United States"
"2545","Turkish Airlines","THYAO.IS","3946141313","2.86","Turkey"
"2546","Aurobindo Pharma","AUROPHARMA.NS","3944556861","6.73","India"
"2547","Honeywell Automation India","HONAUT.NS","3944322356","446.11","India"
"2548","Denali Therapeutics","DNLI","3944172032","32.08","United States"
"2549","Insperity","NSP","3940360960","102.86","United States"
"2550","Huhtamäki","HUH1V.HE","3933232909","37.69","Finland"
"2551","Wiwynn","6669.TW","3925587678","22.45","Taiwan"
"2552","Colas","RE.PA","3922291708","120.16","France"
"2553","Amedisys","AMED","3919647744","120.34","United States"
"2554","ManTech","MANT","3917487616","95.66","United States"
"2555","Pan American Silver","PAAS","3916502784","18.38","Canada"
"2556","Whitecap Resources","WCP.TO","3913817128","6.32","Canada"
"2557","Vir Biotechnology","VIR","3911710720","29.55","United States"
"2558","Janus Henderson","JHG","3908463104","23.41","United Kingdom"
"2559","Aspen Pharmacare","APN.JO","3906501970","8.58","South Africa"
"2560","Enviva","EVA","3905662464","58.68","United States"
"2561","Carvana","CVNA","3904536064","21.99","United States"
"2562","ICU Medical","ICUI","3899827200","163.2","United States"
"2563","Healthcare Realty","HR","3891700224","25.67","United States"
"2564","Shin Kong Financial Holding","2888.TW","3887175238","0.27","Taiwan"
"2565","Box","BOX","3886657536","26.98","United States"
"2566","Maximus","MMS","3876990208","63.13","United States"
"2567","DoubleVerify","DV","3869298944","23.67","United States"
"2568","Granite Real Estate","GRP-UN","3868498176","58.73","Canada"
"2569","F.N.B. Corporation","FNB","3867927552","11.01","United States"
"2570","Kite Realty","KRG","3863954176","17.44","United States"
"2571","Gujarat Gas","GUJGASLTD.NS","3863686983","5.61","India"
"2572","Bank Mega","MEGA.JK","3862705153","0.33","Indonesia"
"2573","Hancock Whitney","HWC","3862421760","44.72","United States"
"2574","Callaway Golf","ELY","3861993216","20.91","United States"
"2575","Beacon Roofing Supply","BECN","3859143680","55.82","United States"
"2576","Bakkafrost","6BF.F","3858872181","65.31","Denmark"
"2577","Ibiden","4062.T","3852820069","27.6","Japan"
"2578","Perfect World Entertainment","002624.SZ","3851379351","1.99","China"
"2579","CG Power and Industrial Solutions","CGPOWER.NS","3849966609","2.52","India"
"2580","DigitalOcean","DOCN","3845596672","37.67","United States"
"2581","Hiscox","HSX.L","3842003171","1090.47","Bermuda"
"2582","AGL Energy","AGL.AX","3838511729","5.67","Australia"
"2583","Allegro MicroSystems","ALGM","3837048576","20.11","United States"
"2584","MEG Energy","MEG.TO","3836267183","12.08","Canada"
"2585","Oberoi Realty","OBEROIRLTY.NS","3830241435","10.53","India"
"2586","Cytokinetics","CYTK","3827796736","44.69","United States"
"2587","Phillips-Van Heusen","PVH","3827462144","57.16","United States"
"2588","Kerry Properties","0683.HK","3824470728","2.63","Hong Kong"
"2589","Electrolux","ELUX-A.ST","3824452799","16.1","Sweden"
"2590","ALTEN","ATE.PA","3821309040","112.52","France"
"2591","Casella Waste Systems","CWST","3811452416","73.81","United States"
"2592","Cummins India","CUMMINSIND.NS","3811377621","13.75","India"
"2593","Direct Line Group","DLG.L","3809730599","289.2","United Kingdom"
"2594","Assaí Atacadista","ASAI","3807229696","14.13","Brazil"
"2595","Sarana Menara Nusantara","TOWR.JK","3805121291","0.08","Indonesia"
"2596","Şişecam","SISE.IS","3805016721","1.24","Turkey"
"2597","National Mineral Development Corporation","NMDC.NS","3803880481","1.3","India"
"2598","Atkore","ATKR","3797498880","88.08","United States"
"2599","Karuna Therapeutics","KRTX","3797194752","127.07","United States"
"2600","Bank of East Asia","0023.HK","3794895921","1.41","Hong Kong"
"2601","IMI plc","IMI.L","3789921630","1437.08","United Kingdom"
"2602","Clearwater Analytics","CWAN","3789408768","13","United States"
"2603","Boston Beer Company","SAM","3785559808","308.18","United States"
"2604","Crescent Point Energy","CPG","3784611840","6.56","Canada"
"2605","Core & Main","CNM","3783575808","22.53","United States"
"2606","Atlantica","AY","3783423232","33.16","United Kingdom"
"2607","Under Armour","UA","3782439936","7.7","United States"
"2608","Hanesbrands","HBI","3780731904","10.84","United States"
"2609","Global-e","GLBE","3780315136","24.16","Israel"
"2610","Minda Industries","MINDAIND.NS","3780032311","6.61","India"
"2611","İsdemir","ISDMR.IS","3776370725","1.3","Turkey"
"2612","NWS holdings","0659.HK","3771749944","0.96","Hong Kong"
"2613","Kumho Petrochemical","011780.KS","3764896417","93.3","South Korea"
"2614","Inari Medical","NARI","3755965696","70.7","United States"
"2615","Livent","LTHM","3755182592","20.95","United States"
"2616","Kohl's","KSS","3754915072","29.23","United States"
"2617","TFS Financial","TFSL","3754255872","13.37","United States"
"2618","Duolingo","DUOL","3749694464","95.75","United States"
"2619","SD BioSensor","137310.KS","3743614082","37.01","South Korea"
"2620","SM Energy","SM","3742443264","30.71","United States"
"2621","Fluidra","FDR.MC","3741211801","19.62","Spain"
"2622","Kojamo","KOJAMO.HE","3740087666","15.13","Finland"
"2623","Ziff Davis","ZD","3737598208","79.03","United States"
"2624","Independent Bank","INDB","3727818752","79.69","United States"
"2625","Turning Point","TPTX","3727662336","75.03","United States"
"2626","Air Lease Corporation","AL","3727045888","33.62","United States"
"2627","Schibsted","SCHA.OL","3726624623","16.63","Norway"
"2628","WNS","WNS","3721873920","76.19","India"
"2629","Fox Factory Holding","FOXF","3721730304","88.3","United States"
"2630","Cabot Corporation","CBT","3720109312","65.92","United States"
"2631","White Mountains Insurance Group","WTM","3718806016","1247.21","Bermuda"
"2632","Flowserve","FLS","3715543808","28.44","United States"
"2633","Sembcorp","U96.SI","3708684510","2.08","Singapore"
"2634","Bharat Forge","BHARATFORG.NS","3707354845","7.96","India"
"2635","Nikon","NINOY","3706847232","10.16","Japan"
"2636","Umpqua Holdings","UMPQ","3706060544","17.08","United States"
"2637","Spire Energy","SR","3705092352","71.09","United States"
"2638","Acom","8572.T","3704166510","2.36","Japan"
"2639","Tate & Lyle","TATE.L","3703471840","921.2","United Kingdom"
"2640","Société Foncière Lyonnaise","FLY.PA","3702600463","86.48","France"
"2641","Ryder","R","3701785600","72.39","United States"
"2642","Freshworks","FRSH","3694223104","13","United States"
"2643","Steel Authority of India","SAIL.NS","3693724729","0.89","India"
"2644","Powszechny Zakład Ubezpieczeń","7PZ.F","3689805611","6.34","Poland"
"2645","Marel","MAREL.AS","3687180227","4.88","Iceland"
"2646","Asbury Automotive Group","ABG","3682758912","166.41","United States"
"2647","Kangwon Land","035250.KS","3682301872","18.16","South Korea"
"2648","Dillard's","DDS","3682171136","210.13","United States"
"2649","Mercury Systems","MRCY","3681280512","63.83","United States"
"2650","HUGO BOSS","BOSS.DE","3680864016","53.33","Germany"
"2651","Evercore","EVR","3676891904","90.58","United States"
"2652","Armstrong World Industries","AWI","3673461504","78.23","United States"
"2653","MSG Sports","MSGS","3666907904","151.36","United States"
"2654","Wix.com","WIX","3664402688","63.77","Israel"
"2655","Galapagos NV","GLPG","3661974784","55.38","Belgium"
"2656","Power Finance Corp","PFC.NS","3657553735","1.39","India"
"2657","Bangkok Expressway and Metro (BEM)","BEM.BK","3653565899","0.24","Thailand"
"2658","Banco Sabadell","BDSB.F","3652274132","0.65","Spain"
"2659","Hochtief","HOT.F","3652210550","48.42","Germany"
"2660","Sime Darby","SIME.KL","3647383203","0.54","Malaysia"
"2661","BE Semiconductor","BESI.AS","3640932907","45.56","Netherlands"
"2662","Hamilton Lane","HLNE","3640107776","68.37","United States"
"2663","Allison Transmission","ALSN","3639922432","37.5","United States"
"2664","SPX FLOW","FLOW","3637604864","86.49","United States"
"2665","Tandem Diabetes Care","TNDM","3636919040","56.86","United States"
"2666","EPR Properties","EPR","3636775168","48.51","United States"
"2667","International Game Technology","IGT","3635061248","17.92","United Kingdom"
"2668","New Relic","NEWR","3631518976","53.98","United States"
"2669","STAAR Surgical","STAA","3626965248","75.86","United States"
"2670","Coromandel","COROMANDEL.NS","3626529066","12.35","India"
"2671","Max Financial Services","MFSL.NS","3626377812","10.5","India"
"2672","Cleanaway Waste Management","CWY.AX","3625187048","1.73","Australia"
"2673","ChampionX","CHX","3623588864","17.82","United States"
"2674","Natera","NTRA","3623324928","37.62","United States"
"2675","New Oriental","EDU","3622182144","21.35","China"
"2676","Fannie Mae","FNMAL","3621263872","4.84","United States"
"2677","Lupin Limited","LUPIN.NS","3621179558","7.97","India"
"2678","Zai Lab","ZLAB","3621153536","36.99","China"
"2679","Bendigo and Adelaide Bank","BEN.AX","3617144152","6.39","Australia"
"2680","Quiñenco","QUINENCO.SN","3616653914","2.18","Chile"
"2681","Simply Good Foods","SMPL","3613356032","36","United States"
"2682","Highwoods Properties","HIW","3611959296","33.55","United States"
"2683","IG Group","IGG.L","3611454980","836.81","United Kingdom"
"2684","Zurn Water Solutions","ZWS","3611376640","28.67","United States"
"2685","Charter Hall Group","CHC.AX","3609907345","7.63","Australia"
"2686","Broadstone Net Lease","BNL","3609817088","21.32","United States"
"2687","Avient","AVNT","3609498368","39.48","United States"
"2688","Fuchs Petrolub","FPE.F","3607560752","23.73","Germany"
"2689","Workiva","WK","3606860032","69.26","United States"
"2690","Derwent London","DLN.L","3606140170","3171.32","United Kingdom"
"2691","Nisshin Seifun Group","2002.T","3605167601","12.12","Japan"
"2692","Enact Holdings","ACT","3603693312","22.13","United States"
"2693","Frasers Logistics & Industrial Trust","BUOU.SI","3601173614","0.97","Singapore"
"2694","Signify Health","SGFY","3599814656","15.46","United States"
"2695","Beazley","BEZ.L","3591913790","588.86","United Kingdom"
"2696","APi Group","APG","3591110400","15.4","United States"
"2697","Tikehau Capital","TKO.PA","3590217621","20.31","France"
"2698","Voestalpine","VAS.F","3590165623","20.11","Austria"
"2699","CSN Mineração","CMIN3.SA","3585781100","0.65","Brazil"
"2700","Fraport","FRA.DE","3584169380","38.79","Germany"
"2701","Applied Industrial Technologies","AIT","3581836800","93.17","United States"
"2702","Enstar Group","ESGR","3576221696","198.2","Bermuda"
"2703","Radian Group","RDN","3572681216","20.68","United States"
"2704","Sega Sammy Holdings","6460.T","3571731320","16.19","Japan"
"2705","Natura&Co","NTCO","3564605184","5.16","Brazil"
"2706","Privia Health Group","PRVA","3562637568","32.8","United States"
"2707","Korea Aerospace Industries","047810.KS","3559471764","36.52","South Korea"
"2708","John Bean Technologies","JBT","3557298688","111.92","United States"
"2709","Vontier","VNT","3550204416","22.05","United States"
"2710","Infratil","IFT.NZ","3549724968","4.9","New Zealand"
"2711","Assured Guaranty","AGO","3549628672","55.35","Bermuda"
"2712","Asana","ASAN","3549243904","18.65","United States"
"2713","Oberbank","OBS.VI","3548275580","100.55","Austria"
"2714","Contact Energy","CEN.NZ","3547557703","4.55","New Zealand"
"2715","Schaeffler","SHA.F","3541600531","5.28","Germany"
"2716","Spectris","SXS.L","3540504435","3344.86","United Kingdom"
"2717","Ardagh Metal Packaging","AMBP","3535385088","5.86","Luxembourg"
"2718","Grupo Catalana Occidente","GCO.MC","3535277627","29.96","Spain"
"2719","Coway","021240.KS","3534901252","48.71","South Korea"
"2720","Samsung Heavy Industries","010145.KS","3534476424","173.98","South Korea"
"2721","SPIE","SPIE.PA","3532778634","21.72","France"
"2722","Workman","7564.T","3530693781","43.26","Japan"
"2723","Vodafone Idea","IDEA.NS","3527095408","0.11","India"
"2724","nCino","NCNO","3519756032","31.94","United States"
"2725","O2 Czech Republic","TEE.F","3517120270","11.39","Czech Republic"
"2726","Venture Corporation","V03.SI","3516829635","12.08","Singapore"
"2727","Lawson","2651.T","3512596504","35.1","Japan"
"2728","Howard Hughes Corporation","HHC","3511976960","68.39","United States"
"2729","Certara","CERT","3511728640","21.97","United States"
"2730","Lancaster Colony Corporation","LANC","3510981632","127.57","United States"
"2731","Wendel","MF.PA","3510588621","80.89","France"
"2732","Eastern Bankshares","EBC","3509186816","19.21","United States"
"2733","Dorman Products","DORM","3507732224","111.54","United States"
"2734","Indosat","ISAT.JK","3497325434","0.43","Indonesia"
"2735","Companhia Siderúrgica Nacional","SID","3495627264","2.59","Brazil"
"2736","Apple Hospitality REIT","APLE","3495134976","15.27","United States"
"2737","B2Gold","BTG","3491355392","3.25","Canada"
"2738","Choice Properties REIT","CHP-UN.TO","3489197769","10.65","Canada"
"2739","Curaleaf","CURLF","3487246336","4.99","United States"
"2740","Franklin Electric","FELE","3485539072","75.26","United States"
"2741","Travel + Leisure","TNL","3481129216","40.76","United States"
"2742","Cushman & Wakefield","CWK","3479943424","15.43","United States"
"2743","BAWAG Group","0B2.F","3473788203","39.1","Austria"
"2744","Magazine Luíza","MGLU3.SA","3470758737","0.52","Brazil"
"2745","Diploma plc","DPLM.L","3469085276","2783.82","United Kingdom"
"2746","Triton International","TRTN","3463660032","53.94","Bermuda"
"2747","Uniper","UN01.DE","3463058083","9.33","Germany"
"2748","Cencosud","CENCOSUD.SN","3462934283","1.22","Chile"
"2749","CVB Financial","CVBF","3460128000","24.53","United States"
"2750","Kirby Corporation","KEX","3458808064","57.36","United States"
"2751","Investors Bancorp","ISBC","3455835392","13.87","United States"
"2752","SSR Mining","SSRM","3455367424","16.25","Canada"
"2753","Raiffeisen Bank International","RAW.F","3451217215","10.39","Austria"
"2754","Community Bank System","CBU","3450233600","64","United States"
"2755","Japan Airport Terminal","9706.T","3449836045","37.04","Japan"
"2756","Petro Rio","PRIO3.SA","3449715667","4.09","Brazil"
"2757","PagSeguro","PAGS","3446439168","10.51","Brazil"
"2758","Melisron","MLSR.TA","3443509163","71.21","Israel"
"2759","NEXTDC","NXT.AX","3436086235","7.51","Australia"
"2760","Appian","APPN","3432503808","49.73","United States"
"2761","Kansai Paint","4613.T","3430079344","13.35","Japan"
"2762","Welbilt","WBT","3425581312","23.93","United States"
"2763","Vale Indonesia","INCO.JK","3414891476","0.34","Indonesia"
"2764","GarantiBank","GARAN.IS","3413418053","0.81","Turkey"
"2765","Romgaz","RZ8G.F","3410471385","8.85","Romania"
"2766","Scor","SCR.PA","3409496808","19.81","France"
"2767","American Equity Investment Life Holding","AEL","3403313920","36.57","United States"
"2768","Beam Therapeutics","BEAM","3403021056","48.43","United States"
"2769","Alteryx","AYX","3402592256","51.69","United States"
"2770","Fielmann","FIE.F","3400504760","40.46","Germany"
"2771","Storebrand","STB.OL","3396096541","7.2","Norway"
"2772","Fluor Corporation","FLR","3394725120","23.91","United States"
"2773","AppFolio","APPF","3394005504","97.25","United States"
"2774","Icade","ICAD.PA","3393922381","43.78","France"
"2775","Mister Car Wash","MCW","3391491840","11.22","United States"
"2776","Just Eat Takeaway","TKWY.AS","3390606351","15.34","Netherlands"
"2777","Computacenter","CCC.L","3389131263","2969.25","United Kingdom"
"2778","Crocs","CROX","3387251712","55.01","United States"
"2779","Nutanix","NTNX","3384596480","15.09","United States"
"2780","Haemonetics","HAE","3384221440","65.97","United States"
"2781","Semtech","SMTC","3382097152","53.28","United States"
"2782","Helen of Troy","HELE","3378120448","140.94","United States"
"2783","Sensient Technologies","SXT","3375443968","80.31","United States"
"2784","Renishaw","RSW.L","3372550555","4628.61","United Kingdom"
"2785","Easterly Government Properties","DEA","3372057088","19.06","United States"
"2786","Encavis","ECV.F","3367947584","20.92","Germany"
"2787","BlackBerry","BB","3359356928","5.61","Canada"
"2788","Nomad Foods","NOMD","3353673728","19.27","United Kingdom"
"2789","Nexans","NEX.PA","3351154550","77.28","France"
"2790","Allete","ALE","3349231872","58.77","United States"
"2791","Mainova","MNV6.F","3345475186","542.99","Germany"
"2792","UniFirst","UNF","3339861760","178.42","United States"
"2793","CJ Group","001040.KS","3338409927","58.12","South Korea"
"2794","Laurus Labs","LAURUSLABS.NS","3331663236","6.19","India"
"2795","DigitalBridge Group","DBRG","3329812992","5.08","United States"
"2796","BB Biotech","BION.SW","3329265765","60.39","Switzerland"
"2797","Mirati Therapeutics","MRTX","3328771072","59.95","United States"
"2798","Indian Railway Finance","IRFC.NS","3328548735","0.25","India"
"2799","Sprout Social","SPT","3327366656","61.12","United States"
"2800","Aarti Industries","AARTIIND.NS","3323074763","9.17","India"
"2801","Taisho Pharmaceutical","4581.T","3318870302","40.48","Japan"
"2802","Sabra Health Care REIT","SBRA","3318823424","14.37","United States"
"2803","Allied Properties REIT","AP-UN.TO","3316880987","25.92","Canada"
"2804","Kuka","KU2.F","3315645587","82.96","Germany"
"2805","Varonis","VRNS","3315588352","30.26","United States"
"2806","ASM Pacific Technology","0522.HK","3314884833","8.03","Hong Kong"
"2807","LivaNova","LIVN","3312782848","61.99","United Kingdom"
"2808","Nordstrom","JWN","3311781632","20.62","United States"
"2809","JCDecaux","DEC.PA","3309771358","15.56","France"
"2810","Lazard","LAZ","3301994752","33.73","Bermuda"
"2811","MultiPlan","MPLN","3300502016","5.17","United States"
"2812","iQIYI","IQ","3299544576","3.83","China"
"2813","Vertiv Holdings","VRT","3296002560","8.75","United States"
"2814","PBF Energy","PBF","3293771264","27.26","United States"
"2815","Boralex","BLX.TO","3290756576","32.04","Canada"
"2816","Acushnet Holdings","GOLF","3289108224","45.54","United States"
"2817","Nelnet","NNI","3286824960","87.48","United States"
"2818","Spirit AeroSystems","SPR","3285456896","31.29","United States"
"2819","Qube Holdings","QUB.AX","3282147048","1.85","Australia"
"2820","Select Medical Holdings","SEM","3281350400","25.12","United States"
"2821","Jinko Solar","JKS","3277842176","67.17","China"
"2822","AntarChile","ANTARCHILE.SN","3277690126","7.19","Chile"
"2823","Instructure Holdings","INST","3276423680","23.18","United States"
"2824","Abcam","ABCM","3274242560","14.3","United Kingdom"
"2825","Perficient","PRFT","3268748800","94.34","United States"
"2826","United Community Bank","UCBI","3265631488","30.8","United States"
"2827","GATX","GATX","3265232128","91.72","United States"
"2828","Thyssenkrupp","TKA.F","3262945882","5.21","Germany"
"2829","AmTrust Financial Services","AFFS","3262066432","16.5","United States"
"2830","Walker & Dunlop","WD","3261668096","98.45","United States"
"2831","BellRing Brands","BRBR","3261097472","23.92","United States"
"2832","DMG Mori","GIL.F","3257630504","40.82","Germany"
"2833","Alarm.com","ALRM","3255674624","65","United States"
"2834","Park Hotels & Resorts","PK","3253177600","13.94","United States"
"2835","Onto Innovation","ONTO","3252406016","65.63","United States"
"2836","NorthWestern Corporation","NWE","3251258368","57.91","United States"
"2837","ITV plc","ITV.L","3250884751","77.17","United Kingdom"
"2838","3M India","3MINDIA.NS","3249980216","288.5","India"
"2839","Guoco","0053.HK","3248691971","9.87","Hong Kong"
"2840","Inchcape","INCH.L","3248041726","862.37","United Kingdom"
"2841","Aerojet Rocketdyne","AJRD","3246895872","40.35","United States"
"2842","Harvey Norman","HVN.AX","3242843529","2.6","Australia"
"2843","Spectrum Brands","SPB","3233552896","79.3","United States"
"2844","easyJet","EJT1.F","3231528543","4.21","United Kingdom"
"2845","Indraprastha Gas","IGL.NS","3231111251","4.61","India"
"2846","MACOM","MTSI","3229653760","46.21","United States"
"2847","Jamf","JAMF","3228166400","26.94","United States"
"2848","Squarespace","SQSP","3227104000","23.07","United States"
"2849","FirstCash","FCFS","3225205760","67.95","United States"
"2850","SATS","S58.SI","3222222963","2.87","Singapore"
"2851","Lion Corp","4912.T","3222186145","11.34","Japan"
"2852","Cohen & Steers","CNS","3217677312","66.09","United States"
"2853","Academy Sports","ASO","3206021888","37.68","United States"
"2854","Persistent Systems","PERSISTENT.NS","3201116300","41.89","India"
"2855","Wynn Macau","1128.HK","3197588765","0.61","Macau"
"2856","Old Mutual","OMU.JO","3195261382","0.68","South Africa"
"2857","Thermax","THERMAX.NS","3191198487","26.07","India"
"2858","Suntec REIT","T82U.SI","3186008951","1.12","Singapore"
"2859","H.B. Fuller","FUL","3185249280","59.92","United States"
"2860","Gates Industrial Corp","GTES","3182824960","10.99","United States"
"2861","Inmobiliaria Colonial","COL.MC","3182245518","5.99","Spain"
"2862","Bellway","BWY.L","3182202113","2576.99","United Kingdom"
"2863","Blueprint Medicines","BPMC","3181064704","53.4","United States"
"2864","CLEAR Secure","YOU","3178403328","21.21","United States"
"2865","Korn Ferry","KFY","3176922368","59.92","United States"
"2866","Skyline Champion","SKY","3173299200","55.83","United States"
"2867","PotlatchDeltic","PCH","3172395520","45.73","United States"
"2868","Indoritel","DNET.JK","3170930771","0.22","Indonesia"
"2869","Kemper","KMPR","3167704832","49.65","United States"
"2870","PacWest Bancorp","PACW","3167545600","26.97","United States"
"2871","PB Fintech","POLICYBZR.NS","3167383907","7.05","India"
"2872","Sumitomo Dainippon Pharma","4506.T","3161312987","7.96","Japan"
"2873","Innovative Industrial","IIPR","3160747776","113","United States"
"2874","Santen Pharmaceutical","4536.T","3159438398","7.95","Japan"
"2875","1&1","1U1.DE","3153722562","17.89","Germany"
"2876","Taylor Morrison","TMHC","3152487680","26.35","United States"
"2877","Varta","VAR1.F","3148353384","77.33","Germany"
"2878","Union Bank of India","UNIONBANK.NS","3146247377","0.46","India"
"2879","TTEC","TTEC","3145270784","66.87","United States"
"2880","ACI Worldwide","ACIW","3143327232","27.38","United States"
"2881","Buzzi Unicem","BZU.MI","3141379990","16.97","Italy"
"2882","Kadokawa","9468.T","3139657710","22.55","Japan"
"2883","Verbio","VBK.F","3134493345","49.25","Germany"
"2884","BTS Group","BTS.BK","3129251640","0.24","Thailand"
"2885","Cornerstone Building Brands","CNR","3129087744","24.57","United States"
"2886","Makkah Construction & Development","4100.SR","3126638252","18.97","Saudi Arabia"
"2887","AbCellera","ABCL","3124205056","10.98","Canada"
"2888","Opendoor","OPEN","3123760128","5","United States"
"2889","Harmony Biosciences","HRMY","3118925824","52.82","United States"
"2890","Bausch Health","BHC","3114150144","8.62","Canada"
"2891","Hysan Development","0014.HK","3112282913","3.03","Hong Kong"
"2892","Deepak Nitrite","DEEPAKNTR.NS","3106616513","22.78","India"
"2893","Renewable Energy Group","REGI","3106199040","61.5","United States"
"2894","SeaWorld Entertainment","SEAS","3105603584","42.75","United States"
"2895","Equity Commonwealth","EQC","3105386496","27.6","United States"
"2896","CNX Resources","CNX","3104909568","15.92","United States"
"2897","Atul","ATUL.NS","3104205113","105.18","India"
"2898","SiTime","SITM","3104101120","147.52","United States"
"2899","Comfort Systems","FIX","3102581248","86.56","United States"
"2900","Lexington Realty Trust","LXP","3100881664","10.79","United States"
"2901","Papa John's Pizza","PZZA","3098764544","86.57","United States"
"2902","TransAlta","TAC","3098672640","11.44","Canada"
"2903","SNC-Lavalin Group","SNC.TO","3098545592","17.3","Canada"
"2904","Ipca Laboratories","IPCALAB.NS","3095822295","12.19","India"
"2905","Carter's","CRI","3094797824","76.81","United States"
"2906","Relaxo Footwear","RELAXO.NS","3094509646","12.43","India"
"2907","Mayr-Melnhof","MYM.F","3091903903","153.24","Austria"
"2908","Hannon Armstrong","HASI","3090100992","35.63","United States"
"2909","Goodyear","GT","3087342336","10.93","United States"
"2910","Avista","AVA","3086664448","42.61","United States"
"2911","Vermilion Energy","VET","3085936128","18.68","Canada"
"2912","IHS Towers","IHS","3084698368","9.3","United Kingdom"
"2913","Rural Electrification Corp","RECLTD.NS","3083794146","1.56","India"
"2914","Hayward","HAYW","3079517952","14.1","United States"
"2915","CA Immo","BZY.F","3078669128","30.37","Austria"
"2916","PTC Therapeutics","PTCT","3074680832","43.1","United States"
"2917","Insight Enterprises","NSIT","3074621952","87.66","United States"
"2918","BancFirst","BANF","3073833984","93.91","United States"
"2919","Royal Mail","RMG.L","3073311205","321.41","United Kingdom"
"2920","Meritage Homes","MTH","3072839168","83.74","United States"
"2921","Visteon","VC","3071429888","109.26","United States"
"2922","TMBThanachart Bank (ttb)","TTB.BK","3070755399","0.03","Thailand"
"2923","Brighthouse Financial","BHF","3070699520","40.93","United States"
"2924","Marks & Spencer","MKS.L","3069911930","156.31","United Kingdom"
"2925","Roivant Sciences","ROIV","3069355264","4.38","United Kingdom"
"2926","American States Water","AWR","3065853184","82.96","United States"
"2927","Pennon Group","PNN.L","3065754962","1163.09","United Kingdom"
"2928","Softcat","SCT.L","3063753616","1536.93","United Kingdom"
"2929","Shapir Civil and Marine Engineering","SPEN.TA","3060842867","8.56","Israel"
"2930","Peloton","PTON","3059827712","9.07","United States"
"2931","Amicus Therapeutics","FOLD","3059379968","10.92","United States"
"2932","NewMarket Corp","NEU","3058259200","298.23","United States"
"2933","Fabrinet","FN","3057953536","83.13","Cayman Islands"
"2934","VIAVI Solutions","VIAV","3054074624","13.41","United States"
"2935","Sumitomo Chemical
India","SUMICHEM.NS","3053900993","6.12","India"
"2936","Aritzia","ATZ.TO","3053622010","27.77","Canada"
"2937","LCI Industries","LCII","3048680448","119.96","United States"
"2938","Gap Inc.","GPS","3046775040","8.28","United States"
"2939","Blackbaud","BLKB","3045810688","57.53","United States"
"2940","Supreme Industries","SUPREMEIND.NS","3042030485","23.95","India"
"2941","Shift4 Payments","FOUR","3040574464","32.52","United States"
"2942","Denbury","DEN","3038761984","60.33","United States"
"2943","Strauss Group","STRS.TA","3031815850","26.07","Israel"
"2944","Finning","FTT.TO","3028512994","19.39","Canada"
"2945","CVR Energy","CVI","3027993856","30.12","United States"
"2946","BRF","BRFS","3027550208","2.81","Brazil"
"2947","California Resources Corporation","CRC","3025272320","38.97","United States"
"2948","Federated Hermes","FHI","3023438080","32.98","United States"
"2949","Mueller Industries","MLI","3022392320","53.12","United States"
"2950","Bank of Hawaii","BOH","3020383744","74.97","United States"
"2951","California Water Service","CWT","3014245632","56.06","United States"
"2952","MultiChoice Group","MCG.JO","3011053618","7.07","South Africa"
"2953","Metro AG","B4B.F","3010847276","8.34","Germany"
"2954","Sunoco","SUN","3005781248","35.89","United States"
"2955","Vopak","VPK.AS","3003586349","23.96","Netherlands"
"2956","CRISIL","CRISIL.NS","2998097966","41.04","India"
"2957","Amot Investment","AMOT.TA","2996610746","6.38","Israel"
"2958","Bayer Crop Science","BAYERCROP.NS","2994811193","66.61","India"
"2959","Arcadis","ARCAD.AS","2994759047","33.65","Netherlands"
"2960","Arconic","ARNC","2993687040","28.3","United States"
"2961","Paramount Resources","POU.TO","2992553562","20.15","Canada"
"2962","Greif","GEF","2989234432","62.58","United States"
"2963","Commvault","CVLT","2988761344","66.66","United States"
"2964","Merit Medical","MMSI","2987629056","52.71","United States"
"2965","Matson","MATX","2984252416","73.61","United States"
"2966","Cathay General Bancorp","CATY","2982707200","39.69","United States"
"2967","Ultra Electronics","ULE.L","2980291391","4146.01","United Kingdom"
"2968","Main Street Capital","MAIN","2977547264","40.8","United States"
"2969","Taiwan Business Bank","2834.TW","2971068004","0.38","Taiwan"
"2970","Joby Aviation","JOBY","2965579520","4.89","United States"
"2971","SL Green Realty","SLG","2964583424","45.74","United States"
"2972","KnowBe4","KNBE","2964002816","16.93","United States"
"2973","Hostess Brands","TWNK","2962107648","21.42","United States"
"2974","Freedom Holding","FRHC","2960438272","49.72","Kazakhstan"
"2975","Kinaxis","KXS.TO","2958943656","107.24","Canada"
"2976","BİM Birleşik Mağazalar","BIMAS.IS","2948440886","4.93","Turkey"
"2977","Tata Teleservices","TTML.NS","2944398887","1.51","India"
"2978","Corporate Office Properties Trust","OFC","2941994240","25.79","United States"
"2979","Meitetsu","9048.T","2936319654","14.94","Japan"
"2980","Diodes Incorporated","DIOD","2936097280","64.89","United States"
"2981","First Hawaiian Bank","FHB","2935181056","22.92","United States"
"2982","Aaon","AAON","2934306816","55.29","United States"
"2983","Prestige Consumer Healthcare","PBH","2932794112","58.75","United States"
"2984","Leslie's","LESL","2932737792","16.04","United States"
"2985","Resideo Technologies","REZI","2928355840","20.14","United States"
"2986","OVH Groupe","OVH.PA","2925190886","15.37","France"
"2987","Aselsan","ASELS.IS","2921630985","1.28","Turkey"
"2988","ABM Industries","ABM","2919641856","43.72","United States"
"2989","Independent Bank Group","IBTX","2918139648","69.03","United States"
"2990","Axonics Modulation Tech","AXNX","2916934144","61.97","United States"
"2991","Bata India","BATAINDIA.NS","2914216002","22.66","India"
"2992","Enovis","ENOV","2913346048","53.92","United States"
"2993","Peabody Energy","BTU","2910511872","20.24","United States"
"2994","Sprouts Farmers Market","SFM","2910490624","26.55","United States"
"2995","JB Hi-Fi","JBH.AX","2907590996","26.59","Australia"
"2996","JBG SMITH","JBGS","2907084544","23.53","United States"
"2997","Cogent Communications","CCOI","2902488320","60.55","United States"
"2998","Nordic Semiconductor","NOD.OL","2898215150","15.18","Norway"
"2999","Essential Properties Realty Trust","EPRT","2897531904","22","United States"
"3000","Bloom Energy","BE","2895843840","17.25","United States"
"3001","Covetrus","CVET","2894998528","20.75","United States"
"3002","Valaris","VAL","2894742784","38.6","United Kingdom"
"3003","Patterson Companies","PDCO","2894460928","29.92","United States"
"3004","Lightspeed POS","LSPD","2894228224","19.38","Canada"
"3005","Comgás","CGAS5.SA","2894170993","22.16","Brazil"
"3006","Vishay Intertechnology","VSH","2892903680","18.53","United States"
"3007","Enerplus","ERF","2892312576","11.85","Canada"
"3008","Dixon Technologies","DIXON.NS","2890219258","48.7","India"
"3009","Metsä Board","METSA.HE","2888388923","8.67","Finland"
"3010","Big Yellow Group","BYG.L","2883545184","1566.64","United Kingdom"
"3011","Syngene International","SYNGENE.NS","2882207774","7.18","India"
"3012","Grand Canyon Education","LOPE","2881436160","89.16","United States"
"3013","Evolution Mining","EVN.AX","2874726673","1.57","Australia"
"3014","TietoEVRY","TIETO.HE","2874298498","24.27","Finland"
"3015","CIE Automotive","CIE.MC","2873319546","23.45","Spain"
"3016","NexPoint Residential","NXRT","2872577536","58.01","United States"
"3017","RLX Technology","RLX","2871336192","1.86","China"
"3018","Pacific Premier Bancorp","PPBI","2868796672","30.22","United States"
"3019","BankUnited","BKU","2868276992","35.07","United States"
"3020","Dycom Industries","DY","2867726080","97.04","United States"
"3021","Evolent Health","EVH","2867368960","31.31","United States"
"3022","Lanxess","LXS.F","2866122972","33.07","Germany"
"3023","Air France-KLM","AF.PA","2861269655","1.11","France"
"3024","Thai Oil","TOP.BK","2860935117","1.4","Thailand"
"3025","Harmonic Drive Systems","6324.T","2860807194","29.79","Japan"
"3026","Hankook Tire","161390.KS","2854700498","23.4","South Korea"
"3027","SITE Centers","SITC","2852180224","13.33","United States"
"3028","Prospect Capital","PSEC","2850937856","7.27","United States"
"3029","Tricon Residential","TCN","2850095872","10.42","Canada"
"3030","Hillenbrand","HI","2849153280","39.73","United States"
"3031","Lithium Americas","LAC","2844914432","20.39","Canada"
"3032","Südzucker","SZU.F","2843138832","13.87","Germany"
"3033","Mayora","D7V.F","2842795439","0.12","Indonesia"
"3034","Mapletree North Asia Commercial Trust","RW0U.SI","2840643118","0.85","Singapore"
"3035","Port of Tauranga","POT.NZ","2838820069","4.04","New Zealand"
"3036","Linamar","LNR.TO","2838463561","41.42","Canada"
"3037","Envestnet","ENV","2836627200","51.4","United States"
"3038","ALSOK","2331.T","2834583102","28","Japan"
"3039","Aditya Birla Capital","ABCAPITAL.NS","2832666514","1.17","India"
"3040","Keppel REIT","K71U.SI","2832649924","0.76","Singapore"
"3041","Dermapharm","DMP.F","2831858357","52.09","Germany"
"3042","Innergex Renewable Energy","INE.TO","2829682670","13.86","Canada"
"3043","Ameris Bancorp","ABCB","2829508864","40.75","United States"
"3044","Patterson-UTI Energy","PTEN","2829243392","13.08","United States"
"3045","Exxaro Resources","EXX.JO","2827844024","11.45","South Africa"
"3046","Black Stone Minerals","BSM","2826873088","13.5","United States"
"3047","Advanced Energy","AEIS","2826713088","75.26","United States"
"3048","Permata Bank","BNLI.JK","2824966327","0.08","Indonesia"
"3049","Summit Materials","SUM","2819637504","23.88","United States"
"3050","Solaria Energía","SLR.MC","2816894262","22.54","Spain"
"3051","De' Longhi","DLG.MI","2816006693","18.77","Italy"
"3052","Darktrace","DARK.L","2815490002","402.36","United Kingdom"
"3053","Alumina Limited","AWC.AX","2814784636","0.97","Australia"
"3054","African Rainbow Minerals","ARI.JO","2811003682","12.52","South Africa"
"3055","Upwork","UPWK","2810833664","21.68","United States"
"3056","H&R REIT","HR-UN.TO","2809162007","9.73","Canada"
"3057","Otter Tail","OTTR","2805076480","67.38","United States"
"3058","Shangri-La","0069.HK","2804556157","0.78","Hong Kong"
"3059","PrairieSky Royalty","PSK.TO","2804505621","11.74","Canada"
"3060","Freenet","FNTN.F","2803364489","23.44","Germany"
"3061","National Health Investors","NHI","2801954560","61.11","United States"
"3062","Fonterra","FCG.NZ","2801797153","1.74","New Zealand"
"3063","Group 1 Automotive","GPI","2800642560","168.75","United States"
"3064","The AZEK Company","AZEK","2798996480","18.04","United States"
"3065","Silicon Motion","SIMO","2794110976","81.14","Hong Kong"
"3066","Rush Enterprises","RUSHA","2789970176","49.41","United States"
"3067","Agiliti","AGTI","2786787072","20.99","United States"
"3068","Sprinklr","CXM","2785438464","10.79","United States"
"3069","MGE Energy","MGEE","2785304832","77.02","United States"
"3070","EngageSmart","ESMT","2783951872","17.12","United States"
"3071","ReNew Power","RNW","2777537024","6.93","India"
"3072","Altarea","ALTA.PA","2777423670","137.36","France"
"3073","Comstock Resources","CRK","2776239616","11.92","United States"
"3074","Evergrande","3333.HK","2775510976","0.21","China"
"3075","Vienna Airport","FLW1.F","2775156352","32.78","Austria"
"3076","Brink's","BCO","2774833152","59.01","United States"
"3077","Mr. Cooper Group","COOP","2774434816","37.54","United States"
"3078","Alamos Gold","AGI","2774426880","7.05","Canada"
"3079","Verint Systems","VRNT","2772034816","42.86","United States"
"3080","Games Workshop Group","GAW.L","2769570731","8433.48","United Kingdom"
"3081","Phoenix Mills","PHOENIXLTD.NS","2767408914","15.5","India"
"3082","Corcept Therapeutics","CORT","2766776064","26.04","United States"
"3083","FormFactor","FORM","2766584576","35.44","United States"
"3084","Vienna Insurance Group","WSV2.F","2760389953","21.42","Austria"
"3085","Faurecia","EO.PA","2759651169","16.51","France"
"3086","Equitrans Midstream","ETRN","2758864128","6.38","United States"
"3087","Associated Banc-Corp","ASB","2757808640","18.38","United States"
"3088","Türkiye Is Bankasi","ISCTR.IS","2756371192","0.26","Turkey"
"3089","Moelis & Company","MC","2755783936","40.06","United States"
"3090","CONMED","CNMD","2754185216","93.28","United States"
"3091","SunPower","SPWR","2753974016","15.84","United States"
"3092","Adient","ADNT","2748582400","28.99","Ireland"
"3093","Allegheny Technologies","ATI","2746442752","22.13","United States"
"3094","Indian Bank","INDIANB.NS","2742825084","2.2","India"
"3095","Progyny","PGNY","2738098432","29.78","United States"
"3096","LondonMetric Property","LMP.L","2737865060","279.33","United Kingdom"
"3097","Texas Capital Bancshares","TCBI","2737531136","53.97","United States"
"3098","Aurubis","NDA.F","2734464837","62.34","Germany"
"3099","Methanex","MEOH","2732780032","36.86","Canada"
"3100","Beijing Airport","0694.HK","2730091209","0.6","China"
"3101","Indah Kiat Pulp & Paper","INKP.JK","2729100800","0.5","Indonesia"
"3102","The Navigator Company","NVG.LS","2728883033","3.84","Portugal"
"3103","Outfront Media","OUT","2727486208","16.63","United States"
"3104","Graham Holdings","GHC","2727011072","558.61","United States"
"3105","Tohoku Electric Power","9506.T","2725666025","5.45","Japan"
"3106","Herc Holdings","HRI","2722793216","91.1","United States"
"3107","Gibson Energy","GEI.TO","2719440294","18.45","Canada"
"3108","Polymetal","PM6.F","2713645820","5.73","Cyprus"
"3109","TechnipFMC","FTI","2713272064","6","United Kingdom"
"3110","Simmons First National","SFNC","2713030144","20.77","United States"
"3111","TripAdvisor","TRIP","2710010112","17.78","United States"
"3112","MakeMyTrip","MMYT","2708395520","25.86","India"
"3113","APL Apollo","APLAPOLLO.NS","2707916870","10.81","India"
"3114","Land and Houses","LH.BK","2707735571","0.23","Thailand"
"3115","Installed Building Products","IBP","2702519040","92.25","United States"
"3116","Zain Saudi Arabia","7030.SR","2701072015","3.01","Saudi Arabia"
"3117","Fate Therapeutics","FATE","2697401600","27.92","United States"
"3118","National Shipping Company of Saudi Arabia (Bahri)","4030.SR","2697187500","5.48","Saudi Arabia"
"3119","KB Home","KBH","2696035072","30.93","United States"
"3120","CarGurus","CARG","2695580928","22.77","United States"
"3121","Coforge","COFORGE.NS","2695351298","44.25","India"
"3122","Britvic","BVIC.L","2694470825","1012.73","United Kingdom"
"3123","Safestore","SAFE.L","2691627496","1261.16","United Kingdom"
"3124","Aixtron","AIXA.F","2690961054","23.98","Germany"
"3125","Spirit Airlines","SAVE","2690492672","24.77","United States"
"3126","Westports","5246.KL","2689213752","0.79","Malaysia"
"3127","Intercorp Financial Services","IFS","2688085248","23.29","Peru"
"3128","Wingstop Restaurants","WING","2688015616","89.97","United States"
"3129","Surgery Partners","SGRY","2685441536","29.87","United States"
"3130","Tata Chemicals","TATACHEM.NS","2675630039","10.5","India"
"3131","Insmed","INSM","2674790400","22.38","United States"
"3132","PJT Partners","PJT","2673664512","67.9","United States"
"3133","Endurance Technologies","ENDURANCE.NS","2671266770","18.99","India"
"3134","Whiting Petroleum","WLL","2669619712","68.03","United States"
"3135","Nerolac Paints","KANSAINER.NS","2667893860","4.95","India"
"3136","Steve Madden","SHOO","2667477760","33.4","United States"
"3137","Zee Entertainment","ZEEL.NS","2667437009","2.78","India"
"3138","Ryman Healthcare","RYM.NZ","2666298439","5.33","New Zealand"
"3139","NetLink Trust","CJLU.SI","2660993721","0.68","Singapore"
"3140","Mr Price Group","MRP.JO","2660669101","10.26","South Africa"
"3141","IDFC FIRST Bank","IDFCFIRSTB.NS","2659468798","0.43","India"
"3142","Cvent","CVT","2659315200","5.53","United States"
"3143","Vector Limited","VCT.NZ","2657093687","2.66","New Zealand"
"3144","Americanas","AMER3.SA","2656848906","2.95","Brazil"
"3145","Fisker","FSR","2655580416","8.94","United States"
"3146","TUI","TUI1.F","2654030126","1.49","Germany"
"3147","Jetblue Airways","JBLU","2651321088","8.27","United States"
"3148","GMR Group","GMRINFRA.NS","2649477625","0.44","India"
"3149","Tsuruha Holdings","3391.T","2648350218","54.54","Japan"
"3150","Champion REIT","2778.HK","2647617162","0.44","Hong Kong"
"3151","Atlas Corp","ATCO","2646108416","10.51","Canada"
"3152","Wizz Air","WIZZ.L","2643301558","2114.02","Jersey"
"3153","TAL Education Group","TAL","2641192704","4.07","China"
"3154","CorVel Corporation","CRVL","2637213696","150.29","United States"
"3155","Evertec","EVTC","2635385600","36.84","United States"
"3156","Whirlpool India","WHIRLPOOL.NS","2628778576","20.72","India"
"3157","Trupanion","TRUP","2626472192","64.5","United States"
"3158","Future plc","FUTR.L","2624565836","2171.66","United Kingdom"
"3159","Calix","CALX","2622916096","40.6","United States"
"3160","Escorts Limited","ESCORTS.NS","2622706391","19.88","India"
"3161","Emami","EMAMILTD.NS","2611123347","5.92","India"
"3162","John Wiley & Sons","WLY","2609082368","46.99","United States"
"3163","Federal Bank","FEDERALBNK.NS","2604823870","1.24","India"
"3164","Farfetch","FTCH","2604388352","6.83","United Kingdom"
"3165","PennyMac","PFSI","2600641792","47.77","United States"
"3166","Kennedy Wilson","KW","2600116480","18.87","United States"
"3167","Werner Enterprises","WERN","2599709696","39.96","United States"
"3168","Growthpoint Properties","GRT.JO","2597198628","0.76","South Africa"
"3169","MaxLinear","MXL","2594291456","33.43","United States"
"3170","J&J Snack Foods","JJSF","2593501184","135.26","United States"
"3171","Copa Holdings","CPA","2592221952","62.34","Panama"
"3172","QinetiQ","QQ.L","2590781833","447.65","United Kingdom"
"3173","Alignment Healthcare","ALHC","2589764096","13.83","United States"
"3174","Bottomline Technologies","EPAY","2586582528","56.99","United States"
"3175","Life Time Group","LTH","2586349056","13.35","United States"
"3176","Nova Measuring Instruments","NVMI","2584241152","90.01","Israel"
"3177","Chindata","CD","2579166464","7.03","China"
"3178","Razer","RAZFF","2575805440","0.27","United States"
"3179","Semen Indonesia","SMS2.F","2575544825","0.41","Indonesia"
"3180","Cal-Maine Foods","CALM","2575238656","52.62","United States"
"3181","AdaptHealth","AHCO","2574319872","19.17","United States"
"3182","Meritor","MTOR","2573829632","36.33","United States"
"3183","United Industrial Corporation","U06.SI","2567983726","1.79","Singapore"
"3184","General Insurance Corporation of India","GICRE.NS","2564062314","1.46","India"
"3185","Pacira Biosciences","PCRX","2562181120","56.39","United States"
"3186","Ermenegildo Zegna","ZGN","2561575936","10.57","Italy"
"3187","Multiplan Empreendimentos Imobiliários","MULT3.SA","2560122332","4.35","Brazil"
"3188","Atlantic Union Bankshares","AUB","2556480512","34.08","United States"
"3189","Mercury General","MCY","2554822400","46.14","United States"
"3190","Signet Jewelers","SIG","2554105600","54.91","Bermuda"
"3191","Mitra Keluarga","MIKA.JK","2553967266","0.18","Indonesia"
"3192","Banco del Bajío","BBAJIOO.MX","2552924623","2.15","Mexico"
"3193","Cano Health","CANO","2548312320","5.26","United States"
"3194","Grainger plc","GRI.L","2548307632","343.76","United Kingdom"
"3195","Arvinas","ARVN","2546651392","47.9","United States"
"3196","Cyfrowy Polsat","CP9.F","2545686138","4.42","Poland"
"3197","NuVasive","NUVA","2543243520","48.87","United States"
"3198","WSFS Financial","WSFS","2543079936","39.32","United States"
"3199","Belden","BDC","2542518784","57.45","United States"
"3200","Arçelik","ARCLK.IS","2539105212","4.1","Turkey"
"3201","Dream Industrial REIT","DIR-UN.TO","2538780319","9.3","Canada"
"3202","Viscofan","VIS.MC","2538700388","54.85","Spain"
"3203","MDC Holdings","MDC","2537999872","35.67","United States"
"3204","First Capital REIT","FCR-UN.TO","2535901267","11.54","Canada"
"3205","GoodRx","GDRX","2535348736","6.4","United States"
"3206","Hensoldt","HAG.F","2533936652","24.13","Germany"
"3207","nternational Bancshares Corp","IBOC","2533837056","40.11","United States"
"3208","Maple Leaf Foods","MFI.TO","2533414885","19.98","Canada"
"3209","Sanmina","SANM","2532331264","41.62","United States"
"3210","Verra Mobility","VRRM","2530063616","16.2","United States"
"3211","Hang Lung Group","0010.HK","2529753637","1.86","Hong Kong"
"3212","Fletcher Building","FLQ.F","2529624422","3.04","New Zealand"
"3213","Tianjin FAW","000927.SZ","2519292174","0.42","China"
"3214","Quaker Chemical Corporation","KWR","2518083072","140.58","United States"
"3215","Mercari","4385.T","2516815263","15.68","Japan"
"3216","Sonos","SONO","2504066560","19.58","United States"
"3217","Oil India","OIL.NS","2502075208","2.31","India"
"3218","Newmark","NMRK","2501079040","10.33","United States"
"3219","Boise Cascade","BCC","2498203904","63.33","United States"
"3220","BGF Retail","282330.KS","2490278197","144.16","South Korea"
"3221","Alliance Resource Partners","ARLP","2489206016","19.57","United States"
"3222","Albany International","AIN","2488499968","79","United States"
"3223","StoneCo","STNE","2484148224","7.97","Brazil"
"3224","SPX Corporation","SPXC","2483635712","54.33","United States"
"3225","LIC Housing Finance","LICHSGFIN.NS","2483336271","4.51","India"
"3226","Artisan Partners","APAM","2482961664","36.84","United States"
"3227","Kulicke and Soffa Industries","KLIC","2482873088","41.99","Singapore"
"3228","Tronox","TROX","2477569792","15.9","United States"
"3229","Ambu","AMBU-B.CO","2476900761","9.76","Denmark"
"3230","Plains GP","PAGP","2473470720","10.26","United States"
"3231","BIC","BB.PA","2472211692","55.05","France"
"3232","Neogen","NEOG","2471646976","22.92","United States"
"3233","Devyani International","DEVYANI.NS","2471362524","2.05","India"
"3234","ESAB","ESAB","2471011840","41.16","United States"
"3235","ACADIA Pharmaceuticals","ACAD","2469056512","15.3","United States"
"3236","Rotork","ROR.L","2468822385","283.37","United Kingdom"
"3237","Hub Group","HUBG","2467106048","71.18","United States"
"3238","Hatsun Agro Products","HATSUN.NS","2465325165","11.43","India"
"3239","Ingevity","NGVT","2462206720","63.54","United States"
"3240","Stagwell","STGW","2461396224","5.15","United States"
"3241","Baytex Energy","BTE.TO","2452717293","4.31","Canada"
"3242","Definitive Healthcare","DH","2452260352","25.11","United States"
"3243","U.S. Cellular","USM","2442678016","28.55","United States"
"3244","Travis Perkins","TPK.L","2442426046","1129.46","United Kingdom"
"3245","Eutelsat","ETL.PA","2441694279","10.38","France"
"3246","Ambarella","AMBA","2437780480","63.95","United States"
"3247","Forward Air","FWRD","2434744576","90.64","United States"
"3248","Groupe Lagardère","MMB.PA","2430159477","17.29","France"
"3249","Akbank","AKBNK.IS","2428227700","0.47","Turkey"
"3250","HUTCHMED","HCM","2427726592","14.04","Hong Kong"
"3251","Fulton Financial","FULT","2417537280","14.48","United States"
"3252","Frontier Airlines","ULCC","2417424896","11.11","United States"
"3253","Safehold","SAFE","2417278720","39.03","United States"
"3254","Ebro Foods","EBRO.MC","2416662910","15.71","Spain"
"3255","Ozon","OZON.ME","2416535296","11.6","United States"
"3256","Ultrapar Participacoes","UGP","2411359744","2.22","Brazil"
"3257","Krones","KRN.F","2407003383","75.01","Germany"
"3258","Entra","ENTRA.OL","2406614405","13.22","Norway"
"3259","Curevac","CVAC","2406375936","12.86","Germany"
"3260","Timken India","TIMKEN.NS","2405579864","31.96","India"
"3261","Fortis Healthcare","FORTIS.NS","2403786873","3.18","India"
"3262","Bank of India","BANKINDIA.NS","2399959585","0.58","India"
"3263","NETSCOUT","NTCT","2399931136","32.38","United States"
"3264","Covivio Hotels","COVH.PA","2390651045","16.14","France"
"3265","EnerSys","ENS","2387527168","58.73","United States"
"3266","Foot Locker","FL","2387500544","25.26","United States"
"3267","TreeHouse Foods","THS","2384155904","42.56","United States"
"3268","Herbalife","HLF","2381123072","21.98","United States"
"3269","Jungheinrich","JUN3.F","2380859463","22.85","Germany"
"3270","Tootsie Roll Industries","TR","2378635520","35.06","United States"
"3271","Owens & Minor","OMI","2373468416","31.19","United States"
"3272","HighPeak Energy","HPK","2370694400","21.83","United States"
"3273","Grupo Aeroportuario Centro Norte","OMAB","2370115840","49.1","Mexico"
"3274","Shaftesbury","SHB.L","2369749085","609.78","United Kingdom"
"3275","Badger Meter","BMI","2369301248","80.95","United States"
"3276","Altra Industrial Motion","AIMC","2368801792","36.41","United States"
"3277","Victoria's Secret & Co","VSCO","2364425216","28.46","United States"
"3278","Glaukos","GKOS","2362893312","49.92","United States"
"3279","Melco Resorts & Entertainment","MLCO","2362139904","5","Hong Kong"
"3280","Assura Plc","AGR.L","2358249032","79.28","United Kingdom"
"3281","Grindwell Norton","GRINDWELL.NS","2358168311","21.3","India"
"3282","Millicom","TIGO","2357964800","13.8","Luxembourg"
"3283","Claros Mortgage Trust","CMTG","2354910464","16.87","United States"
"3284","Delek Group","DLEKG.TA","2352419044","123.72","Israel"
"3285","Blue Dart Express","BLUEDART.NS","2352153206","99.13","India"
"3286","Mandarin Oriental","M04.SI","2350519040","1.86","Hong Kong"
"3287","Focus Financial Partners","FOCS","2347817216","35.92","United States"
"3288","GCP Applied Technologies","GCP","2345051136","31.69","United States"
"3289","National Vision Holdings","EYE","2344136704","28.79","United States"
"3290","Krispy Kreme","DNUT","2338811904","13.98","United States"
"3291","Wienerberger","WIB.F","2335295324","20.73","Austria"
"3292","The a2 Milk Company","ACOPY","2335251200","3.01","New Zealand"
"3293","Cedar Fair","FUN","2334998016","40.94","United States"
"3294","Rambus","RMBS","2334798592","21.18","United States"
"3295","LGI Homes","LGIH","2333260544","98.59","United States"
"3296","SKF India","SKFINDIA.NS","2331995084","47.17","India"
"3297","Vicor","VICR","2329339904","52.98","United States"
"3298","EFG International","EFGN.SW","2328046407","7.55","Switzerland"
"3299","Ströer","SAX.F","2325405410","40.24","Germany"
"3300","PagerDuty","PD","2323756800","26.46","United States"
"3301","St. Joe Company","JOE","2322919936","39.43","United States"
"3302","Crestwood Equity Partners","CEQP","2321994752","23.7","United States"
"3303","WD-40 Company","WDFC","2314818304","169.87","United States"
"3304","Pebblebrook Hotel Trust","PEB","2313478400","17.6","United States"
"3305","Kosmos Energy","KOS","2311347968","5.08","United States"
"3306","Greggs","GRG.L","2309495865","2263.19","United Kingdom"
"3307","Flywire","FLYW","2308338944","21.53","United States"
"3308","Oatly","OTLY","2307930368","3.9","Sweden"
"3309","Euronav","EURN","2307400192","11.44","Belgium"
"3310","Golub Capital","GBDC","2305387008","13.49","United States"
"3311","Rubis","RUI.PA","2304122015","22.39","France"
"3312","IronSource","IS","2303054080","2.26","Israel"
"3313","Sembcorp Marine","S51.SI","2299649511","0.07","Singapore"
"3314","Columbia Bank","COLB","2297843200","29.22","United States"
"3315","Hays plc","HAS.L","2292624555","138.6","United Kingdom"
"3316","SJM Holdings","0880.HK","2287120833","0.4","Hong Kong"
"3317","Freshpet","FRPT","2285848832","47.81","United States"
"3318","Winpak","WPK.TO","2284590688","35.15","Canada"
"3319","Ameresco","AMRC","2283740928","44.08","United States"
"3320","Rajesh Exports","RAJESHEXPO.NS","2283671270","7.73","India"
"3321","Innospec","IOSP","2282998272","92","United States"
"3322","Korea Gas","036460.KS","2280852481","26.57","South Korea"
"3323","The Foschini Group","TFG.JO","2278977090","7.07","South Africa"
"3324","AEON REIT Investment","3292.T","2274842690","1112.68","Japan"
"3325","United Natural Foods","UNFI","2274561792","39.02","United States"
"3326","Cactus Wellhead","WHD","2274192896","37.62","United States"
"3327","Central Garden & Pet","CENT","2269378048","43.2","United States"
"3328","Nordic Entertainment Group (NENT Group)","NENT-B.ST","2266194097","29.27","Sweden"
"3329","American Assets Trust","AAT","2265057280","29.53","United States"
"3330","OPC Energy","OPCE.TA","2265057076","10.7","Israel"
"3331","Interparfums","IPAR","2264649984","71.12","United States"
"3332","Virgin Money UK","VMUK.L","2260902452","156.96","United Kingdom"
"3333","Weber","WEBR","2260098816","7.87","United States"
"3334","Golar LNG","GLNG","2256949248","20.9","Bermuda"
"3335","Integer Holdings","ITGR","2252962816","68.06","United States"
"3336","Sanoma","SAA1V.HE","2251183686","13.8","Finland"
"3337","Globalstar","GSAT","2249999872","1.25","United States"
"3338","Chegg","CHGG","2249743872","17.87","United States"
"3339","Toho Gas","9533.T","2247322818","21.38","Japan"
"3340","Q2","QTWO","2245664000","39.26","United States"
"3341","Turkcell","TKC","2245541888","2.57","Turkey"
"3342","Sportradar","SRAD","2241889536","7.55","Switzerland"
"3343","Star Bulk Carriers","SBLK","2240695808","21.82","Greece"
"3344","Aurora Innovation","AUR","2240185344","1.97","United States"
"3345","Distell Group","DGH.JO","2236354550","10.04","South Africa"
"3346","UNITI","UNIT","2235909632","9.43","United States"
"3347","Kenon Holdings","KEN","2234580480","41.47","Singapore"
"3348","Alfen","ALFEN.AS","2233813012","102.97","Netherlands"
"3349","Jfrog","FROG","2232880128","22.6","United States"
"3350","Upstart","UPST","2230395904","26.31","United States"
"3351","Arbor Realty Trust","ABR","2230011904","13.92","United States"
"3352","AMP Limited","AMP.AX","2229953994","0.68","Australia"
"3353","Coursera","COUR","2227028480","15.46","United States"
"3354","Sunnova","NOVA","2226744064","19.43","United States"
"3355","Stepan Company","SCL","2226559744","99.56","United States"
"3356","Brady","BRC","2225751808","44.32","United States"
"3357","Chesapeake Utilities","CPK","2225485312","125.54","United States"
"3358","Four Corners Property Trust","FCPT","2224420352","27.64","United States"
"3359","Bavarian Nordic","BAVA.CO","2216915986","31.52","Denmark"
"3360","Plexus","PLXS","2208152832","79.65","United States"
"3361","Navient","NAVI","2207997696","14.93","United States"
"3362","Doosan Bobcat","241560.KS","2207232160","22.02","South Korea"
"3363","Kyndryl","KD","2205694720","9.77","United States"
"3364","Primary Health Properties","PHP.L","2205205282","164.35","United Kingdom"
"3365","LifeStance Health Group","LFST","2204762368","5.89","United States"
"3366","Grayscale Bitcoin Trust","GBTC","2203905024","12.54","United States"
"3367","MicroStrategy","MSTR","2203127552","195.01","United States"
"3368","MGP Ingredients","MGPI","2200768512","100.1","United States"
"3369","EVO Payments","EVOP","2197505024","25.1","United States"
"3370","Xerox","XRX","2195168768","14.18","United States"
"3371","Burford Capital","BUR","2194859264","10.02","Guernsey"
"3372","Ninety One Group","N91.L","2191659913","232.5","South Africa"
"3373","Harel Group","HARL.TA","2190735041","10.13","Israel"
"3374","ComfortDelGro","C52.SI","2188854263","1.01","Singapore"
"3375","Global Blood Therapeutics","GBT","2187624960","33.61","United States"
"3376","Vistry Group","VTY.L","2186404897","999.06","United Kingdom"
"3377","Jackson Financial","JXN","2184766976","25.13","United States"
"3378","SSP Group","SSPG.L","2184285638","274.46","United Kingdom"
"3379","Prestige Group","PRESTIGE.NS","2178806091","5.44","India"
"3380","Dr Lal PathLabs","LALPATHLAB.NS","2178620424","26.14","India"
"3381","Schrödinger","SDGR","2178251776","30.62","United States"
"3382","Electra","ELTR.TA","2176608320","565.7","Israel"
"3383","Liberty Oilfield Services","LBRT","2174207744","11.64","United States"
"3384","MVV Energie","MVV1.F","2173637695","32.88","Germany"
"3385","EQRx","EQRX","2172984064","4.46","United States"
"3386","Primo Water","PRMW","2171989504","13.14","United States"
"3387","CD Projekt","CDR.WA","2171712642","21.56","Poland"
"3388","Federal Signal","FSS","2171114752","35.82","United States"
"3389","Arcosa","ACA","2169617408","44.9","United States"
"3390","Sabancı Holding","SAHOL.IS","2167839522","1.08","Turkey"
"3391","Chimera Investment Corporation","CIM","2167804160","9.15","United States"
"3392","Axos Financial","AX","2164588032","36.28","United States"
"3393","Shutterstock","SSTK","2161164800","59.07","United States"
"3394","Nikola","NKLA","2160438016","5.13","United States"
"3395","Frontdoor","FTDR","2160094976","26.26","United States"
"3396","Alpha Metallurgical Resources","AMR","2159246848","115.39","United States"
"3397","Pan Ocean","028670.KS","2158524361","4.04","South Korea"
"3398","Green Thumb Industries","GTII.CN","2155667905","8.96","United States"
"3399","Hudson Pacific Properties","HPP","2155048704","14.76","United States"
"3400","Acer","2353.TW","2152198391","0.72","Taiwan"
"3401","Cyxtera Technologies","CYXT","2151720448","12.05","United States"
"3402","First Merchants Corporation","FRME","2148369408","36.13","United States"
"3403","Hanmi Pharmaceutical","008930.KS","2145326346","31.89","South Korea"
"3404","InMode","INMD","2143500800","25.8","Israel"
"3405","Super Group","SGHC","2142160768","4.37","Guernsey"
"3406","Twist Bioscience","TWST","2141407872","38.06","United States"
"3407","360 DigiTech","QFIN","2141021696","13.79","China"
"3408","CBIZ","CBZ","2140732672","41.07","United States"
"3409","Delek Logistics Partners","DKL","2139345664","49.21","United States"
"3410","Sun TV Network","SUNTV.NS","2137262304","5.42","India"
"3411","Nu Skin","NUS","2136931328","42.56","United States"
"3412","WH Smith","SMWH.L","2136474110","1632.02","United Kingdom"
"3413","Shimao Property","0813.HK","2136456868","0.56","Hong Kong"
"3414","Callon Petroleum","CPE","2133233408","34.58","United States"
"3415","JK Cement","JKCEMENT.NS","2133165068","27.61","India"
"3416","Excelerate Energy","EE","2131954560","19.69","United States"
"3417","MINISO Group","MNSO","2126360448","6.94","China"
"3418","Worthington Industries","WOR","2122914432","43.88","United States"
"3419","Compañía Cervecerías Unidas","CCU","2120941440","11.48","Chile"
"3420","CASIO","6952.T","2118268364","8.86","Japan"
"3421","Supermicro","SMCI","2116763264","40.78","United States"
"3422","Allegiant Air","ALGT","2110925568","116.52","United States"
"3423","Arch Resources","ARCH","2103378560","135.9","United States"
"3424","Kadant","KAI","2101723392","180.26","United States"
"3425","eXp World Holdings","EXPI","2100503168","14.05","United States"
"3426","HPH Trust (Hutchison Port)","NS8U.SI","2090664064","0.24","Singapore"
"3427","Itron","ITRI","2090412288","46.39","United States"
"3428","MillerKnoll","MLKN","2090365440","27.58","United States"
"3429","Revolve","RVLV","2089283712","28.5","United States"
"3430","Robertet","CBE.PA","2088357390","790.35","France"
"3431","Trulieve Cannabis","TRUL.CN","2085647695","11.32","United States"
"3432","Sunstone Hotel Investors","SHO","2084237952","9.75","United States"
"3433","Uniqa Insurance Group","UN9.F","2083586317","6.55","Austria"
"3434","Voltalia","VLTSA.PA","2081465211","21.87","France"
"3435","Keywords Studios","KWS.L","2079965691","2702.99","Ireland"
"3436","CompuGroup Medical","COP.DE","2077441931","39.7","Germany"
"3437","Yapı Kredi","YKBNK.IS","2077075347","0.25","Turkey"
"3438","Air Transport Services Group","ATSG","2074978816","27.9","United States"
"3439","Sage Therapeutics","SAGE","2064803200","34.96","United States"
"3440","CNO Financial Group","CNO","2063982976","17.81","United States"
"3441","Coca-Cola İçecek","CCOLA.IS","2059979058","8.1","Turkey"
"3442","Redrow","RDW.L","2059664220","584.82","United Kingdom"
"3443","Sabre","SABR","2059527296","6.31","United States"
"3444","Helios Technologies","HLIO","2059524992","63.37","United States"
"3445","CI Financial","CIXX","2056531456","10.69","Canada"
"3446","Luminar Technologies","LAZR","2053847296","5.76","United States"
"3447","Cracker Barrel","CBRL","2053480704","90.11","United States"
"3448","Lenzing","LEN.F","2052003974","75.31","Austria"
"3449","PowerSchool","PWSC","2049637120","12.96","United States"
"3450","Weis Markets","WMK","2049523584","76.2","United States"
"3451","Diversey","DSEY","2048887168","6.32","United Kingdom"
"3452","Siltronic","WAF.F","2048265524","68.28","Germany"
"3453","BioCryst Pharmaceuticals","BCRX","2045117184","11.02","United States"
"3454","Rosseti","RSTI.ME","2039412697","0.01","Russia"
"3455","Dana","DAN","2036126976","14.06","United States"
"3456","Software AG","SOW.F","2035284304","27.51","Germany"
"3457","Harmony Gold","HMY","2033890304","3.15","South Africa"
"3458","Seacoast Banking","SBCF","2031452800","33.08","United States"
"3459","Medifast","MED","2030567552","176.36","United States"
"3460","Apollo Medical Holdings","AMEH","2030304896","45","United States"
"3461","Macerich","MAC","2030076672","9.04","United States"
"3462","Golden Ocean Group","GOGL","2029748224","10.05","Bermuda"
"3463","Chorus","CNU.NZ","2026644674","4.44","New Zealand"
"3464","Energizer Holdings","ENR","2024933632","28.42","United States"
"3465","Gentherm","THRM","2023352960","61.07","United States"
"3466","Relay Therapeutics","RLAY","2022144000","18.61","United States"
"3467","Trainline","TRN.L","2022049605","420.66","United Kingdom"
"3468","Bachoco","IBA","2020499968","40.41","Mexico"
"3469","Ansell","ANN.AX","2019901781","15.83","Australia"
"3470","Jet2","JET2.L","2018407046","940.46","United Kingdom"
"3471","Empire State Realty Trust","ESRT","2018306304","7.04","United States"
"3472","Patria Investments","PAX","2018015872","13.71","Cayman Islands"
"3473","ams AG","DQW1.F","2017612967","7.6","Austria"
"3474","Hain Celestial","HAIN","2016851840","22.46","United States"
"3475","Minerals Technologies","MTX","2016517888","61.17","United States"
"3476","Kajaria Ceramics","KAJARIACER.NS","2011167658","12.61","India"
"3477","Olink Holding","OLK","2010374144","16.88","Sweden"
"3478","Red Rock Resorts","RRR","2008290176","32.67","United States"
"3479","Immofinanz","IMO1.F","2007386096","14.26","Austria"
"3480","Encore Wire","WIRE","2007096192","101.74","United States"
"3481","American Eagle Outfitters","AEO","2006566784","11.85","United States"
"3482","AeroVironment","AVAV","2005980288","80.41","United States"
"3483","TowneBank","TOWN","2003554560","27.55","United States"
"3484","Bowlero","BOWL","2003198336","11.69","United States"
"3485","Cavco Industries","CVCO","1997415040","224.6","United States"
"3486","TPG Capital","TPG","1997323392","25.26","United States"
"3487","Holly Energy Partners","HEP","1996487552","15.79","United States"
"3488","Yelp","YELP","1993977856","28.14","United States"
"3489","Formosa Sumco Technology","3532.TW","1988564145","5.13","Taiwan"
"3490","Boot Barn Holdings","BOOT","1987343872","66.83","United States"
"3491","Laureate Education","LAUR","1983807360","11.5","United States"
"3492","Aavas Financiers","AAVAS.NS","1982064155","25.1","India"
"3493","WaFd Bank","WAFD","1981762048","30.35","United States"
"3494","C3 AI","AI","1977988864","18.46","United States"
"3495","E2open","ETWO","1976555392","6.56","United States"
"3496","ContourGlobal","GLO.L","1975356816","300.74","United Kingdom"
"3497","Cranswick","CWK.L","1972416570","3639.65","United Kingdom"
"3498","Mednax","MD","1970364800","22.58","United States"
"3499","Kronos Worldwide","KRO","1969781632","17.06","United States"
"3500","Bread Financial","BFH","1969126784","39.56","United States"
"3501","Genus","GNS.L","1968006885","2900.31","United Kingdom"
"3502","Ballard Power Systems","BLDP","1967829632","6.6","Canada"
"3503","Retail Opportunity Investments","ROIC","1963649536","15.81","United States"
"3504","Fine Organics","FINEORG.NS","1962987062","64.02","India"
"3505","TRI Pointe Group","TPH","1962275712","18.97","United States"
"3506","Vtech","0303.HK","1961167102","7.76","Hong Kong"
"3507","PriceSmart","PSMT","1960492672","63.5","United States"
"3508","Park National Corp","PRK","1959828096","120.61","United States"
"3509","CSG International","CSGS","1956978560","60.33","United States"
"3510","Progress Software","PRGS","1956150912","45.01","United States"
"3511","Balfour Beatty","BBY.L","1955878615","315.71","United Kingdom"
"3512","Banner Bank","BANR","1955278464","56.88","United States"
"3513","ANGI Homeservices","ANGI","1954106496","3.89","United States"
"3514","LegalZoom","LZ","1953226496","9.86","United States"
"3515","Terex","TEX","1951488000","28.16","United States"
"3516","Kontoor Brands","KTB","1950199040","34.81","United States"
"3517","One Medical","ONEM","1948241920","10.04","United States"
"3518","mBank","MBK.WA","1944550463","45.88","Poland"
"3519","Toyo Tire","5105.T","1942732508","12.62","Japan"
"3520","ViaSat","VSAT","1942061312","26.09","United States"
"3521","GMS","GMS","1941713280","45.53","United States"
"3522","O-I Glass","OI","1940202752","12.42","United States"
"3523","Genworth Financial","GNW","1937366528","3.8","United States"
"3524","TeamViewer","TMV.DE","1937317647","9.63","Germany"
"3525","LiveRamp","RAMP","1937099648","27.96","United States"
"3526","NexTier Oilfield","NEX","1932765184","7.92","United States"
"3527","TuSimple","TSP","1932626048","8.65","United States"
"3528","AtriCure","ATRC","1931593984","41.73","United States"
"3529","Duck Creek Technologies","DCT","1926256640","14.53","United States"
"3530","Edgewell Personal Care","EPC","1925439488","36.47","United States"
"3531","Canada Goose","GOOS","1924352896","17.4","Canada"
"3532","NOS","PMV.F","1923965619","3.74","Portugal"
"3533","ZipRecruiter","ZIP","1922280192","16.31","United States"
"3534","Piper Sandler","PIPR","1920263424","107.82","United States"
"3535","Doosan Fuel Cell","336260.KS","1920080814","22.29","South Korea"
"3536","Arcus Biosciences","RCUS","1919189760","26.76","United States"
"3537","First Advantage","FA","1918164736","12.54","United States"
"3538","EverCommerce","EVCM","1916899584","9.8","United States"
"3539","Cargojet","CJT.TO","1916505891","102.7","Canada"
"3540","Dunelm Group","DNLM.L","1915723444","939.03","United Kingdom"
"3541","Fortress Transportation","FTAI","1915526272","19.28","United States"
"3542","InterDigital","IDCC","1912705152","61.96","United States"
"3543","Ramco Cements","RAMCOCEM.NS","1912138099","8.09","India"
"3544","Beyond Meat","BYND","1907333248","30.02","United States"
"3545","Playtech","PTEC.L","1906533899","637.12","Isle of Man"
"3546","Hecla Mining","HL","1905674880","3.52","United States"
"3547","Transocean","RIG","1903551616","2.8","Switzerland"
"3548","Goosehead Insurance","GSHD","1900541312","51.19","United States"
"3549","Silvergate Capital","SI","1898660736","60.02","United States"
"3550","Kennametal","KMT","1898204032","22.97","United States"
"3551","DCM Shriram","DCMSHRIRAM.NS","1895379057","12.13","India"
"3552","TechTarget","TTGT","1895362688","64.14","United States"
"3553","WesBanco","WSBC","1892013440","31.39","United States"
"3554","Cinemark Theatres","CNK","1889844736","15.69","United States"
"3555","Jumbo S.A.","5JB.F","1888941241","13.57","Greece"
"3556","SJW Group","SJW","1888911616","62.47","United States"
"3557","Babcock International Group","BAB.L","1888273637","373.47","United Kingdom"
"3558","RLJ Lodging Trust","RLJ","1883992704","11.24","United States"
"3559","The Beauty Health Company","SKIN","1883653120","12.51","United States"
"3560","Sanofi India Limited","SANOFI.NS","1882909512","81.68","India"
"3561","Flagstar Bank","FBC","1882235392","35.35","United States"
"3562","Maxar Technologies","MAXR","1881847040","25.53","United States"
"3563","ArcBest","ARCB","1881365888","76.84","United States"
"3564","Elkem","ELK.OL","1879287223","2.92","Norway"
"3565","Boral","BLD.AX","1879123239","1.7","Australia"
"3566","Plus500","P55.F","1878608571","18.9","Israel"
"3567","KAR Auction Services","KAR","1876469504","15.44","United States"
"3568","FB Financial","FBK","1876402304","39.73","United States"
"3569","BayWa","BYW.F","1873804935","54.5","Germany"
"3570","Victrex","VCT.L","1872514068","2152.65","United Kingdom"
"3571","Qt Group","QTCOM.HE","1869140690","75.01","Finland"
"3572","Trustmark","TRMK","1868493440","30.4","United States"
"3573","Carborundum Universal","CARBORUNIV.NS","1865410277","9.82","India"
"3574","First Financial Bank","FFBC","1863350400","19.73","United States"
"3575","ProSiebenSat.1 Media","PSM.F","1860502331","8.22","Germany"
"3576","McGrath RentCorp","MGRC","1860475392","76.42","United States"
"3577","WABCO India","WABCOINDIA.NS","1857603686","97.94","India"
"3578","Usiminas","USIM5.SA","1854462336","1.54","Brazil"
"3579","Mueller Water Products","MWA","1853680128","11.81","United States"
"3580","Trinity Industries","TRN","1851861376","22.22","United States"
"3581","Top Glove","BVA.SI","1851011287","0.23","Malaysia"
"3582","Masonite","DOOR","1850329984","82","United States"
"3583","TaskUs","TASK","1847597696","18.9","United States"
"3584","Shoals Technologies","SHLS","1847343232","16.44","United States"
"3585","Tofaş Türk Otomobil Fabrikası","TOASO.IS","1847087691","3.69","Turkey"
"3586","Rocket Lab","RKLB","1846496512","3.98","United States"
"3587","OPKO Health","OPK","1844672000","2.71","United States"
"3588","Indian Energy Exchange","IEX.NS","1842370716","2.05","India"
"3589","Scorpio Tankers","STNG","1841431040","31","Monaco"
"3590","CareTrust REIT","CTRE","1840634496","18.97","United States"
"3591","Gerresheimer","GXI.F","1840351051","58.27","Germany"
"3592","Close Brothers Group","CBG.L","1834643845","1204.1","United Kingdom"
"3593","Ironwood Pharmaceuticals","IRWD","1833364352","11.92","United States"
"3594","Canadian Solar","CSIQ","1829996288","28.47","Canada"
"3595","ForgeRock","FORG","1829740416","21.71","United States"
"3596","Nutex Health","NUTX","1825698944","2.82","United States"
"3597","KWS","KWS.F","1825037772","55.3","Germany"
"3598","JOYY","YY","1824529792","25.46","China"
"3599","Urban Edge Properties","UE","1824221824","14.9","United States"
"3600","ICF","ICFI","1819210880","96.8","United States"
"3601","Six Flags","SIX","1816167424","21.01","United States"
"3602","Constellium","CSTM","1814882304","12.81","France"
"3603","Stock Yards Bancorp","SYBT","1812795648","62.03","United States"
"3604","Österreichische Post","POST.VI","1810233018","26.8","Austria"
"3605","NV5 Global","NVEE","1809099648","116.75","United States"
"3606","Osisko Gold Royalties","OR","1808365184","9.78","Canada"
"3607","Sinch","SINCH.ST","1807343123","2.16","Sweden"
"3608","Urban Outfitters","URBN","1806961664","19.5","United States"
"3609","Paradox Interactive","PDX.ST","1806844178","16.81","Sweden"
"3610","Alembic Pharmaceuticals","APLLTD.NS","1803129525","9.17","India"
"3611","Xencor","XNCR","1799981824","30.23","United States"
"3612","NW Natural","NWN","1799291136","52.53","United States"
"3613","GrafTech","EAF","1795545600","6.9","United States"
"3614","Philip Morris ČR","TBK.F","1794372601","653.59","Czech Republic"
"3615","NexGen Energy","NXE","1794371712","3.59","Canada"
"3616","Kemira","KEMIRA.HE","1793194023","11.49","Finland"
"3617","Orange Polska","TPA1.F","1792699656","1.32","Poland"
"3618","Washington Real Estate Investment Trust","WRE","1791354624","20.49","United States"
"3619","Rattler Midstream","RTLR","1790941440","12.27","United States"
"3620","Iovance Biotherapeutics","IOVA","1788571904","11.38","United States"
"3621","Verano Holdings","VRNOF","1787499136","5.86","United States"
"3622","Spirent","SPT.L","1785874550","291.93","United Kingdom"
"3623","Compass","COMP","1784717824","4.18","United States"
"3624","IIFL Wealth Management","IIFLWAM.NS","1784458796","20.07","India"
"3625","secunet","YSN.F","1782446399","275.52","Germany"
"3626","SIGNA Sports United","SSU","1780395008","5.28","Germany"
"3627","Telecom Argentina","TEO","1778517248","4.13","Argentina"
"3628","Hexaware Technologies","HEXAWARE.NS","1778195381","5.92","India"
"3629","MONETA Money Bank","MM0.F","1777379169","3.42","Czech Republic"
"3630","Northern Oil and Gas","NOG","1773795712","22.27","United States"
"3631","Diamondrock Hospitality Company","DRH","1773283328","8.38","United States"
"3632","Shufersal","SAE.TA","1772469974","6.63","Israel"
"3633","First Majestic Silver","AG","1771575168","6.74","Canada"
"3634","InvenTrust Properties","IVT","1768953472","26.25","United States"
"3635","Cannae Holdings","CNNE","1768800256","20.83","United States"
"3636","Triple Flag Precious Metals","TFPM.TO","1768764865","11.34","Canada"
"3637","SolarWinds","SWI","1767248128","11.01","United States"
"3638","Konecranes","KCR.HE","1765626208","22.3","Finland"
"3639","Heartland Financial USA","HTLF","1765354368","41.67","United States"
"3640","Goodman Property Trust","GMT.NZ","1765256829","1.26","New Zealand"
"3641","Fever-Tree Drinks","FEVR.L","1764259592","1513.58","United Kingdom"
"3642","K12","LRN","1762274560","41.22","United States"
"3643","Dynavax Technologies","DVAX","1762052352","13.95","United States"
"3644","Bukalapak.com","BUKA.JK","1760685549","0.02","Indonesia"
"3645","Türk Telekom","TTKOM.IS","1759639644","0.5","Turkey"
"3646","Krystal Biotech","KRYS","1758057728","68.58","United States"
"3647","Centerra Gold","CGAU","1757953152","5.91","Canada"
"3648","Sandy Spring Bank","SASR","1754851840","38.79","United States"
"3649","Minera Valparaíso","MINERA.SN","1754824538","14.04","Chile"
"3650","Genesis Energy","GNE.NZ","1752510555","1.67","New Zealand"
"3651","Itaú CorpBanca","ITCB","1752267392","2.7","Chile"
"3652","Amphastar Pharmaceuticals","AMPH","1748688000","35.81","United States"
"3653","Lakeland Financial Corp","LKFN","1748120576","68.97","United States"
"3654","Veracyte","VCYT","1747551872","24.46","United States"
"3655","Telephone and Data Systems","TDS","1747497472","15.25","United States"
"3656","Ashmore Group","ASHM.L","1743895285","237.97","United Kingdom"
"3657","Hercules Capital","HTGC","1740499968","14.05","United States"
"3658","Great Portland Estates","GPE.L","1738139857","684.66","United Kingdom"
"3659","Plantronics","POLY","1736634112","39.74","United States"
"3660","Cargotec","CGCBV.HE","1735708831","25.6","Finland"
"3661","Immunocore","IMCR","1734374400","39.51","United Kingdom"
"3662","Jasa Marga","JSMR.JK","1733945566","0.24","Indonesia"
"3663","ESCO Technologies","ESE","1732785792","67.03","United States"
"3664","CONSOL Energy","CEIX","1732021376","49.75","United States"
"3665","Aareal Bank","ARL.F","1723741442","28.56","Germany"
"3666","Axcelis Technologies","ACLS","1723334656","52.19","United States"
"3667","Manchester United","MANU","1722941696","10.57","United Kingdom"
"3668","Asahi India Glass","ASAHIINDIA.NS","1722860745","7.09","India"
"3669","Virgin Galactic","SPCE","1720916480","6.66","United States"
"3670","Paramount Group","PGRE","1719552384","7.17","United States"
"3671","Pets at Home","PETS.L","1718229405","343.02","United Kingdom"
"3672","Kainos Group","KNOS.L","1716757836","1383.59","United Kingdom"
"3673","Fulgent Genetics","FLGT","1716216192","56.59","United States"
"3674","Olav Thon","OLT.OL","1715824302","16.56","Norway"
"3675","Xenon Pharmaceuticals","XENE","1714251904","32.28","Canada"
"3676","Gogo Inflight Internet","GOGO","1711390592","15.28","United States"
"3677","Adtalem Global Education","ATGE","1711390080","37.91","United States"
"3678","Olo","OLO","1710647552","10.68","United States"
"3679","Hilltop Holdings","HTH","1707892480","26.45","United States"
"3680","Pigeon","7956.T","1705981319","14.26","Japan"
"3681","New India Assurance","NIACL.NS","1705871114","1.04","India"
"3682","Ingles Markets","IMKTA","1705507200","89.79","United States"
"3683","Atlas Air Worldwide Holdings","AAWW","1705237376","60.49","United States"
"3684","CryoPort","CYRX","1698054400","34.39","United States"
"3685","Provident Financial Services","PFS","1697094784","22.5","United States"
"3686","Xenia Hotels & Resorts","XHR","1696998528","14.84","United States"
"3687","Madison Square Garden","MSGE","1696793728","49.6","United States"
"3688","KPIT Technologies","KPITTECH.NS","1695211664","6.18","India"
"3689","Semrush","SEMR","1691741056","11.99","United States"
"3690","Shake Shack","SHAK","1691114240","40.14","United States"
"3691","Vertex","VERX","1689601024","11.31","United States"
"3692","Quilter","QLT.L","1689024275","120.29","United Kingdom"
"3693","Ping Identity Holding","PING","1686947328","19.78","United States"
"3694","Shop Apotheke Europe","SAE.F","1685226377","91.8","Netherlands"
"3695","Perimeter Solutions","PRM","1683769088","10.32","United States"
"3696","Corbion","CRBN.AS","1683447505","28.56","Netherlands"
"3697","TANLA","TANLA.NS","1682294747","12.39","India"
"3698","Allscripts","MDRX","1682290048","14.5","United States"
"3699","N-Able","NABL","1682261376","9.35","United States"
"3700","XL Axiata","E5F.F","1682148070","0.13","Indonesia"
"3701","Hope Bancorp","HOPE","1681932160","13.97","United States"
"3702","CSW Industrials","CSWI","1678828416","107.09","United States"
"3703","Winnebago Industries","WGO","1674070912","52.72","United States"
"3704","National Aluminum & Alloy","NATIONALUM.NS","1673590464","0.91","India"
"3705","Strategic Education","STRA","1672085504","67","United States"
"3706","Faraday Future","FFIE","1671591808","5.53","United States"
"3707","B&G Foods","BGS","1671357568","23.34","United States"
"3708","Xometry","XMTR","1667821952","35.5","United States"
"3709","Array Technologies","ARRY","1666942592","11.1","United States"
"3710","Kratos Defense & Security Solutions","KTOS","1666223360","13.33","United States"
"3711","Amplitude","AMPL","1666108800","14.94","United States"
"3712","Nevro","NVRO","1664305024","47.2","United States"
"3713","Fortune REIT","0778.HK","1663040541","0.84","Hong Kong"
"3714","ImmunityBio","IBRX","1661470464","4.18","United States"
"3715","Birchcliff Energy","BIR.TO","1661247185","6.28","Canada"
"3716","e.l.f. Cosmetics","ELF","1660706816","31.77","United States"
"3717","Two Harbors Investment","TWO","1660489984","4.83","United States"
"3718","RWS Holdings","RWS.L","1659980268","426.25","United Kingdom"
"3719","Diagnosticos da America","DASA3.SA","1657927055","2.96","Brazil"
"3720","EVgo","EVGO","1657673088","6.26","United States"
"3721","Outokumpu","OUT1V.HE","1657433066","3.66","Finland"
"3722","Alvotech","ALVO","1656820096","6.8","Iceland"
"3723","Wolverine World Wide","WWW","1656661760","20.52","United States"
"3724","Tokai Carbon","5301.T","1656434850","7.36","Japan"
"3725","Great Eagle","0041.HK","1655518803","2.21","Hong Kong"
"3726","Kindred Group","KIND-SDB.ST","1654362148","7.43","Malta"
"3727","Impinj","PI","1653559168","65.15","United States"
"3728","PageGroup","PAGE.L","1650731538","502.32","United Kingdom"
"3729","Pactiv Evergreen","PTVE","1650535680","9.29","United States"
"3730","Apollo Tyres","APOLLOTYRE.NS","1649099365","2.6","India"
"3731","Axsome Therapeutics","AXSM","1648380160","42.36","United States"
"3732","Guaranty Trust Bank","9JO.F","1648136000","2.8","Nigeria"
"3733","Frontline","FRO","1646565888","8.09","Bermuda"
"3734","USA Compression Partners","USAC","1643730432","16.88","United States"
"3735","AUTO1","AG1.F","1643065790","7.63","Germany"
"3736","Noble Corporation","NE","1641848960","25.25","United Kingdom"
"3737","Victory Capital","VCTR","1641802112","23.94","United States"
"3738","NBT Bancorp","NBTB","1638419456","38.26","United States"
"3739","Hillman Solutions","HLMN","1636996480","8.43","United States"
"3740","Century Communities","CCS","1634851072","49.66","United States"
"3741","Tellurian","TELL","1633641088","2.88","United States"
"3742","Sterling Check","STER","1633064448","16.97","United States"
"3743","Credo Technology","CRDO","1632490368","11.24","United States"
"3744","DeNA","2432.T","1632241623","13.77","Japan"
"3745","Renasant Corp","RNST","1631723904","29.19","United States"
"3746","IIFL Finance","IIFL.NS","1630341264","4.29","India"
"3747","Paymentus","PAY","1626424960","13.4","United States"
"3748","EnPro Industries","NPO","1624911744","78.12","United States"
"3749","DSME (Daewoo Shipbuilding)","042660.KS","1624344363","15.14","South Korea"
"3750","Preferred Apartment Communities","APTS","1624227456","25","United States"
"3751","Northwest Bank","NWBI","1623788544","12.82","United States"
"3752","Compass Diversified Holdings","CODI","1623433856","23.14","United States"
"3753","Tivity Health","TVTY","1622802944","32.5","United States"
"3754","Aurinia Pharmaceuticals","AUPH","1621528448","11.44","Canada"
"3755","Exide Industries","EXIDEIND.NS","1617510174","1.9","India"
"3756","Tanger Factory Outlet Centers","SKT","1615508864","14.8","United States"
"3757","Knowles","KN","1613961600","17.59","United States"
"3758","Albioma","ABIO.PA","1612676312","50.16","France"
"3759","TODA corp","1860.T","1608687770","5.22","Japan"
"3760","Vector Group","VGR","1608256512","10.38","United States"
"3761","Bharat Dynamics","BDL.NS","1604642198","8.76","India"
"3762","Helios Towers","HTWS.L","1603223545","152.98","United Kingdom"
"3763","Acadia Realty Trust","AKR","1602992000","16","United States"
"3764","Liberty Latin America","LILA","1599785472","7.07","United States"
"3765","Sheela Foam","SFL.NS","1599448787","32.71","India"
"3766","Bank of N. T. Butterfield & Son","NTB","1597959296","32.22","Bermuda"
"3767","StoneX Group","SNEX","1597886720","79.15","United States"
"3768","Tenneco","TEN","1596728832","19.15","United States"
"3769","Everi Holdings","EVRI","1596550656","17.32","United States"
"3770","StepStone Group","STEP","1593342208","26.06","United States"
"3771","Digital Turbine","APPS","1591032576","16.17","United States"
"3772","Life Healthcare Group","LHC.JO","1589892726","1.09","South Africa"
"3773","Sparkassen Immobilien","T1L.F","1588436625","22.47","Austria"
"3774","WideOpenWest","WOW","1587429504","18.08","United States"
"3775","Gray Television","GTN","1586759808","16.63","United States"
"3776","Piedmont Office Realty Trust","PDM","1584803456","12.85","United States"
"3777","Delek US","DK","1582568064","22.37","United States"
"3778","Brandywine Realty Trust","BDN","1582319872","9.18","United States"
"3779","Expensify","EXFY","1581635200","19.38","United States"
"3780","Triumph Bancorp","TBK","1581038208","64.62","United States"
"3781","Wallbox","WBX","1580429440","8.54","Spain"
"3782","Xperi","XPER","1580055168","15.2","United States"
"3783","Vivid Seats","SEAT","1577331712","7.88","United States"
"3784","Chambal Fertilisers","CHAMBLFERT.NS","1576991057","3.79","India"
"3785","EchoStar","SATS","1574981120","18.82","United States"
"3786","ChemoCentryx","CCXI","1574798080","22.12","United States"
"3787","KCC Corp","002380.KS","1574744654","214.13","South Korea"
"3788","Archaea Energy","LFG","1574673280","13.59","United States"
"3789","SMA Solar Technology","S92.F","1573144454","45.05","Germany"
"3790","Wüstenrot & Württembergische","WUW.F","1572936849","16.79","Germany"
"3791","Emergent BioSolutions","EBS","1572875904","31.31","United States"
"3792","Embraer","ERJ","1571674112","8.05","Brazil"
"3793","Supernus Pharmaceuticals","SUPN","1570882176","29.41","United States"
"3794","Middlesex Water Company","MSEX","1569265792","89.37","United States"
"3795","NuStar Energy","NS","1568508672","14.22","United States"
"3796","Shinsegae","004170.KS","1568415485","159.45","South Korea"
"3797","FIGS","FIGS","1568127360","9.52","United States"
"3798","Hipgnosis Songs Fund","SONG.L","1567457823","129.41","United Kingdom"
"3799","Revolution Medicines","RVMD","1566571776","21.1","United States"
"3800","Bajaj Electricals","BAJAJELEC.NS","1565152078","13.62","India"
"3801","Office Depot","ODP","1563474304","31.78","United States"
"3802","Maytronics","MTRN.TA","1560759877","14.28","Israel"
"3803","Barnes Group","B","1560518272","30.78","United States"
"3804","Integral Ad Science","IAS","1560457088","10.06","United States"
"3805","Bank Danamon","BDMN.JK","1558811052","0.16","Indonesia"
"3806","TriCo Bancshares","TCBK","1557778688","46.32","United States"
"3807","Resolute Forest Products","RFP","1557057024","20.28","Canada"
"3808","Vaisala","VAIAS.HE","1555499375","42.94","Finland"
"3809","HiteJinro","000080.KS","1554355130","22.41","South Korea"
"3810","Hornbach Baumarkt","HBM.F","1550917374","48.77","Germany"
"3811","Nordex","NDX1.F","1549524497","9.68","Germany"
"3812","Myriad Genetics","MYGN","1549016960","19.28","United States"
"3813","Enterprise Financial Services Corp","EFSC","1548886528","41.59","United States"
"3814","Horace Mann Educators","HMN","1548694528","37.38","United States"
"3815","Veritex Holdings","VBTX","1548195584","28.69","United States"
"3816","Biotest","BIO.F","1547843958","42.53","Germany"
"3817","Happiest Minds Technologies","HAPPSTMNDS.NS","1547194858","10.52","India"
"3818","Zentalis Pharmaceuticals","ZNTL","1546743424","27.16","United States"
"3819","Enel Chile","ENIC","1545179648","1.12","Chile"
"3820","Sigma Lithium","SGML","1544602752","14.46","Canada"
"3821","Centennial Resource Development","CDEV","1543236992","5.42","United States"
"3822","Swissquote","SQN.SW","1542868372","102.96","Switzerland"
"3823","Ligand Pharmaceuticals","LGND","1542303104","91.47","United States"
"3824","Veritiv","VRTV","1542103552","105","United States"
"3825","Ascential","ASCL.L","1541431659","350.18","United Kingdom"
"3826","Buenaventura Mining Company","BVN","1540431232","6.07","Peru"
"3827","Payoneer","PAYO","1539955200","4.48","United States"
"3828","VIZIO","VZIO","1537107584","7.98","United States"
"3829","Allogene Therapeutics","ALLO","1535801984","10.7","United States"
"3830","Santam","SNT.JO","1533786289","14.58","South Africa"
"3831","Formula Systems","FORTY","1532535936","100.05","Israel"
"3832","Dave & Buster's","PLAY","1532148608","31.31","United States"
"3833","Bonheur ASA","BONHR.OL","1531447435","36.01","Norway"
"3834","Vista Outdoor","VSTO","1529401344","27.06","United States"
"3835","OSI Systems","OSIS","1526962944","89.59","United States"
"3836","Radico Khaitan","RADICO.NS","1524684374","11.4","India"
"3837","Eve Air Mobility","EVEX","1522552320","5.76","United States"
"3838","PRA Group","PRAA","1520758528","38.22","United States"
"3839","Sweetgreen","SG","1520609536","13.88","United States"
"3840","Tabcorp","TAH.AX","1519656356","0.68","Australia"
"3841","Lundin Gold","LUG.TO","1517269847","6.45","Canada"
"3842","First National of Nebraska","FINN","1517103616","14100","United States"
"3843","FuelCell Energy","FCEL","1515507328","3.92","United States"
"3844","SES AI","SES","1513199744","4.35","United States"
"3845","US Ecology","ECOL","1512275328","47.99","United States"
"3846","Tilray","TLRY","1511920896","3.15","Canada"
"3847","The Chefs' Warehouse","CHEF","1511697280","39.54","United States"
"3848","Apollo Commercial Real Estate","ARI","1511353344","10.75","United States"
"3849","Griffon Corporation","GFF","1510780288","26.49","United States"
"3850","U.S. Physical Therapy","USPH","1510380160","116.26","United States"
"3851","KIOCL","KIOCL.NS","1508905182","2.48","India"
"3852","BRP Group","BRP","1506571136","25.49","United States"
"3853","Getnet","GET","1502711296","1.61","Brazil"
"3854","Borregaard","BRG.OL","1501250876","15.05","Norway"
"3855","CenturyPly","CENTURYPLY.NS","1500045318","6.73","India"
"3856","Gogoro","GGR","1499984640","6.27","Taiwan"
"3857","Global Net Lease","GNL","1498513280","14.12","United States"
"3858","Westamerica Bancorporation","WABC","1497774464","55.71","United States"
"3859","Tiger Brands","TBS.JO","1495834019","8.82","South Africa"
"3860","Fiskars","FSKRS.HE","1493281721","18.42","Finland"
"3861","Sinclair Broadcast","SBGI","1492016512","21.24","United States"
"3862","Udemy","UDMY","1491515520","10.68","United States"
"3863","Eagle Bancorp","EGBN","1489483648","46.43","United States"
"3864","Hongkong and Shanghai Hotels","0045.HK","1489397053","0.9","Hong Kong"
"3865","Bloomin' Brands","BLMN","1489321728","16.79","United States"
"3866","CI&T","CINT","1489270912","11.21","Brazil"
"3867","Travere Therapeutics","TVTX","1488137728","23.43","United States"
"3868","Magellan Financial Group","MFG.AX","1487668557","8.04","Australia"
"3869","MYR Group","MYRG","1485172992","87.34","United States"
"3870","Palomar Holdings","PLMR","1484738688","58.97","United States"
"3871","Elgi Equipments","ELGIEQUIP.NS","1482342076","4.69","India"
"3872","IndiaMART","INDIAMART.NS","1481713056","48.4","India"
"3873","Evraz","EVZ.F","1481424764","1.02","Russia"
"3874","NovaGold Resources","NG","1480808704","4.43","Canada"
"3875","Pfeiffer Vacuum","PFV.F","1480156477","148.62","Germany"
"3876","CDSL","CDSL.NS","1480004861","14.16","India"
"3877","Materion","MTRN","1479897600","72.15","United States"
"3878","AAR","AIR","1473333888","41.86","United States"
"3879","PeptiDream","4587.T","1473071297","11.35","Japan"
"3880","Brigham Minerals","MNRL","1469804288","23.36","United States"
"3881","Monro","MNRO","1469242880","44.46","United States"
"3882","Lindsay Corporation","LNN","1466079232","133.53","United States"
"3883","Formosa Taffeta","1434.TW","1465909961","0.87","Taiwan"
"3884","Ratnamani Metals & Tubes","RATNAMANI.NS","1464598960","20.9","India"
"3885","XPEL","XPEL","1464020096","53.02","United States"
"3886","Korian","KORI.PA","1462954538","14.15","France"
"3887","Green Plains","GPRE","1462873856","27.18","United States"
"3888","NMI Holdings","NMIH","1459899776","16.96","United States"
"3889","Natco Pharma","NATCOPHARM.NS","1458930460","7.99","India"
"3890","Trinseo","TSE","1456897408","40.3","United States"
"3891","Warrior Met Coal","HCC","1455070592","28.17","United States"
"3892","Koza Gold","KOZAL.IS","1455057780","9.54","Turkey"
"3893","HNI Corporation","HNI","1454239744","34.31","United States"
"3894","Dürr","DUE.F","1454131741","20.98","Germany"
"3895","Coface","COFA.PA","1453489231","9.73","France"
"3896","PVR Cinemas","PVR.NS","1449155143","23.75","India"
"3897","The Cheesecake Factory","CAKE","1447297536","27.42","United States"
"3898","Nextdoor","KIND","1447157888","3.75","United States"
"3899","Fresh Del Monte Produce","FDP","1446999936","30.26","Cayman Islands"
"3900","GAG Immobilien","GWK3.HM","1446425355","90.5","Germany"
"3901","BASF India","BASF.NS","1445811494","33.38","India"
"3902","Sovos Brands","SOVO","1443807488","14.31","United States"
"3903","Iveco Group","IVG.MI","1443216024","5.09","Italy"
"3904","Türkiye Kalkınma","KLNMA.IS","1443037229","0.72","Turkey"
"3905","Yanlord","Z25.SI","1442575478","0.75","Singapore"
"3906","Remitly","RELY","1442253440","8.68","United States"
"3907","Cricut","CRCT","1441810432","6.5","United States"
"3908","VakıfBank","VAKBN.IS","1440778876","0.2","Turkey"
"3909","Meridian Bioscience","VIVO","1437204480","32.86","United States"
"3910","Sixth Street Specialty Lending","TSLX","1435774464","18.82","United States"
"3911","Orpea","ORP.PA","1435024410","22.22","France"
"3912","Casino Guichard-Perrachon","CO.PA","1434782697","13.28","France"
"3913","Montauk Renewables","MNTK","1434603904","9.99","United States"
"3914","Safety Insurance","SAFT","1432452992","97.17","United States"
"3915","Marcus & Millichap","MMI","1431911424","36.82","United States"
"3916","Rackspace Technology","RXT","1431739392","6.79","United States"
"3917","CS Disco","LAW","1430691584","24.4","United States"
"3918","GlobalData","DATA.L","1429988784","1202.91","United Kingdom"
"3919","Sonic Automotive","SAH","1429687552","36.14","United States"
"3920","Addus HomeCare","ADUS","1423604608","88.58","United States"
"3921","Flex Lng","FLNG","1423368832","26.79","Bermuda"
"3922","Ready Capital","RC","1422579712","12.25","United States"
"3923","Sana Biotechnology","SANA","1418716672","7.48","United States"
"3924","Live Oak Bank","LOB","1418011264","32.19","United States"
"3925","Exclusive Networks","EXN.PA","1416773245","15.3","France"
"3926","YTL Corporation Berhad","1773.T","1415781086","0.12","Malaysia"
"3927","Nokian Tyres","TYRES.HE","1414902347","10.24","Finland"
"3928","Summerset Holdings","SUM.NZ","1413866667","6.12","New Zealand"
"3929","Green Dot","GDOT","1409524992","26","United States"
"3930","TF1","TFI.PA","1407969882","6.45","France"
"3931","PIERER Mobility","PMAG.F","1405790858","61.34","Austria"
"3932","Fastly","FSLY","1404857984","11.62","United States"
"3933","Sapiens","SPNS","1404685056","25.49","Israel"
"3934","Galaxy Digital Holdings","7LX.F","1404680623","4.18","United States"
"3935","Silk Road Medical","SILK","1401495552","39.91","United States"
"3936","Banco de Brasília","BSLI3.SA","1400369349","3.69","Brazil"
"3937","Deutsche EuroShop","DEQ.F","1397817404","22.6","Germany"
"3938","Prothena","PRTA","1397165056","29.85","Ireland"
"3939","P10","PX","1396940544","11.92","United States"
"3940","Aris Water Solutions","ARIS","1396896128","16.38","United States"
"3941","Ceres Power","CWR.L","1394593845","710.1","United Kingdom"
"3942","AJ Bell","AJB.L","1394514272","339.24","United Kingdom"
"3943","Taro Pharmaceutical","TARO","1394399744","37.1","Israel"
"3944","ePlus","PLUS","1392958080","51.94","United States"
"3945","Marten Transport","MRTN","1392270976","16.99","United States"
"3946","LTC Properties","LTC","1391066880","39.14","United States"
"3947","Partner Communications","PTNR","1390326400","7.51","Israel"
"3948","Buckle","BKE","1390133504","27.75","United States"
"3949","TAG Immobilien","TEG.F","1389616780","8.97","Germany"
"3950","Oxford Industries","OXM","1387061120","87.08","United States"
"3951","Jeld-Wen","JELD","1384575104","15.9","United States"
"3952","ITM Power","ITM.L","1383958445","225.71","United Kingdom"
"3953","City Union Bank","CUB.NS","1380419641","1.87","India"
"3954","Stewart Information Services","STC","1379488000","51.06","United States"
"3955","TDCX","TDCX","1377460352","9.45","Singapore"
"3956","Janus International Group","JBI","1376217216","9.39","United States"
"3957","Bank of Maharashtra","MAHABANK.NS","1375592720","0.2","India"
"3958","Ladder Cap","LADR","1375269888","10.81","United States"
"3959","Marshalls plc","MSLH.L","1374161528","543.21","United Kingdom"
"3960","Embecta","EMBC","1373860864","23.77","United States"
"3961","Bank Islam Malaysia","BIMB.KL","1373345372","0.77","Malaysia"
"3962","AvidXchange","AVDX","1372614144","6.94","United States"
"3963","SJVN","SJVN.NS","1371584505","0.35","India"
"3964","PROCEPT BioRobotics","PRCT","1364955008","30.9","United States"
"3965","Radius Global Infrastructure","RADI","1360396032","14.67","United States"
"3966","GasLog","GLOG-PA","1359752320","24.85","Greece"
"3967","PennyMac Mortgage Investment Trust","PMT","1359535360","14.79","United States"
"3968","Kforce","KFRC","1359299328","63.57","United States"
"3969","BigCommerce","BIGC","1357537152","18.68","United States"
"3970","Criteo","CRTO","1357390720","22.49","France"
"3971","Seadrill","SDRL.OL","1356999706","27.14","Bermuda"
"3972","Recursion Pharmaceuticals","RXRX","1355415296","7.88","United States"
"3973","Indian Telephone Industries","ITI.NS","1355368142","1.44","India"
"3974","BGC Partners","BGCP","1352702464","3.7","United States"
"3975","Mallplaza","MALLPLAZA.SN","1352130213","0.69","Chile"
"3976","THG (The Hut Group)","THG.L","1351916376","90.9","United Kingdom"
"3977","Arcos Dorados Holdings","ARCO","1351268736","6.42","Uruguay"
"3978","World Fuel Services","INT","1350558592","21.43","United States"
"3979","Lyell Immunopharma","LYEL","1350050560","5.49","United States"
"3980","BridgeBio Pharma","BBIO","1349923200","9.14","United States"
"3981","Costamare","CMRE","1348965760","10.87","Monaco"
"3982","Glenmark Pharmaceuticals","GLENMARK.NS","1347881922","4.78","India"
"3983","Precinct Properties","PCT.NZ","1347757212","0.85","New Zealand"
"3984","Ecovyst","ECVT","1346747776","9.71","United States"
"3985","Sally Beauty Holdings","SBH","1346072576","12.58","United States"
"3986","CoreCivic","CXW","1345924736","11.33","United States"
"3987","Sierra Oncology","SRRA","1342822784","54.99","Canada"
"3988","Momentive Global","MNTV","1342786432","8.95","United States"
"3989","Universal Corporation","UVV","1342356992","54.58","United States"
"3990","Huron Consulting","HURN","1341838464","63.11","United States"
"3991","Methode Electronics","MEI","1341782016","35.03","United States"
"3992","Paysafe","PSFE","1340694656","1.85","United States"
"3993","Galaxy Surfactants","GALAXYSURF.NS","1340300912","37.79","India"
"3994","Trustpower","TPW.NZ","1336635392","4.27","New Zealand"
"3995","Secure Energy Services","SES.TO","1334918365","4.31","Canada"
"3996","SpringWorks Therapeutics","SWTX","1334666752","27.01","United States"
"3997","UCT (Ultra Clean Holdings)","UCTT","1332705024","29.55","United States"
"3998","Terveystalo","TTALO.HE","1331017878","10.54","Finland"
"3999","Halkbank","HALKB.IS","1330867997","0.27","Turkey"
"4000","Adaptive Biotechnologies","ADPT","1328409600","9.34","United States"
"4001","Healthcare Services Group","HCSG","1327465472","17.93","United States"
"4002","Atos","ATO.PA","1326919304","10.95","France"
"4003","JYP Entertainment","035900.KQ","1326233496","40.07","South Korea"
"4004","Algoma Steel","ASTL","1325952000","9","Canada"
"4005","Gibraltar Industries","ROCK","1323537664","40.36","United States"
"4006","KEC International","KEC.NS","1322495667","5.14","India"
"4007","Braves Group","BATRK","1322490112","24.77","United States"
"4008","SpareBank 1","SPOL.OL","1320775534","11.4","Norway"
"4009","RPC","RES","1316174080","6.08","United States"
"4010","Vaxcyte","PCVX","1316142464","22.57","United States"
"4011","Synthomer","SYNT.L","1314480686","276","United Kingdom"
"4012","Warby Parker","WRBY","1313798528","11.43","United States"
"4013","Centerspace","CSR","1313729024","80.29","United States"
"4014","Enovix","ENVX","1312626304","8.37","United States"
"4015","Granite Construction","GVA","1311484800","28.91","United States"
"4016","Holley","HLLY","1310678656","11.11","United States"
"4017","Fiverr","FVRR","1308727552","35.25","Israel"
"4018","Kinetik","KNTK","1307154048","34.36","United States"
"4019","Day One Biopharmaceuticals","DAWN","1304481920","18.14","United States"
"4020","Franchise Group","FRG","1304456064","32.33","United States"
"4021","NaaS Technology","NAAS","1304320128","6.09","China"
"4022","Avid Technology","AVID","1302383232","28.96","United States"
"4023","GB Group (GBG)","GBG.L","1299213617","515.64","United Kingdom"
"4024","Textainer Group","TGH","1297929216","27.03","Bermuda"
"4025","Sylvamo","SLVM","1296869248","29.4","United States"
"4026","Mirion Technologies","MIR","1295696384","6.23","United States"
"4027","RSA Insurance Group","RSAB.L","1294629115","126.89","United Kingdom"
"4028","AssetMark","AMK","1293782528","17.58","United States"
"4029","Skycity Entertainment Group","SKC.NZ","1292813903","1.6","New Zealand"
"4030","Redington India","REDINGTON.NS","1291498920","1.65","India"
"4031","First Commonwealth Financial Corp","FCF","1291196928","13.69","United States"
"4032","IVERIC bio","ISEE","1291086720","11.09","United States"
"4033","First Busey","BUSE","1290715648","23.35","United States"
"4034","Asseco","SFB1.F","1287777432","15.52","Poland"
"4035","CommScope","COMM","1286054400","6.21","United States"
"4036","AVI Limited","AVI.JO","1283981483","3.89","South Africa"
"4037","Jastrzebska Spólka Weglowa","JSW.WA","1283758035","10.93","Poland"
"4038","Alexander & Baldwin","ALEX","1283535872","17.66","United States"
"4039","CareDx","CDNA","1283160704","24.11","United States"
"4040","Sri Trang Gloves","STGT.BK","1281773296","0.45","Thailand"
"4041","Tamarack Valley Energy","TVE.TO","1280839805","2.9","Canada"
"4042","Gamma Communications","GAMA.L","1280630803","1328.91","United Kingdom"
"4043","ProAssurance","PRA","1279313792","23.67","United States"
"4044","Protolabs","PRLB","1278843520","46.51","United States"
"4045","Newegg","NEGG","1278099712","3.48","United States"
"4046","Wacker Neuson","WAC.F","1278064105","17.73","Germany"
"4047","Avanos Medical","AVNS","1275879296","26.96","United States"
"4048","Weatherford International","WFRD","1275755776","18.09","United States"
"4049","USANA","USNA","1274857472","66.44","United States"
"4050","National Express Group","NEX.L","1273955873","204.8","United Kingdom"
"4051","Cohu","COHU","1272273280","26.16","United States"
"4052","3D Systems","DDD","1272098944","9.76","United States"
"4053","Exscientia","EXAI","1268661376","10.45","United Kingdom"
"4054","LendingClub","LC","1268227584","12.41","United States"
"4055","Carpenter Technology","CRS","1267313280","26.25","United States"
"4056","Getty Realty","GTY","1266464256","27.1","United States"
"4057","Global Industrial Company","GIC","1266035200","33.39","United States"
"4058","Agios Pharmaceuticals","AGIO","1265075712","23.09","United States"
"4059","SFL Corp","SFL","1264970752","9.13","Bermuda"
"4060","Capitol Federal Savings Bank","CFFN","1264969088","9.11","United States"
"4061","PostNL","PNL.AS","1264238817","2.45","Netherlands"
"4062","Advantage Energy","AAV.TO","1263933785","6.66","Canada"
"4063","KKR Real Estate Finance Trust","KREF","1263635072","17.87","United States"
"4064","Equinox Gold","EQX","1263464448","4.14","Canada"
"4065","Yatsen Holding","YSG","1263439104","2","China"
"4066","Veris Residential","VRE","1261654144","12.65","United States"
"4067","Fila","081660.KS","1261551315","20.99","South Korea"
"4068","Jack in the Box","JACK","1261286784","59.93","United States"
"4069","Advantage Solutions","ADV","1260899584","3.96","United States"
"4070","Patrick Industries","PATK","1260433024","54.79","United States"
"4071","23andMe","ME","1259930240","2.81","United States"
"4072","Zydus Wellness","ZYDUSWELL.NS","1258304052","19.74","India"
"4073","Arcutis Biotherapeutics","ARQT","1257170176","24.45","United States"
"4074","East India Distilleries Parry","EIDPARRY.NS","1256684260","7.08","India"
"4075","Nexters","GDEV","1253816832","6.38","Cyprus"
"4076","Virtus Investment Partners","VRTS","1253245568","167.7","United States"
"4077","Budimex","BDX.WA","1253033963","49.08","Poland"
"4078","OFG Bancorp","OFG","1249058560","25.7","United States"
"4079","Establishment Labs","ESTA","1248606464","51.6","Costa Rica"
"4080","Phreesia","PHR","1248080512","23.89","United States"
"4081","Vericel","VCEL","1245039744","26.42","United States"
"4082","Nongshim","004370.KS","1244862845","215.28","South Korea"
"4083","John Wood Group","WG.L","1243062136","174.43","United Kingdom"
"4084","Amylyx Pharmaceuticals","AMLX","1241143808","21.2","United States"
"4085","Open Lending","LPRO","1238198656","9.81","United States"
"4086","PROS","PRO","1238136064","27.41","United States"
"4087","First Bancorp","FBNC","1238103680","34.73","United States"
"4088","Custom Truck One Source","CTOS","1237949952","5","United States"
"4089","M/I Homes","MHO","1237776512","43.76","United States"
"4090","Agilysys","AGYS","1236602624","49.99","United States"
"4091","Punjab & Sind Bank","PSB.NS","1236076293","0.18","India"
"4092","AMC Networks","AMCX","1234562176","28.77","United States"
"4093","Corsair Gaming","CRSR","1234121856","12.94","United States"
"4094","Membership Collective","MCG","1233339136","6.12","United Kingdom"
"4095","Rent-A-Center","RCII","1233131520","20.85","United States"
"4096","Veidekke","VEI.OL","1232361306","9.13","Norway"
"4097","Compañía de Acero del Pacífico","CAP.SN","1231499893","8.24","Chile"
"4098","Siam City Cement (INSEE)","SCCC.BK","1231098709","4.13","Thailand"
"4099","Russel Metals","RUS.TO","1228208735","19.14","Canada"
"4100","Repay Holdings","RPAY","1228093824","13.45","United States"
"4101","Extreme Networks","EXTR","1227241728","9.38","United States"
"4102","Archrock","AROC","1226974720","7.91","United States"
"4103","Z Energy","ZEL.NZ","1224995800","2.35","New Zealand"
"4104","B. Riley Financial","RILY","1224930816","43.86","United States"
"4105","City Holding Company","CHCO","1224753152","81.85","United States"
"4106","Alkami Technology","ALKT","1223149056","13.52","United States"
"4107","Danaos","DAC","1221341312","58.96","Greece"
"4108","Jenoptik","JEN.F","1221309587","21.34","Germany"
"4109","Zuora","ZUO","1220940032","9.45","United States"
"4110","tuya","TUYA","1220019584","2.18","China"
"4111","Bilfinger","GBF.F","1218448282","29.92","Germany"
"4112","Miramar Hotel and Investment","0071.HK","1216478881","1.76","Hong Kong"
"4113","Lemonade","LMND","1215212544","19.67","United States"
"4114","Infinera","INFN","1214775808","5.65","United States"
"4115","Momentum Metropolitan","MTM.JO","1213576869","0.85","South Africa"
"4116","Forge Global","FRGE","1211745408","7.16","United States"
"4117","Valneva SE","VALN","1209576192","20.64","France"
"4118","Steelcase","SCS","1209372544","10.73","United States"
"4119","Planet Labs","PL","1209091584","4.5","United States"
"4120","Anywhere Real Estate","HOUS","1207574784","10.22","United States"
"4121","ModivCare","MODV","1206496768","85.89","United States"
"4122","Mechel PAO","MTL","1206171008","2.25","Russia"
"4123","TTM Technologies","TTMI","1206083200","11.94","United States"
"4124","Bytes Technology","BYIT.L","1205005152","493.77","United Kingdom"
"4125","Astra Agro Lestari","AALI.JK","1204135416","0.63","Indonesia"
"4126","V-Guard Industries","VGUARD.NS","1201954226","2.79","India"
"4127","NLC India","NLCINDIA.NS","1201633689","0.87","India"
"4128","Celestica","CLS","1201379456","9.71","Canada"
"4129","Southside Bancshares","SBSI","1200395392","37.37","United States"
"4130","CropEnergies","CE2.F","1198221579","13.66","Germany"
"4131","Dime Community Bancshares","DCOM","1197129088","30.51","United States"
"4132","AST SpaceMobile","ASTS","1196864384","6.59","United States"
"4133","ASOS","ASC.L","1196440096","1110.2","United Kingdom"
"4134","SM Entertainment","041510.KQ","1196343692","51.24","South Korea"
"4135","Salzgitter","SZG.F","1194325848","22.08","Germany"
"4136","Valhi","VHI","1193576320","42.21","United States"
"4137","Argo Group","ARGO","1191725056","34.09","Bermuda"
"4138","Kornit Digital","KRNT","1190352128","23.91","Israel"
"4139","Hornbach Holding","HBH.F","1189915543","74.41","Germany"
"4140","Revenio","REG1V.HE","1188698096","44.75","Finland"
"4141","Meta Financial Group","CASH","1188401536","40.47","United States"
"4142","Utz Brands","UTZ","1186714752","14.7","United States"
"4143","Mixi","2121.T","1186504024","16.35","Japan"
"4144","Hypoport","HYQ.F","1184694379","188.03","Germany"
"4145","Scholastic","SCHL","1182316672","34.35","United States"
"4146","stem","STEM","1181263872","7.66","United States"
"4147","Earthstone Energy","ESTE","1180981632","11.32","United States"
"4148","Rush Street Interactive","RSI","1180546048","5.37","United States"
"4149","Berkshire Hills Bancorp","BHLB","1180245632","24.94","United States"
"4150","American Well","AMWL","1180002688","4.35","United States"
"4151","Bodycote","BOY.L","1176559160","614.53","United Kingdom"
"4152","Kaiser Aluminum","KALU","1174532480","73.85","United States"
"4153","Cancom","COK.F","1172913488","30.43","Germany"
"4154","Kymera Therapeutics","KYMR","1172070400","22.66","United States"
"4155","Inter Cars","CAR.WA","1171321748","82.67","Poland"
"4156","Veru","VERU","1171085824","14.63","United States"
"4157","3R Petroleum","RRRP3.SA","1168244594","5.77","Brazil"
"4158","Malibu Boats","MBUU","1167856512","56.96","United States"
"4159","Pampa Energía","PAM","1165738752","20.94","Argentina"
"4160","Celldex Therapeutics","CLDX","1165117184","24.92","United States"
"4161","iStar","STAR","1163183104","14.04","United States"
"4162","Clover Health Investments","CLOV","1163052928","2.46","United States"
"4163","AMAG Austria Metall","AM8.F","1162766544","31.67","Austria"
"4164","Myovant Sciences","MYOV","1162574848","12.2","United Kingdom"
"4165","Yacimientos Petrolíferos Fiscales","YPF","1162239872","2.96","Argentina"
"4166","PC Connection","CNXN","1160738688","44.19","United States"
"4167","HireRight","HRT","1160724096","14.62","United States"
"4168","Virgin Orbit","VORB","1158823168","3.46","United States"
"4169","Tauron Polska","1T5.F","1157939869","0.64","Poland"
"4170","Primoris Services Corporation","PRIM","1156738560","21.69","United States"
"4171","Reata Pharmaceuticals","RETA","1156241664","31.71","United States"
"4172","Ottogi","007310.KS","1155984838","339.93","South Korea"
"4173","REGENXBIO","RGNX","1154263168","26.76","United States"
"4174","Employers Holdings","EIG","1153640064","41.59","United States"
"4175","The Bancorp","TBBK","1150680576","20.34","United States"
"4176","MFA Financial","MFA","1150569600","11.23","United States"
"4177","Camtek","CAMT","1150358784","26.22","Israel"
"4178","Grenke","GLJ.F","1150314828","24.43","Germany"
"4179","Franklin BSP Realty Trust","FBRT","1149501312","13.74","United States"
"4180","Stratasys","SSYS","1149024384","17.3","United States"
"4181","Kura Oncology","KURA","1148806400","17.24","United States"
"4182","Colbún","COLBUN.SN","1146530664","0.07","Chile"
"4183","Canoo","GOEV","1145743232","4.51","United States"
"4184","Photronics","PLAB","1143936128","18.57","United States"
"4185","LSB Industries","LXU","1143734912","12.77","United States"
"4186","OceanFirst Financial","OCFC","1142073472","19.23","United States"
"4187","Armada Hoffler Properties","AHH","1141205504","12.92","United States"
"4188","Blue Star","BLUESTARCO.NS","1140205540","11.84","India"
"4189","Mahindra CIE","MAHINDCIE.NS","1137526047","3","India"
"4190","TriMas","TRS","1136743936","26.75","United States"
"4191","National Bank Holdings","NBHC","1135559296","37.79","United States"
"4192","Sturm, Ruger & Co","RGR","1134885632","64.36","United States"
"4193","BrightView","BV","1134599936","12.2","United States"
"4194","Golden Entertainment","GDEN","1134296704","39.14","United States"
"4195","Telia Lietuva","ZWS.F","1133591039","1.9","Lithuania"
"4196","Customers Bancorp","CUBI","1133069056","34.36","United States"
"4197","Bright Health","BHG","1132642816","1.8","United States"
"4198","Dah Sing Banking Group","2356.HK","1131797754","0.81","Hong Kong"
"4199","Bpost","13B.F","1131730952","5.57","Belgium"
"4200","Grid Dynamics","GDYN","1128682112","16.83","United States"
"4201","Funko","FNKO","1128004096","24.27","United States"
"4202","Dream Finders Homes","DFH","1127954304","12.16","United States"
"4203","Citycon","CTY1S.HE","1125972819","6.7","Finland"
"4204","Heartland Express","HTLD","1125195648","14.26","United States"
"4205","Madrigal Pharmaceuticals","MDGL","1122838272","65.65","United States"
"4206","Simulations Plus","SLP","1122064000","55.45","United States"
"4207","Enerpac Tool Group","EPAC","1121559296","19.29","United States"
"4208","Diversified Energy","DEC.L","1121555554","131.83","United States"
"4209","1st Source","SRCE","1120753152","45.32","United States"
"4210","Banc of California","BANC","1117917312","18.21","United States"
"4211","BSE","BSE.NS","1117340414","8.27","India"
"4212","Sun Country Airlines","SNCY","1115727616","19.24","United States"
"4213","Energy Recovery","ERII","1114852736","19.71","United States"
"4214","Talos Energy","TALO","1114225152","13.5","United States"
"4215","STRATEC","SBS.F","1114224233","91.3","Germany"
"4216","Atrion","ATRI","1113033728","620.04","United States"
"4217","Polenergia","PEP.WA","1112671904","21.73","Poland"
"4218","Micro Focus","MFGP","1110446976","3.31","United Kingdom"
"4219","Himax","HIMX","1110284672","6.37","Taiwan"
"4220","La-Z-Boy","LZB","1109660160","25.75","United States"
"4221","GungHo Online Entertainment","3765.T","1109175744","17.92","Japan"
"4222","PGT Innovations","PGTI","1106097280","18.46","United States"
"4223","Prometheus Biosciences","RXDX","1105772672","28.21","United States"
"4224","Overstock.com","OSTK","1105598720","25.88","United States"
"4225","NOW Inc.","DNOW","1103768704","9.97","United States"
"4226","First Foundation","FFWM","1102592000","19.51","United States"
"4227","Grupa Kety","KTY.WA","1100773692","114.07","Poland"
"4228","Avid Bioservices","CDMO","1100657664","17.8","United States"
"4229","Fnac Darty","FNAC.PA","1100004199","41.25","France"
"4230","S&T Bancorp","STBA","1098750848","27.95","United States"
"4231","SpartanNash","SPTN","1098603776","30.41","United States"
"4232","ImmunoGen","IMGN","1098269312","4.98","United States"
"4233","Chinook Therapeutics","KDNY","1097815296","17.82","United States"
"4234","Grendene","GRND3.SA","1095841282","1.21","Brazil"
"4235","Matterport","MTTR","1095736448","3.89","United States"
"4236","Hindustan Copper","HINDCOPPER.NS","1095242169","1.13","India"
"4237","CTS Corporation","CTS","1095225216","34.13","United States"
"4238","Revance Therapeutics","RVNC","1095161472","15.05","United States"
"4239","Cronos Group","CRON","1094812800","2.92","Canada"
"4240","Sandstorm Gold","SAND","1093225088","5.61","Canada"
"4241","VIP Industries","VIPIND.NS","1092229774","7.72","India"
"4242","Hims & Hers Health","HIMS","1090073344","5.29","United States"
"4243","Tennant Company","TNC","1088590464","58.59","United States"
"4244","Compass Minerals","CMP","1087455744","31.85","United States"
"4245","Playa Hotels & Resorts","PLYA","1085845888","6.55","United States"
"4246","Cellebrite","CLBT","1085473920","5.73","Israel"
"4247","Vacasa","VCSA","1083962496","2.5","United States"
"4248","SkyWest","SKYW","1083692672","21.45","United States"
"4249","Clean Energy Fuels","CLNE","1082701056","4.86","United States"
"4250","Ferroglobe","GSM","1079859328","5.77","United Kingdom"
"4251","MAG Silver","MAG","1079819776","10.76","Canada"
"4252","Omega Flex","OFLX","1078979712","106.89","United States"
"4253","Monarch Casino & Resort","MCRI","1077956992","57.11","United States"
"4254","Everbridge","EVBG","1077876736","27.26","United States"
"4255","Norway Royal Salmon","NRS.OL","1077319266","24.84","Norway"
"4256","National Healthcare","NHC","1077118848","69.62","United States"
"4257","New York Mortgage Trust","NYMT","1075122176","2.82","United States"
"4258","Bally's Corporation","BALY","1074990208","20.46","United States"
"4259","Pacific Biosciences","PACB","1074794624","4.79","United States"
"4260","A10 Networks","ATEN","1073674880","14.16","United States"
"4261","Netstreit","NTST","1073492800","20.6","United States"
"4262","RHI Magnesita","RHF.F","1072480660","22.12","Austria"
"4263","Cyient","CYIENT.NS","1070742414","9.7","India"
"4264","Laredo Petroleum","LPI","1070567552","61.87","United States"
"4265","LivePerson","LPSN","1069842112","14.37","United States"
"4266","PAR Technology","PAR","1066799744","39.42","United States"
"4267","IDFC","IDFC.NS","1065230114","0.67","India"
"4268","PureCycle Technologies","PCT","1065088832","6.53","United States"
"4269","ACV Auctions","ACVA","1064242688","6.77","United States"
"4270","S&T AG","SANT.F","1062721577","16.08","Austria"
"4271","Pegasus Airlines","PGSUS.IS","1059931027","10.36","Turkey"
"4272","Grupa Zywiec","ZWC.WA","1059838768","103.18","Poland"
"4273","NeoGenomics","NEO","1059195392","8.49","United States"
"4274","Finolex Industries","FINPIPE.NS","1057045842","1.7","India"
"4275","Singapore Post","S08.SI","1056065825","0.47","Singapore"
"4276","TAV Airports Holding","TAVHL.IS","1055058735","2.92","Turkey"
"4277","Tompkins Financial","TMP","1053411200","72.53","United States"
"4278","Accel Entertainment","ACEL","1053270784","10.98","United States"
"4279","iRobot","IRBT","1052774848","38.83","United States"
"4280","Shinpoong Pharm","019170.KS","1052226337","19.88","South Korea"
"4281","Expro Group","XPRO","1052006464","9.6","United States"
"4282","EaseMyTrip","EASEMYTRIP.NS","1051896220","4.84","India"
"4283","Domo","DOMO","1050970688","31.16","United States"
"4284","Digital World Acquisition","DWAC","1050135552","28.22","United States"
"4285","EIH Limited","EIHOTEL.NS","1049637722","1.68","India"
"4286","Quess","QUESS.NS","1049199932","7.08","India"
"4287","CSI","CSVI","1049010240","38.2","United States"
"4288","Li-Cycle","LICY","1046708928","6","Canada"
"4289","Efes Beverage Group","AEFES.IS","1045821878","1.77","Turkey"
"4290","Montrose Environmental","MEG","1045283840","35.22","United States"
"4291","Borosil","BORORENEW.NS","1045007493","8.01","India"
"4292","Nicolet Bankshares","NCBS","1044725568","78.01","United States"
"4293","Construction Partners","ROAD","1044594560","19.88","United States"
"4294","FibroGen","FGEN","1043999040","11.19","United States"
"4295","Rhön-Klinikum","RHK.DE","1043284819","15.59","Germany"
"4296","Federal Agricultural Mortgage","AGM","1042982784","97","United States"
"4297","Gree","3632.T","1042328129","6.02","Japan"
"4298","BELLUS Health","BLU","1040793024","9.75","Canada"
"4299","E. W. Scripps Company","SSP","1040298304","12.49","United States"
"4300","Volaris","VLRS","1039764224","8.99","Mexico"
"4301","Energy Vault","NRGV","1039299648","7.77","United States"
"4302","Magnite","MGNI","1037472128","7.87","United States"
"4303","Shentel","SHEN","1036665920","20.71","United States"
"4304","AZZ","AZZ","1036304384","41.9","United States"
"4305","Canopy Growth","CGC","1035503616","2.27","Canada"
"4306","Metrovacesa","MVC.MC","1034019009","6.83","Spain"
"4307","Nabors Industries","NBR","1033582208","109.82","Bermuda"
"4308","Solid Power","SLDP","1031330944","5.94","United States"
"4309","Amber Enterprises India","AMBER.NS","1030923411","30.6","India"
"4310","Syndax Pharmaceuticals","SNDX","1030738048","18.33","United States"
"4311","Green Brick Partners","GRBK","1028644672","21.24","United States"
"4312","TriState Capital Holdings","TSC","1028616384","30.58","United States"
"4313","Merus","MRUS","1027782400","23.6","Netherlands"
"4314","Mission Produce","AVO","1027335360","14.54","United States"
"4315","flatexDEGIRO AG","FTK.DE","1024784024","9.33","Germany"
"4316","PBF Logistics","PBFX","1022899712","16.34","United States"
"4317","The Andersons","ANDE","1022680896","30.23","United States"
"4318","Brookline Bancorp","BRKL","1022517376","13.23","United States"
"4319","H&E Equipment Services","HEES","1022288448","28.27","United States"
"4320","Aimco","AIV","1021953152","6.69","United States"
"4321","Mesa Laboratories","MLAB","1021551168","193.92","United States"
"4322","MTY Food Group","MTY.TO","1020463812","41.8","Canada"
"4323","TORM","TRMD","1019755968","12.49","United Kingdom"
"4324","UMH Properties","UMH","1018739904","18.78","United States"
"4325","Kayne Anderson Capital Advisors","KYN","1017906432","8.05","United States"
"4326","Atoss","AOF.F","1017234148","127.9","Germany"
"4327","Docebo","DCBO","1016668992","28.59","Canada"
"4328","uniQure","QURE","1015051776","21.76","Netherlands"
"4329","Proterra","PTRA","1014650048","4.55","United States"
"4330","Freightways","FRE.NZ","1012358802","6.11","New Zealand"
"4331","Oceaneering International","OII","1011562880","10.09","United States"
"4332","LeMaitre Vascular","LMAT","1010889600","46.05","United States"
"4333","Hartalega","5168.KL","1009474433","0.62","Malaysia"
"4334","Graphite India","GRAPHITE.NS","1007006621","5.15","India"
"4335","Hamburger Hafen","HHFA.F","1004378675","13.33","Germany"
"4336","Eventbrite","EB","1004197632","10.28","United States"
"4337","MannKind Corp","MNKD","1003945792","3.98","United States"
"4338","Eldorado Gold","EGO","1002834112","5.43","Canada"
"4339","Amara Raja Batteries","AMARAJABAT.NS","1001675969","5.86","India"
"4340","BrightSpire Capital","BRSP","1001481728","7.64","United States"
"4341","Target Hospitality","TH","1001201984","10.33","United States"
"4342","DHT Holdings","DHT","1000794048","6","Bermuda"
"4343","Cerus","CERS","1000358208","5.66","United States"
"4344","iHeartMedia","IHRT","999138752","7.03","United States"
"4345","Standex","SXI","998526336","82.73","United States"
"4346","Verve Therapeutics","VERV","998370624","20.52","United States"
"4347","Lightwave Logic","LWLG","998105856","8.94","United States"
"4348","Rocket Pharmaceuticals","RCKT","998102528","15.16","United States"
"4349","OdontoPrev","ODPV3.SA","997859620","1.78","Brazil"
"4350","MapmyIndia","MAPMYINDIA.NS","996120400","18.71","India"
"4351","Enanta Pharmaceuticals","ENTA","994416704","48.01","United States"
"4352","Amneal Pharmaceuticals","AMRX","993348416","3.28","United States"
"4353","Uponor","UPONOR.HE","992258960","13.66","Finland"
"4354","Procaps Group","PROC","991722944","8.79","Luxembourg"
"4355","Melco International Development","0200.HK","991126703","0.65","Hong Kong"
"4356","Oscar Health","OSCR","989622848","4.69","United States"
"4357","Heska Corporation","HSKA","989497984","91.7","United States"
"4358","Vimeo","VMEO","986087808","5.93","United States"
"4359","Republic Bank","RBCAA","985755648","49.29","United States"
"4360","Merchants Bancorp","MBIN","985424128","22.78","United States"
"4361","Patrizia Immobilien","P1Z.VI","985297279","11.04","Germany"
"4362","Caleres","CAL","985296064","26.82","United States"
"4363","Intapp","INTA","985290112","15.84","United States"
"4364","BrainChip","BRN.AX","984267997","0.54","Australia"
"4365","Service Properties Trust","SVC","983942400","5.96","United States"
"4366","Mahanagar Gas","MGL.NS","982833277","9.95","India"
"4367","ADTRAN","ADTN","982403968","20","United States"
"4368","Innoviva","INVA","982053312","14.09","United States"
"4369","Brinker International","EAT","981602176","22.39","United States"
"4370","G-III Apparel Group","GIII","980904640","20.34","United States"
"4371","RadNet","RDNT","979343680","17.42","United States"
"4372","KRUK Spólka Akcyjna","KRU.WA","978132554","51.45","Poland"
"4373","Allego","ALLG","976465920","3.68","Netherlands"
"4374","Clearfield","CLFD","974600960","70.77","United States"
"4375","Genesis Energy L.P.","GEL","974503040","7.95","United States"
"4376","Replimune","REPL","974039488","19.85","United States"
"4377","Belite Bio","BLTE","972727232","40.37","United States"
"4378","Fortress REIT","FFA.JO","971411472","0.64","South Africa"
"4379","Donnelley Financial Solutions","DFIN","971172224","30.55","United States"
"4380","Kiwi Property","KWIPF","971040128","0.6","New Zealand"
"4381","Amerant Bancorp","AMTB","970445568","28.38","United States"
"4382","The Greenbrier Companies","GBX","970135872","29.77","United States"
"4383","Cerence","CRNC","969271168","24.66","United States"
"4384","Radware","RDWR","968561280","21.6","Israel"
"4385","ConnectOne Bancorp","CNOB","967952576","24.49","United States"
"4386","The Necessity Retail REIT","RTL","967799680","7.27","United States"
"4387","AMERISAFE","AMSF","965633600","49.98","United States"
"4388","Office Properties Income Trust","OPI","965110272","19.93","United States"
"4389","ContextLogic (wish.com)","WISH","962853568","1.45","United States"
"4390","Astec Industries","ASTE","961542464","42.1","United States"
"4391","Model N","MODN","960004288","26.07","United States"
"4392","MoneyGram","MGI","957969088","9.95","United States"
"4393","TomTom","TOM2.AS","957390641","7.54","Netherlands"
"4394","Redwood Trust","RWT","956609920","7.95","United States"
"4395","Antares Pharma","ATRS","955062720","5.59","United States"
"4396","Intersect ENT","XENT","954898880","28.24","United States"
"4397","QCR Holdings","QCRH","953881664","54.04","United States"
"4398","Orion Engineered Carbons","OEC","953156480","15.69","United States"
"4399","Lakeland Bancorp","LBAI","952261568","14.7","United States"
"4400","Hollysys Automation Technologie","HOLI","951119808","15.35","China"
"4401","Harmonic","HLIT","950849920","9.1","United States"
"4402","Zhihu","ZH","950702400","1.46","China"
"4403","AdvanSix","ASIX","950453568","33.82","United States"
"4404","Momo","MOMO","950125248","4.79","China"
"4405","Guess","GES","949955328","17.45","United States"
"4406","Camping World","CWH","948649920","22.75","United States"
"4407","Gateway Real Estate","GTY.F","948374266","5.08","Germany"
"4408","Hudbay Minerals","HBM","947506944","3.34","Canada"
"4409","Zeta Global","ZETA","945644480","4.66","United States"
"4410","Cross Country Healthcare","CCRN","944647552","24.72","United States"
"4411","Imax Corp","IMAX","941615744","16.09","Canada"
"4412","Bluerock Residential","BRG","938679872","26.19","United States"
"4413","Arrival","ARVL","938268672","1.47","United Kingdom"
"4414","Origin Bancorp","OBNK","938150592","39.47","United States"
"4415","Magic Software","MGIC","937532608","18.9","Israel"
"4416","Sorrento Therapeutics","SRNE","937359872","2.41","United States"
"4417","IntegraFin","IHP.L","937306242","282.9","United Kingdom"
"4418","Enova International","ENVA","935471744","28.73","United States"
"4419","Sierra Wireless","SWIR","934175232","24.37","Canada"
"4420","Schnitzer Steel","SCHN","933472448","34.01","United States"
"4421","Sunteck Realty","SUNTECK.NS","933317570","6.37","India"
"4422","ACM Research","ACMR","933272640","15.78","United States"
"4423","Unitil Corporation","UTL","932362944","58.16","United States"
"4424","Ellington Financial","EFC","931313472","15.51","United States"
"4425","Kingsoft Cloud","KC","929124160","3.82","China"
"4426","Tejas Networks","TEJASNET.NS","928681880","6.13","India"
"4427","Mercer International","MERC","927838976","14.03","Canada"
"4428","Veeco","VECO","926985856","18.09","United States"
"4429","Designer Brands","DBI","925849344","13.16","United States"
"4430","Editas Medicine","EDIT","925282048","13.48","United States"
"4431","MYT Netherlands Parent (Mytheresa)","MYTE","925185216","10.95","Germany"
"4432","Kahoot!","KAHOT.OL","924735908","1.89","Norway"
"4433","Cassava Sciences","SAVA","918717760","22.92","United States"
"4434","IonQ","IONQ","917388224","4.63","United States"
"4435","Anavex Life Sciences","AVXL","915748480","11.83","United States"
"4436","International Seaways","INSW","914751936","18.42","United States"
"4437","Galicia Financial Group","GGAL","914307712","6.2","Argentina"
"4438","Network18","NETWORK18.NS","912564635","0.87","India"
"4439","Dah Sing Financial","0440.HK","911936145","2.85","Hong Kong"
"4440","Uranium Energy","UEC","911824128","3.19","United States"
"4441","Sumo Logic","SUMO","910810816","7.87","United States"
"4442","Qurate Retail Group","QRTEA","910115456","2.31","United States"
"4443","Jupiter Fund Management","JUP.L","907864446","164.15","United Kingdom"
"4444","Par Pacific Holdings","PARR","907816576","15.1","United States"
"4445","Hudco","HUDCO.NS","906429496","0.45","India"
"4446","Cellcom Israel","CEL.TA","904950699","5.51","Israel"
"4447","FREYR Battery","FREY","904449920","7.74","Luxembourg"
"4448","Morphic Therapeutic","MORF","904305920","23.63","United States"
"4449","Enerjisa Enerji","ENJSA.IS","903975533","0.77","Turkey"
"4450","Redfin","RDFN","902405120","8.42","United States"
"4451","Deluxe","DLX","901942784","20.98","United States"
"4452","Heritage Financial","HFWA","901780672","25.69","United States"
"4453","Alpha & Omega Semiconductor","AOSL","901651776","33.31","United States"
"4454","SIGA Technologies","SIGA","900073280","12.43","United States"
"4455","Broadmark Realty Capital","BRMK","897734784","6.76","United States"
"4456","ProPetro","PUMP","894908992","8.59","United States"
"4457","SmartRent","SMRT","894620544","4.58","United States"
"4458","Boohoo Group","BOO.L","894146922","66.18","United Kingdom"
"4459","Titan International","TWI","891607680","14.23","United States"
"4460","Corporación América Airports","CAAP","891197632","5.46","Luxembourg"
"4461","Seabridge Gold","SA","888699136","11.08","Canada"
"4462","Praj Industries","PRAJIND.NS","886739353","4.83","India"
"4463","Cowen","COWN","886223680","31.91","United States"
"4464","2U","TWOU","885936960","11.5","United States"
"4465","Forrester Research","FORR","885284416","46.9","United States"
"4466","Community Healthcare Trust","CHCT","884303552","35.27","United States"
"4467","Juventus Turin","JUVE.MI","883410888","0.35","Italy"
"4468","Brooge Energy","BROG","881087488","8.04","United Arab Emirates"
"4469","Health Catalyst","HCAT","880506240","16.25","United States"
"4470","Nürnberger Versicherung","NBG6.F","880361991","75.41","Germany"
"4471","Ace Hardware Indonesia","ACES.JK","879726924","0.05","Indonesia"
"4472","Prosegur","PSG.MC","878084891","1.66","Spain"
"4473","Allcargo Logistics","ALLCARGO.NS","877463645","3.57","India"
"4474","MRC Global","MRC","877411648","10.51","United States"
"4475","GoPro","GPRO","875235456","5.57","United States"
"4476","United Fire Group","UFCS","872772480","34.74","United States"
"4477","Drägerwerk","DRW8.F","872446456","41.68","Germany"
"4478","Polyplex","POLYPLEX.NS","872267967","27.79","India"
"4479","Conduent","CNDT","872118208","4.05","United States"
"4480","James River Group","JRVR","871094016","23.26","Bermuda"
"4481","Secureworks","SCWX","871083840","10.27","United States"
"4482","Unisys","UIS","870499840","12.87","United States"
"4483","Steel Partners","SPLP","870042624","42","United States"
"4484","OYAK Çimento","OYAKC.IS","867604691","0.75","Turkey"
"4485","Pushpay Holdings","PPH.NZ","866940167","0.75","New Zealand"
"4486","Paya","PAYA","865731968","6.56","United States"
"4487","Palfinger","PFI.F","865647332","22.47","Austria"
"4488","Matthews International Corporation","MATW","864051136","27.6","United States"
"4489","Cresco Labs","CRLBF","863426688","2.95","United States"
"4490","NAPCO Security Technologies","NSSC","863277696","23.5","United States"
"4491","Multi Commodity Exchange","MCX.NS","856686858","16.8","India"
"4492","Alector","ALEC","856199680","10.4","United States"
"4493","Global Blue Group","GB","856041536","4.55","Switzerland"
"4494","RPT Realty","RPT","854917952","9.85","United States"
"4495","Restaurant Brands New Zealand","RBD.NZ","852856711","6.84","New Zealand"
"4496","Knr Constructions","KNRCON.NS","851932524","3.03","India"
"4497","AvePoint","AVPT","851899264","4.66","United States"
"4498","International Money Express","IMXI","851879168","22.16","United States"
"4499","Nuvalent","NUVL","851292736","17.62","United States"
"4500","I-Mab Biopharma","IMAB","851254784","10.3","China"
"4501","Blucora","BCOR","850927488","18.01","United States"
"4502","American Axle & Manufacturing","AXL","850630976","7.43","United States"
"4503","Abercrombie & Fitch","ANF","849777984","16.85","United States"
"4504","SMART Global Holdings","SGH","847355968","16.95","United States"
"4505","Arcellx","ACLX","847270720","19.35","United States"
"4506","Tecnoglass","TGLS","846704448","17.76","Colombia"
"4507","Triumph Group","TGI","843324160","13.04","United States"
"4508","NeoPhotonics","NPTN","840071808","15.71","United States"
"4509","Nano Dimension","NNDM","839166336","3.26","United States"
"4510","Dril-Quip","DRQ","838809216","24.3","United States"
"4511","MarineMax","HZO","838431488","38.94","United States"
"4512","Washington Trust Bancorp","WASH","838198208","48.3","United States"
"4513","Avidity Biosciences","RNA","837518016","16.83","United States"
"4514","Westlake Chemical Partners","WLKP","837046336","23.77","United States"
"4515","Denison Mines","DNN","836744576","0.98","Canada"
"4516","Energy Fuels","UUUU","835610112","5.09","United States"
"4517","PropertyGuru","PGRU","835073024","5.18","Singapore"
"4518","GPA","CBD","834600512","3.1","Brazil"
"4519","Nuvation Bio","NUVB","834343424","3.83","United States"
"4520","OneConnect","OCFT","834333632","2.09","China"
"4521","Varex Imaging","VREX","833611008","20.95","United States"
"4522","Digi International","DGII","833264000","23.75","United States"
"4523","Suzlon","SUZLON.NS","832296474","0.08","India"
"4524","Dole PLC","DOLE","832077440","8.77","Ireland"
"4525","AerSale","ASLE","831661568","16.09","United States"
"4526","PubMatic","PUBM","831299648","15.97","United States"
"4527","OrthoPediatrics","KIDS","831054464","41.08","United States"
"4528","Doosan","000150.KS","828651758","50.47","South Korea"
"4529","Huya","HUYA","827939584","3.48","China"
"4530","Perion Network","PERI","827089920","18.16","Israel"
"4531","Adecoagro","AGRO","826625280","7.43","Luxembourg"
"4532","Afya","AFYA","824131968","9.07","Brazil"
"4533","Lion Electric","LEV","824122496","4.34","Canada"
"4534","Norwegian Air Shuttle","NAS.OL","824089121","0.89","Norway"
"4535","Deciphera Pharmaceuticals","DCPH","823733248","12.44","United States"
"4536","Prince Pipes And Fittings","PRINCEPIPE.NS","822303394","7.43","India"
"4537","Gladstone Land","LAND","822169536","23.89","United States"
"4538","Perdoceo Education","PRDO","820537024","11.93","United States"
"4539","Associated Capital Group","AC","820466560","37.22","United States"
"4540","Kaman","KAMN","819460992","29.29","United States"
"4541","Bombay Burmah","BBTC.NS","819452144","11.74","India"
"4542","Mahindra Lifespaces","MAHLIFE.NS","817375295","5.28","India"
"4543","Outset Medical","OM","817282560","17.1","United States"
"4544","UserTesting","USER","817187712","5.72","United States"
"4545","Riverstone Holdings","AP4.SI","817043693","0.55","Singapore"
"4546","PDF Solutions","PDFS","816366912","22.09","United States"
"4547","Ivanhoe Electric","IE","816020224","8.79","Canada"
"4548","Materialise NV","MTLS","815371648","13.81","Belgium"
"4549","Mensch und Maschine","MUM.F","813098667","47.56","Germany"
"4550","Chalet Hotels","CHALET.NS","811230986","3.95","India"
"4551","Arco Platform","ARCE","810700992","14.26","Brazil"
"4552","Marathon Digital Holdings","MARA","809543040","7.62","United States"
"4553","SLR Investment","SLRC","809381632","14.78","United States"
"4554","Ryerson","RYI","807876352","20.82","United States"
"4555","Calumet Specialty Products Partners","CLMT","806935232","10.2","United States"
"4556","Cosmo Pharmaceuticals","C43.F","806705617","47.66","Ireland"
"4557","iTeos Therapeutics","ITOS","803930688","22.62","United States"
"4558","Clarus","CLAR","802619328","21.2","United States"
"4559","Asiana Airlines","020560.KS","802378669","10.78","South Korea"
"4560","Great Lakes Dredge & Dock Corp.","GLDD","802033984","12.14","United States"
"4561","Geo Group","GEO","800419200","6.45","United States"
"4562","CEVA","CEVA","800163584","34.48","United States"
"4563","TimkenSteel","TMST","800102144","17.16","United States"
"4564","Vivint Smart Home","VVNT","797133696","3.75","United States"
"4565","CBL Properties","CBL","796627584","25.04","United States"
"4566","AngioDynamics","ANGO","796543296","20.54","United States"
"4567","Phibro Animal Health","PAHC","796300800","19.66","United States"
"4568","Poshmark","POSH","795300288","10.18","United States"
"4569","Property For Industry","PFI.NZ","794273932","1.57","New Zealand"
"4570","Allegiance Bancshares","ABTX","793319424","38.93","United States"
"4571","Benchmark Electronics","BHE","793303168","22.58","United States"
"4572","Finolex Cables","FINCABLES.NS","793279226","5.19","India"
"4573","IGM Biosciences","IGMS","793121088","18.65","United States"
"4574","Aliansce Sonae Shopping Centers","ALSO3.SA","792636798","2.99","Brazil"
"4575","Summit Hotel Properties","INN","790540288","7.4","United States"
"4576","Myers Industries","MYE","790483456","21.75","United States"
"4577","ChipMOS Technologies","IMOS","789602560","21.62","Taiwan"
"4578","Vertex Energy","VTNR","789516416","10.51","United States"
"4579","WalkMe","WKME","788867264","9.34","Israel"
"4580","Consolidated Communications","CNSL","788154688","6.83","United States"
"4581","Columbus McKinnon","CMCO","787711040","27.59","United States"
"4582","Core Laboratories","CLB","786595072","16.98","Netherlands"
"4583","SilverCrest Metals","SILV","785044288","5.38","Canada"
"4584","Cimpress","CMPR","783174016","30","Ireland"
"4585","Sunlight REIT","0435.HK","781965504","0.46","Hong Kong"
"4586","Microvision","MVIS","781443328","4.73","United States"
"4587","ScanSource","SCSC","780933504","30.95","United States"
"4588","Mastek","MASTEK.NS","779510839","25.95","India"
"4589","Codexis","CDXS","779077952","11.93","United States"
"4590","Tidewater","TDW","778586048","18.62","United States"
"4591","VEON","VEON","776650304","0.44","Netherlands"
"4592","Interface","TILE","776644288","13.06","United States"
"4593","Latham Group","SWIM","774971072","6.48","United States"
"4594","CrossAmerica Partners","CAPL","772660800","20.38","United States"
"4595","RE/MAX Holdings","RMAX","772414592","24.27","United States"
"4596","Quanex Building Products","NX","771987328","23.17","United States"
"4597","Brookdale Senior Living","BKD","771605952","4.12","United States"
"4598","Fortuna Silver Mines","FSM","771132224","2.56","Canada"
"4599","Symphony Limited","SYMPHONY.NS","771121324","11.02","India"
"4600","Badger Infrastructure Solutions","BDGI.TO","770259176","22.34","Canada"
"4601","Cadre","CDRE","766568640","20.7","United States"
"4602","System1","SST","766099456","8.46","United States"
"4603","CinCor Pharma","CINC","765510912","20.3","United States"
"4604","Zensar","ZENSARTECH.NS","763979083","3.21","India"
"4605","Calavo Growers","CVGW","763265152","43.02","United States"
"4606","Pacific Century Regional Developments","P15.SI","762857057","0.29","Singapore"
"4607","Mirum Pharmaceuticals","MIRM","761788096","23.85","United States"
"4608","Hyzon Motors","HYZN","761056000","3.07","United States"
"4609","Erasca","ERAS","760393920","6.24","United States"
"4610","Alabama Power","ALP-PQ","760383744","24.9","United States"
"4611","Snap One","SNPO","758784000","10","United States"
"4612","Kearny Financial","KRNY","756445056","11.16","United States"
"4613","Univest","UVSP","756399616","25.56","United States"
"4614","Gladstone Commercial","GOOD","754732992","19.18","United States"
"4615","Hawaiian Airlines","HA","753995072","14.69","United States"
"4616","Coeur Mining","CDE","753627200","2.68","United States"
"4617","ReconAfrica","0XD.F","752993110","3.77","Canada"
"4618","Eurowag","WPS.L","752275881","108.05","United Kingdom"
"4619","Perella Weinberg Partners","PWP","751882944","5.59","United States"
"4620","Zeal Network","TIMA.F","751153810","32.78","Germany"
"4621","Couchbase","BASE","749795008","16.83","United States"
"4622","Evolus","EOLS","749655360","13.38","United States"
"4623","Azul","AZUL","749646528","6.47","Brazil"
"4624","Chase Corporation","CCF","747568832","78.95","United States"
"4625","Thryv","THRY","747428608","21.83","United States"
"4626","Horizon Bancorp","HBNC","746402048","17.13","United States"
"4627","Artivion","AORT","746141696","18.56","United States"
"4628","Olvi plc","OLVAS.HE","745988891","35.5","Finland"
"4629","Transportadora de Gas del Sur","TGS","745232384","4.95","Argentina"
"4630","Eckert & Ziegler","EUZ.F","744837277","35.33","Germany"
"4631","Origin Materials","ORGN","744661568","5.27","United States"
"4632","Anterix","ATEX","743622656","39.25","United States"
"4633","Forestar Group","FOR","743587584","14.95","United States"
"4634","Morphosys","MOR","743076864","5.44","Germany"
"4635","Precision Drilling Corporation","PDS","742817920","54.21","Canada"
"4636","TPG Real Estate Finance Trust","TRTX","742527360","9.62","United States"
"4637","Pharvaris","PHVS","742448000","22.4","Netherlands"
"4638","Sundial Growers","SNDL","742277376","0.31","Canada"
"4639","U.S. Silica","SLCA","741941824","9.83","United States"
"4640","American Woodmark","AMWD","741733952","44.7","United States"
"4641","MMTC","MMTC.NS","741434804","0.49","India"
"4642","Y-mAbs Therapeutics","YMAB","740586304","16.94","United States"
"4643","Adler Real Estate","ADL.DE","739348658","6.76","Germany"
"4644","First Mid-Illinois Bancshares","FMBH","738815168","36.13","United States"
"4645","SP Plus Corporation","SP","738791616","31.76","United States"
"4646","Ichor Systems","ICHR","738523776","25.8","United States"
"4647","Kelly Services","KELYA","737820544","19.48","United States"
"4648","Biolife Solutions","BLFS","737716736","17.4","United States"
"4649","Seritage Growth Properties","SRG","737701248","10.66","United States"
"4650","sterling & wilson solar","SWSOLAR.NS","737582221","3.89","India"
"4651","Select Energy Services","WTTR","737441408","6.45","United States"
"4652","Global Medical REIT","GMRE","736734528","10.96","United States"
"4653","AudioCodes","AUDC","735303872","22.62","Israel"
"4654","WisdomTree Investments","WETF","734045568","5.01","United States"
"4655","Archer Aviation","ACHR","731985024","3.03","United States"
"4656","Schweitzer-Mauduit International","SWM","731768512","23.41","United States"
"4657","Blink Charging","BLNK","731763648","17.12","United States"
"4658","Arqit Quantum","ARQQ","731555968","6","United Kingdom"
"4659","Rover","ROVR","731394816","4.02","United States"
"4660","ARMOUR Residential REIT","ARR","730980096","7.09","United States"
"4661","Orient Electric","ORIENTELEC.NS","730566918","3.44","India"
"4662","Desktop Metal","DM","729987968","2.33","United States"
"4663","TG Therapeutics","TGTX","729396800","5.05","United States"
"4664","Sleep Number","SNBR","728542656","32.77","United States"
"4665","Jubilant Pharmova","JUBLPHARMA.NS","728311614","4.57","India"
"4666","Community Trust Bancorp","CTBI","728155648","40.69","United States"
"4667","Lilium","LILM","727947520","2.5","Germany"
"4668","Movado","MOV","727647488","31.78","United States"
"4669","SiriusPoint","SPNT","727458048","4.49","Bermuda"
"4670","Aeva Technologies","AEVA","727038592","3.36","United States"
"4671","VRL Logistics","VRLLOG.NS","726954970","8.23","India"
"4672","Metropolitan Bank Holding","MCB","726430784","64.84","United States"
"4673","Butterfly Network","BFLY","726193024","3.65","United States"
"4674","SPARC","SPARC.NS","724595757","2.67","India"
"4675","Similarweb","SMWB","723962048","9.54","Israel"
"4676","ATN International","ATNI","723626368","45.96","United States"
"4677","Sterlite Technologies","STLTECH.NS","722774998","1.82","India"
"4678","BrightSphere Investment Group","BSIG","722046464","17.43","United States"
"4679","Wemade","112040.KQ","719881403","43.9","South Korea"
"4680","Plymouth Industrial REIT","PLYM","719602112","17.72","United States"
"4681","New Work","NWO.F","718873742","127.9","Germany"
"4682","Air New Zealand","ANZFF","718426240","0.39","New Zealand"
"4683","HarborOne Bancorp","HONE","717607808","14","United States"
"4684","NEUCA","NEU.WA","716828666","166.39","Poland"
"4685","Greenpanel Industries","GREENPANEL.NS","716504627","5.84","India"
"4686","Via S.A.","VIIA3.SA","716297671","0.45","Brazil"
"4687","National Western Life","NWLI","716295936","197","United States"
"4688","Novonix","NVX","715564288","5.89","Australia"
"4689","Allbirds","BIRD","715157888","4.82","United States"
"4690","Agenus","AGEN","714219008","2.53","United States"
"4691","Transport Corporation of India","TCI.NS","711442378","9.2","India"
"4692","PMV Pharmaceuticals","PMVP","710955968","15.6","United States"
"4693","Terran Orbital","LLAP","710898368","5.16","United States"
"4694","Gorman-Rupp","GRC","710655488","27.25","United States"
"4695","Kura Sushi USA","KRUS","710278720","72.92","United States"
"4696","NBCC India","NBCC.NS","709739901","0.39","India"
"4697","Enfusion","ENFN","709611264","10.82","United States"
"4698","Universal Health Realty Income Trust","UHT","709443008","51.46","United States"
"4699","Azure Power","AZRE","708336512","11.04","India"
"4700","Farmland Partners","FPI","708131264","13.88","United States"
"4701","Slam Corp","SLAM","706531264","9.83","United States"
"4702","Wabash National","WNC","705579136","14.39","United States"
"4703","Kiniksa Pharmaceuticals","KNSA","705226624","10.18","Bermuda"
"4704","YG Entertainment","122870.KQ","704179015","38.7","South Korea"
"4705","Insteel Industries","IIIN","704087872","36.22","United States"
"4706","Riskified","RSKD","701870400","4.2","Israel"
"4707","CTI BioPharma","CTIC","701747456","6.44","United States"
"4708","Canaan","CAN","701036288","3.75","China"
"4709","RITES","RITES.NS","700885807","2.92","India"
"4710","Genesco","GCO","699756928","50.97","United States"
"4711","Instil Bio","TIL","699480512","5.41","United States"
"4712","Cutera","CUTR","699109312","38.49","United States"
"4713","Com2uS","078340.KQ","699071235","56.21","South Korea"
"4714","ADC Therapeutics","ADCT","698975552","9.1","Switzerland"
"4715","Renren","RENN","698210752","28.02","China"
"4716","Universal Logistics Holdings","ULH","698060864","26.4","United States"
"4717","Jindal Stainless","JSL.NS","696300706","1.32","India"
"4718","Iamgold","IAG","695490432","1.42","Canada"
"4719","Accolade","ACCD","694291648","9.75","United States"
"4720","Bluelinx","BXC","692572288","71.71","United States"
"4721","Cera Sanitaryware","CERA.NS","692363791","53.22","India"
"4722","BEML","BEML.NS","690749150","16.55","India"
"4723","Arhaus","ARHS","690510592","4.93","United States"
"4724","Magnachip","MX","690475904","15.38","Luxembourg"
"4725","Nexa Resources","NEXA","688682752","5.2","Luxembourg"
"4726","TCG BDC","CGBD","688621568","13.12","United States"
"4727","Winmark","WINA","688309440","197.86","United States"
"4728","Hanmi Financial","HAFC","687030848","22.55","United States"
"4729","Ares Commercial Real Estate","ACRE","683746304","12.56","United States"
"4730","New Found Gold","NFGC","682602304","4.13","Canada"
"4731","Genco Shipping & Trading","GNK","681846720","16.2","United States"
"4732","Ponsse","PON1V.HE","681596911","23.63","Finland"
"4733","Taboola.com","TBLA","681560384","2.85","United States"
"4734","VIB Vermögen","VIH1.F","681256414","24.59","Germany"
"4735","Big Lots","BIG","681071936","23.46","United States"
"4736","YIT","YIT.HE","680884448","3.25","Finland"
"4737","Cars.com","CARS","678936896","9.77","United States"
"4738","Tremor International","TRMR","678206272","9.03","Israel"
"4739","Geopark","GPRK","678183040","11.3","Chile"
"4740","Tokmanni","TOKMAN.HE","677870367","11.43","Finland"
"4741","indie Semiconductor","INDI","677343232","5.71","United States"
"4742","Banco Macro","BMA","677131968","10.59","Argentina"
"4743","ESAB India","ESABINDIA.NS","675904628","43.86","India"
"4744","Heritage-Crystal Clean","HCCI","674976128","27.8","United States"
"4745","Locaweb","LWSA3.SA","674069725","1.14","Brazil"
"4746","Delegat","DGL.NZ","673951733","6.66","New Zealand"
"4747","MBIA","MBI","673100352","12.27","United States"
"4748","Frontier Developments","FDEV.L","672917296","1706.9","United Kingdom"
"4749","TerrAscend","TRSSF","672387520","2.24","Canada"
"4750","Norma Group","NOEJ.F","672075616","21","Germany"
"4751","The Shyft Group","SHYF","672036544","19.18","United States"
"4752","JBM Auto","JBMA.NS","670465172","5.66","India"
"4753","UB Properties","UBA","670067136","16.35","United States"
"4754","HealthStream","HSTM","669838336","21.89","United States"
"4755","Team17","TM17.L","669739167","460.01","United Kingdom"
"4756","Standard Lithium","SLI","668411840","4.03","Canada"
"4757","Kalpataru Power Transmission","KALPATPOWR.NS","667217088","4.47","India"
"4758","Bristow Group","VTOL","666168192","23.52","United States"
"4759","Douglas Dynamics","PLOW","665555008","29.08","United States"
"4760","Dynex Capital","DX","664630080","16.24","United States"
"4761","MediaAlpha","MAX","662801984","11.01","United States"
"4762","UP Fintech (Tiger Brokers)","TIGR","662531008","4.34","China"
"4763","Camden National Bank","CAC","662473792","45.2","United States"
"4764","Theravance Biopharma","TBPH","662203968","8.7","Cayman Islands"
"4765","Gujarat Alkalies and Chemicals","GUJALKALI.NS","661096425","9","India"
"4766","Microvast","MVST","661047744","2.19","United States"
"4767","Baozun","BZUN","660828288","9.62","China"
"4768","Geron","GERN","660532288","1.75","United States"
"4769","Quanterix","QTRX","660321664","17.89","United States"
"4770","CRA International","CRAI","659241792","89.42","United States"
"4771","Heritage Commerce","HTBK","658240640","10.89","United States"
"4772","ProFrac","PFHC","658142528","15.96","United States"
"4773","Sterling Construction","STRL","657926336","21.74","United States"
"4774","HomeStreet Bank","HMST","656402880","35.1","United States"
"4775","Adicet Bio","ACET","654071936","16.35","United States"
"4776","Keros Therapeutics","KROS","652066816","27.13","United States"
"4777","Xponential Fitness","XPOF","651480960","13.35","United States"
"4778","Al Moammar Information Systems","7200.SR","651444084","21.71","Saudi Arabia"
"4779","Atea Pharmaceuticals","AVIR","651424128","7.82","United States"
"4780","Blend Labs","BLND","651302400","2.8","United States"
"4781","Hinduja Global Solutions","HGS.NS","650940913","15.57","India"
"4782","World Acceptance Corporation","WRLD","650685056","103.64","United States"
"4783","REV Group","REVG","650281280","10.67","United States"
"4784","Ocugen","OCGN","649889280","2.68","United States"
"4785","Cathay Real Estate Development","2501.TW","648927684","0.56","Taiwan"
"4786","Edelweiss Financial Services","EDELWEISS.NS","648835627","0.69","India"
"4787","IDT Corporation","IDT","648415104","24.71","United States"
"4788","Orla Mining","ORLA","648317696","2.57","Canada"
"4789","Acco Brands","ACCO","647868480","6.68","United States"
"4790","Riot Blockchain","RIOT","646963456","4.78","United States"
"4791","Atai Life Sciences","ATAI","646146624","4.02","Germany"
"4792","The Vita Coco Company","COCO","646022016","11.62","United States"
"4793","Northfield Bancorp","NFBK","645922752","13.21","United States"
"4794","Sunway","5211.KL","645853719","0.36","Malaysia"
"4795","OneSpaWorld","OSW","645838336","7.01","Bahamas"
"4796","Flushing Financial Corp","FFIC","644572416","21.24","United States"
"4797","Karooooo","KARO","644401920","20.82","Singapore"
"4798","Nektar Therapeutics","NKTR","643576640","3.46","United States"
"4799","Luther Burbank","LBC","643157504","12.58","United States"
"4800","Johnson Outdoors","JOUT","642820992","63.22","United States"
"4801","Old Second Bancorp","OSBC","641572224","14.43","United States"
"4802","Boston Omaha","BOC","641188480","21.59","United States"
"4803","NanoString Technologies","NSTG","639609728","13.78","United States"
"4804","Rain Industries","RAIN.NS","639204608","1.9","India"
"4805","Portillo's","PTLO","639155584","17.83","United States"
"4806","Organogenesis","ORGO","637902208","4.94","United States"
"4807","Zealand Pharma","ZEAL","637865216","14.76","Denmark"
"4808","1-800-Flowers","FLWS","636522112","9.86","United States"
"4809","Amyris","AMRS","636230848","1.99","United States"
"4810","KSB ltd","KSB.NS","635736598","18.26","India"
"4811","IES Holdings","IESC","635070336","30.55","United States"
"4812","Seer","SEER","635034112","10.17","United States"
"4813","PureTech Health","PRTC","634846784","22.2","United States"
"4814","Vaibhav Global","VAIBHAVGBL.NS","634546611","3.86","India"
"4815","RBL Bank","RBLBANK.NS","634517092","1.06","India"
"4816","Aktia Bank","AKTIA.HE","633529919","8.81","Finland"
"4817","Jindal Stainless (Hisar)","JSLHISAR.NS","632806012","2.68","India"
"4818","Century Aluminum","CENX","632234944","6.93","United States"
"4819","Vertical Aerospace","EVTL","630981248","3.02","United Kingdom"
"4820","Nkarta","NKTX","630708032","13.03","United States"
"4821","Aston Martin","A5SA.F","629551493","5.41","United Kingdom"
"4822","Sangamo Therapeutics","SGMO","629287232","4.29","United States"
"4823","Hingham Institution for Savings","HIFS","627615360","292.54","United States"
"4824","Nano-X Imaging","NNOX","626006400","12.02","Israel"
"4825","Vanda Pharmaceuticals","VNDA","625905856","11.08","United States"
"4826","Wirtualna Polska (WP Holding)","WPL.WA","625820327","21.39","Poland"
"4827","Amalgamated Financial","AMAL","625719168","20.28","United States"
"4828","Ranger Oil","ROCC","625378432","29.55","United States"
"4829","Coherus BioSciences","CHRS","622480896","8.04","United States"
"4830","DICE Therapeutics","DICE","621608448","16.26","United States"
"4831","G8 Education","GEM.AX","621522461","0.73","Australia"
"4832","HCI Group","HCI","621187840","68.45","United States"
"4833","Navios Maritime Partners","NMM","620852352","20.56","Monaco"
"4834","Electrica","ECEA.F","620565430","6.99","Romania"
"4835","The Hackett Group","HCKT","618460544","19.54","United States"
"4836","Smith & Wesson","SWBI","618263552","13.51","United States"
"4837","Indus Holding","INH.F","617838238","22.67","Germany"
"4838","Heidrick & Struggles","HSII","617758656","31.33","United States"
"4839","Chico's","CHS","616954944","4.93","United States"
"4840","Skillsoft","SKIL","616436928","3.76","United States"
"4841","NextDecade Corp","NEXT","615470464","4.81","United States"
"4842","CEWE","CWC.F","613957888","84.57","Germany"
"4843","CEAT","CEATLTD.NS","612490248","15.14","India"
"4844","COLOPL","3668.T","611898832","4.77","Japan"
"4845","Caverion","CAV1V.HE","611349623","4.48","Finland"
"4846","Inogen","INGN","610857664","26.75","United States"
"4847","Invitae","NVTA","608762240","2.66","United States"
"4848","Varroc","VARROC.NS","607820969","3.98","India"
"4849","TrueBlue","TBI","607206720","18.25","United States"
"4850","Piedmont Lithium","PLL","606808768","33.83","Australia"
"4851","Suprajit Engineering","SUPRAJIT.NS","605728304","4.37","India"
"4852","Yalla Group","YALA","604957888","4.08","United Arab Emirates"
"4853","Delta Corp","DELTACORP.NS","604465730","2.26","India"
"4854","INDUS Realty Trust","INDT","602558720","59.16","United States"
"4855","Sema4","SMFR","601712128","1.6","United States"
"4856","Central Pacific Financial","CPF","601042560","21.82","United States"
"4857","TrustCo Bank","TRST","599903104","31.25","United States"
"4858","Maverix Metals","MMX","599706368","4.07","Canada"
"4859","UFP Technologies","UFPT","596678016","78.91","United States"
"4860","SilverBow Resources","SBOW","595583552","26.7","United States"
"4861","Olectra Greentech","OLECTRA.NS","594999358","7.25","India"
"4862","Eagle Bulk Shipping","EGLE","594682624","43.43","United States"
"4863","Collegium Pharmaceutical","COLL","593853248","17.48","United States"
"4864","Sohu.com","SOHU","593569024","15.53","China"
"4865","Hibbett Sports","HIBB","593069760","45.85","United States"
"4866","Hyliion","HYLN","592425984","3.41","United States"
"4867","Eagle Pharmaceuticals","EGRX","592146240","44.81","United States"
"4868","NerdWallet","NRDS","592106624","8.71","United States"
"4869","Yext","YEXT","591986496","4.79","United States"
"4870","Shoe Carnival","SCVL","591198016","21.43","United States"
"4871","Pulmonx","LUNG","590896256","15.92","United States"
"4872","PDS Multinational","PDSMFL.NS","590788155","22.65","India"
"4873","Jindal Worldwide","JINDWORLD.NS","590145906","2.9","India"
"4874","Ingersoll Rand India","INGERRAND.NS","589071059","18.66","India"
"4875","Finnair","FIA1S.HE","588945890","0.41","Finland"
"4876","Carriage Services","CSV","588417216","39.52","United States"
"4877","Cardiovascular Systems","CSII","588121152","14.42","United States"
"4878","Kezar Life Sciences","KZR","587843776","9.73","United States"
"4879","Orion Office REIT","ONL","587774784","10.38","United States"
"4880","Savencia Fromage & Dairy","SAVE.PA","587244243","59.93","France"
"4881","Gujarat Mineral Development","GMDCLTD.NS","586140988","1.84","India"
"4882","8x8","EGHT","586101376","4.94","United States"
"4883","Swvl Holdings","SWVL","586093184","4.93","United Arab Emirates"
"4884","Voltamp Transformers","VOLTAMP.NS","583980063","40.23","India"
"4885","Samyang Foods","003230.KS","583953568","78","South Korea"
"4886","York Water","YORW","582107904","40.86","United States"
"4887","Janux Therapeutics","JANX","581146432","13.96","United States"
"4888","QuinStreet","QNST","580955264","10.6","United States"
"4889","Tunas Ridean","TURI.JK","580900923","0.1","Indonesia"
"4890","Rashtriya Chemicals and Fertilizers","RCF.NS","579397487","1.05","India"
"4891","The First Bancshares","FBMS","578988288","28.2","United States"
"4892","Endeavour Silver","EXK","578356224","3.05","Canada"
"4893","RAPT Therapeutics","RAPT","577964416","19.5","United States"
"4894","American Software","AMSWA","576065792","17.12","United States"
"4895","DXP Enterprises","DXPE","576056320","30.9","United States"
"4896","Titan Machinery","TITN","575242240","25.49","United States"
"4897","FRP Holdings","FRPH","574408192","60.9","United States"
"4898","Dorian LPG","LPG","574331840","14.31","United States"
"4899","Celularity","CELU","572307264","4.02","United States"
"4900","Maxeon Solar Technologies","MAXN","569669696","12.77","Singapore"
"4901","LendingTree","TREE","569222592","44.59","United States"
"4902","Focus Universal","FCUV","569019584","13.02","United States"
"4903","Atlanticus","ATLC","566410944","37.98","United States"
"4904","Fluence Energy","FLNC","566045248","10.26","United States"
"4905","Jumia","JMIA","565803776","5.67","Germany"
"4906","Modine Manufacturing","MOD","565466240","10.88","United States"
"4907","VTEX","VTEX","565445824","2.96","United Kingdom"
"4908","Inhibrx","INBX","564088960","14.45","United States"
"4909","Phillips Carbon Black","PHILIPCARB.NS","563545169","3.24","India"
"4910","City Office REIT","CIO","562722880","12.92","Canada"
"4911","Indiabulls Housing Finance","IBULHSGFIN.NS","562597129","1.19","India"
"4912","Vinci Partners","VINP","561994304","10.1","Brazil"
"4913","SandRidge Energy","SD","561174784","15.28","United States"
"4914","Ebix","EBIX","560922112","18.15","United States"
"4915","WM Technology","MAPS","560243648","3.21","United States"
"4916","PREOS Real Estate","PAG.F","560015252","4.68","Germany"
"4917","GAMCO Investors","GBL","558138432","21.06","United States"
"4918","Denny's","DENN","557881024","9.04","United States"
"4919","Amarin Corporation","AMRN","557796224","1.41","Ireland"
"4920","Mullen Automotive","MULN","556300288","1.17","United States"
"4921","Stitch Fix","SFIX","555998912","5.14","United States"
"4922","Jindal Poly Films","JINDALPOLY.NS","554626961","12.67","India"
"4923","Loma Negra","LOMA","554303552","4.73","Argentina"
"4924","Youdao","DAO","554263616","4.4","China"
"4925","Bangkok Airways","BA.BK","554189264","0.26","Thailand"
"4926","Telesat","TSAT","554082304","11.21","Canada"
"4927","National Energy Services Reunited","NESR","553648896","6.06","United States"
"4928","SunCoke Energy","SXC","553648512","6.64","United States"
"4929","IDEAYA Biosciences","IDYA","553323328","14.32","United States"
"4930","Tricida","TCDA","553140480","9.98","United States"
"4931","Starry Group","STRY","550545792","3.31","United States"
"4932","Vista Oil & Gas","VIST","550133568","6.37","Mexico"
"4933","Obsidian Energy","OBE","549982208","6.7","Canada"
"4934","5E Advanced Materials","FEAM","548730112","12.83","United States"
"4935","First Financial","THFF","548422464","44.15","United States"
"4936","Viad","VVI","547915904","26.61","United States"
"4937","Borr Drilling","BORR","547633792","3.58","Bermuda"
"4938","BLS International","BLS.NS","546216117","2.67","India"
"4939","Barrett Business Services","BBSI","546009984","74.59","United States"
"4940","Jeju Air","089590.KS","545302654","10.97","South Korea"
"4941","Offerpad","OPAD","544457216","2.22","United States"
"4942","NETGEAR","NTGR","543773760","18.9","United States"
"4943","One Liberty Properties","OLP","543474048","25.73","United States"
"4944","Arlo Technologies","ARLO","542881920","6.25","United States"
"4945","Hyster-Yale Materials Handling","HY","541860032","32.04","United States"
"4946","Chatham Lodging Trust","CLDT","540272448","11.07","United States"
"4947","Ruth's Hospitality Group","RUTH","540237696","15.74","United States"
"4948","Diamond Hill Investment Group","DHIL","539569280","170.18","United States"
"4949","Ethan Allen","ETD","539354304","21.3","United States"
"4950","Opera","OPRA","538831808","4.68","Norway"
"4951","Trinity Capital","TRIN","538743744","14.11","United States"
"4952","The Children's Place","PLCE","538417280","40.87","United States"
"4953","Gossamer Bio","GOSS","538274624","6.98","United States"
"4954","LiveChat Software","LVC.WA","537821234","20.8","Poland"
"4955","Neenah","NP","537219200","32","United States"
"4956","Gevo","GEVO","537034432","2.29","United States"
"4957","Teekay Tankers","TNK","535129984","15.83","Canada"
"4958","Bioceres Crop Solutions","BIOX","534833696","11.66","Argentina"
"4959","Columbia Care","CCHWF","533111104","1.41","United States"
"4960","Waterdrop Inc.","WDH","530961760","1.35","China"
"4961","PetIQ","PETQ","530673792","17.52","United States"
"4962","Immatics","IMTX","530472928","8.43","Germany"
"4963","Greenlam Industries","GREENLAM.NS","530416113","4.4","India"
"4964","W&T Offshore","WTI","529144416","3.7","United States"
"4965","Rigetti Computing","RGTI","528337600","4.6","United States"
"4966","ANI Pharmaceuticals","ANIP","527407136","30.58","United States"
"4967","Rimini Street","RMNI","527079424","6.06","United States"
"4968","OneWater Marine","ONEW","526499712","33.83","United States"
"4969","Intrepid Potash","IPI","525954176","38.62","United States"
"4970","Vaxart","VXRT","524839424","4.15","United States"
"4971","Faro Technologies","FARO","524741344","28.74","United States"
"4972","AnaptysBio","ANAB","522570304","18.54","United States"
"4973","Donegal Group","DGICA","522023808","16.75","United States"
"4974","Barbeque Nation Hospitality","BARBEQUE.NS","521901103","13.4","India"
"4975","JCI Hitachi India","JCHAC.NS","521884463","19.12","India"
"4976","Ambac","AMBC","521787232","11.59","United States"
"4977","NIU","NIU","521542688","6.78","China"
"4978","trivago","TRVG","521520064","1.45","Germany"
"4979","Babcock & Wilcox","BW","521480320","6.04","United States"
"4980","MetroCity Bankshares","MCBS","521017984","20.46","United States"
"4981","Jin Air","272450.KS","520214969","10.09","South Korea"
"4982","Cazoo","CZOO","519827744","0.68","United Kingdom"
"4983","Centessa Pharmaceuticals","CNTA","519106304","5.52","United Kingdom"
"4984","TravelCenters of America","TA","518839424","34.97","United States"
"4985","HEG","HEG.NS","518729572","13.44","India"
"4986","Enento Group","ENENTO.HE","518399807","21.57","Finland"
"4987","Bank of Marin Bancorp","BMRC","517349440","32.34","United States"
"4988","New Gold","NGD","517337216","0.71","Canada"
"4989","loanDepot","LDI","517318912","1.52","United States"
"4990","Granite Point Mortgage Trust","GPMT","517013792","9.6","United States"
"4991","Cardlytics","CDLX","516843744","15.15","United States"
"4992","COMPASS Pathways","CMPS","514600480","12.11","United Kingdom"
"4993","Skillz","SKLZ","513955136","1.26","United States"
"4994","AMMO","POWW","513570176","4.41","United States"
"4995","FDC India","FDC.NS","513017232","3.09","India"
"4996","CatchMark Timber Trust","CTT","512911104","10.41","United States"
"4997","Simona","SIM0.F","512820513","85.47","Germany"
"4998","Whitestone REIT","WSR","512649664","10.27","United States"
"4999","Despegar","DESP","511355040","7.72","Argentina"
"5000","HBT Financial","HBT","510727200","17.66","United States"
"5001","Argan","AGX","510018944","35.91","United States"
"5002","Altimmune","ALT","509643168","11.79","United States"
"5003","Senseonics Holdings","SENS","509589312","1.1","United States"
"5004","ViewRay","VRAY","507989280","2.82","United States"
"5005","Cara Therapeutics","CARA","506972768","9.46","United States"
"5006","Liquidity Services","LQDT","506351840","15.73","United States"
"5007","Cerberus Cyber Sentinel","CISO","506302304","4.06","United States"
"5008","Chennai Petroleum","CHENNPETRO.NS","505778191","3.4","India"
"5009","PennantPark Floating Rate","PFLT","505259200","12.23","United States"
"5010","Orchid Island Capital","ORC","504783424","2.85","United States"
"5011","Appen","APX.AX","504668446","4.06","Australia"
"5012","Innoviz","INVZ","504488608","3.74","Israel"
"5013","Community Health Systems","CYH","503082080","3.74","United States"
"5014","Arrow Financial","AROW","502943200","31.4","United States"
"5015","MaxCyte","MXCT","502622976","4.95","United States"
"5016","Ducommun","DCO","502029280","41.72","United States"
"5017","Eagle Point Credit Company","ECC","501808608","12.16","United States"
"5018","REX American Resources","REX","501622816","84.25","United States"
"5019","Core Scientific","CORZ","501123680","1.54","United States"
"5020","Turning Point Brands","TPB","501108704","27.63","United States"
"5021","LoveSac","LOVE","500644096","33.1","United States"
"5022","Iguatemi","IGTI3.SA","499404959","0.45","Brazil"
"5023","Telos","TLS","498946688","7.35","United States"
"5024","Heidelbergcement India","HEIDELBERG.NS","498928719","2.2","India"
"5025","Playstudios","MYPS","498924128","3.95","United States"
"5026","Religare","RELIGARE.NS","498249573","1.56","India"
"5027","Ranpak","PACK","498145984","6.08","United States"
"5028","Ituran","ITRN","497223008","24.24","Israel"
"5029","Traeger","COOK","496490368","4.2","United States"
"5030","Pearl Abyss","263750.KQ","496365111","38.12","South Korea"
"5031","Zumiez","ZUMZ","496317088","25.51","United States"
"5032","Imago BioSciences","IMGO","496253632","14.71","United States"
"5033","Tata Coffee","TATACOFFEE.NS","495538603","2.65","India"
"5034","SurModics","SRDX","495385888","35.41","United States"
"5035","Bluegreen Vacations","BVH","494611040","24.58","United States"
"5036","Tattooed Chef","TTCF","493521920","5.99","United States"
"5037","PORR","ABS2.F","493001524","11.93","Austria"
"5038","Akoya Biosciences","AKYA","492423776","13.1","United States"
"5039","Harsco","HSC","492189984","6.2","United States"
"5040","Reliance Power","RPOWER.NS","491793227","0.14","India"
"5041","Newtek","NEWT","491081600","20.33","United States"
"5042","Godawari Power & Ispat","GPIL.NS","490708540","3.48","India"
"5043","IFB Industries","IFBIND.NS","490354877","12.08","India"
"5044","Aarti Drugs","AARTIDRUGS.NS","490095850","5.29","India"
"5045","BJ's Restaurants","BJRI","487882784","20.82","United States"
"5046","Weight Watchers","WW","487395200","6.93","United States"
"5047","Astec Lifesciences","ASTEC.NS","487180771","24.85","India"
"5048","RCI Hospitality Holdings","RICK","485753760","51.59","United States"
"5049","Nacon","NACON.PA","485629522","5.63","France"
"5050","Tufin","TUFN","485358112","12.65","Israel"
"5051","Banco Latinoamericano de Comercio Exterior","BLX","484953280","13.39","Panama"
"5052","Mersana Therapeutics","MRSN","484471520","5","United States"
"5053","Tetra Technologies","TTI","483994368","3.79","United States"
"5054","Nazara Technologies","NAZARA.NS","483639195","7.37","India"
"5055","DoubleDown Interactive","DDI","481659072","9.72","United States"
"5056","Gladstone Investment","GAIN","481635200","14.5","United States"
"5057","Immunovant","IMVT","481211104","4.13","United States"
"5058","Rovio Entertainment","ROVIO.HE","479290980","6.34","Finland"
"5059","Genius Sports","GENI","479113216","2.33","United Kingdom"
"5060","HilleVax","HLVX","479011776","14.33","United States"
"5061","Ramaco Resources","METC","478152736","10.8","United States"
"5062","Marcus Corporation","MCS","476191072","15.07","United States"
"5063","Orthofix Medical","OFIX","475896800","23.9","United States"
"5064","DRDGOLD","DRD","475747712","5.55","South Africa"
"5065","Kimball Electronics","KE","475048864","19.12","United States"
"5066","Wheels Up","UP","474608224","1.93","United States"
"5067","Garrett Motion","GTX","474366016","7.32","Switzerland"
"5068","Cue Health","HLTH","473324096","3.21","United States"
"5069","Equity BancShares","EQBK","472992160","29.06","United States"
"5070","National Presto Industries","NPK","472247200","66.95","United States"
"5071","Computer Programs and Systems","CPSI","471998688","31.97","United States"
"5072","Capital City Bank Group","CCBG","471990656","27.85","United States"
"5073","Karur Vysya Bank","KARURVYSYA.NS","471969449","0.59","India"
"5074","Hippo","HIPO","471412704","0.83","United States"
"5075","RADA Electronic Industries","RADA","470328512","9.46","Israel"
"5076","CION Investment","CION","469337216","8.24","United States"
"5077","fuboTV","FUBO","469182880","2.54","United States"
"5078","Gateway Distriparks","GDL.NS","469048583","3.76","India"
"5079","1-800-PetMeds","PETS","468545440","22.32","United States"
"5080","Central Puerto","CEPU","468100000","3.1","Argentina"
"5081","Riley Permian","REPX","466567232","23.88","United States"
"5082","Aaron's","AAN","466466656","15.19","United States"
"5083","ON24","ONTF","466267680","9.95","United States"
"5084","EHang Holdings","EH","465643840","8.12","China"
"5085","Artesian Resources","ARTNA","464161664","49.78","United States"
"5086","The RMR Group","RMR","463857184","28.11","United States"
"5087","Infibeam Avenues","INFIBEAM.NS","463253987","0.17","India"
"5088","Torrid","CURV","462386048","4.46","United States"
"5089","Gaotu Techedu","GOTU","462079520","1.79","China"
"5090","JSW Holdings","JSWHL.NS","461515551","41.7","India"
"5091","nLIGHT","LASR","461104928","10.35","United States"
"5092","Clear Channel Outdoor","CCO","460937216","0.97","United States"
"5093","PlayWay","6P5.F","460631618","67.97","Poland"
"5094","Navitas Semiconductor","NVTS","460130528","3.72","Ireland"
"5095","Koppers","KOP","459650976","21.74","United States"
"5096","MidWestOne Financial Group","MOFG","458889824","29.27","United States"
"5097","Arcturus Therapeutics","ARCT","457444992","17.32","United States"
"5098","Aveanna Healthcare","AVAH","457211680","2.48","United States"
"5099","Amryt Pharma","AMYT","456035424","7.11","United Kingdom"
"5100","Bridgewater Bancshares","BWB","455159776","16.27","United States"
"5101","Cass Information Systems","CASS","454774784","33.31","United States"
"5102","Tutor Perini","TPC","454145760","8.87","United States"
"5103","Seneca Foods","SENEA","454014880","55.34","United States"
"5104","Mail.ru Group","RL9A.F","453626948","2.01","Cyprus"
"5105","C4 Therapeutics","CCCC","452838016","9.28","United States"
"5106","Stoneridge","SRI","452066528","16.55","United States"
"5107","BBVA Argentina","BBAR","451363776","2.21","Argentina"
"5108","Bandwidth","BAND","449681408","17.79","United States"
"5109","SI-BONE","SIBN","449008128","13.24","United States"
"5110","ESS Tech","GWH","447279168","2.93","United States"
"5111","Synlait Milk","SML.NZ","446660540","2.04","New Zealand"
"5112","Workhorse Group","WKHS","446387776","2.73","United States"
"5113","Kodiak Sciences","KOD","446281440","8.59","United States"
"5114","Sportsman's Warehouse","SPWH","446061280","10.11","United States"
"5115","CareMax","CMAX","445576800","5.1","United States"
"5116","Mahindra Logistics","MAHLOG.NS","444056396","6.17","India"
"5117","The Tinplate Company Of India","TINPLATE.NS","443973505","4.24","India"
"5118","Indoco Remedies","INDOCO.NS","441118391","4.79","India"
"5119","Largo","LGO","439810528","6.68","Canada"
"5120","Vuzix","VUZI","439626848","6.91","United States"
"5121","VSE Corporation","VSEC","439238272","34.37","United States"
"5122","ADMA Biologics","ADMA","438532576","2.23","United States"
"5123","Sight Sciences","SGHT","436878976","9.18","United States"
"5124","Upland Software","UPLD","434422272","13.87","United States"
"5125","Protagonist Therapeutics","PTGX","434256608","8.93","United States"
"5126","TPI Composites","TPIC","434054528","11.65","United States"
"5127","Greene County Bancorp","GCBC","434013632","50.98","United States"
"5128","ChannelAdvisor","ECOM","433975392","14.24","United States"
"5129","Webzen","069080.KQ","432236790","13.8","South Korea"
"5130","Guaranty Bancshares","GNTY","432017984","36","United States"
"5131","Engineers India","ENGINERSIN.NS","430502035","0.77","India"
"5132","Bank Mayapada Internasional","MAYA.JK","430340874","0.04","Indonesia"
"5133","AppHarvest","APPH","430339040","4.23","United States"
"5134","CapStar Financial","CSTR","429626944","19.47","United States"
"5135","QNB Finansleasing","QNBFL.IS","429476732","3.73","Turkey"
"5136","Inovio Pharmaceuticals","INO","428535712","1.87","United States"
"5137","Bionano Genomics","BNGO","428519808","1.48","United States"
"5138","Mitek Systems","MITK","425730272","9.6","United States"
"5139","Farmers & Merchants Bancorp","FMAO","424903072","32.52","United States"
"5140","Lulu's Fashion Lounge","LVLU","424440320","10.93","United States"
"5141","Oppenheimer Holdings","OPY","424215072","35.46","United States"
"5142","Affimed","AFMD","424065984","2.84","Germany"
"5143","TCNS Clothing","TCNSBRANDS.NS","423107851","6.87","India"
"5144","Intercept Pharmaceuticals","ICPT","422817408","14.23","United States"
"5145","Brasil Agro","LND","421565600","4.25","Brazil"
"5146","ZimVie","ZIMV","420931200","16.14","United States"
"5147","Covenant Logistics","CVLG","420828640","26.98","United States"
"5148","Cenntro Electric Group","CENN","420622176","1.61","United States"
"5149","Babylon Holdings","BBLN","420528192","1.01","United Kingdom"
"5150","Aura Biosciences","AURA","419881024","14.35","United States"
"5151","CSB Bank","CSBBANK.NS","419819661","2.42","India"
"5152","PennantPark Investment","PNNT","418613664","6.33","United States"
"5153","Helix Energy Solutions","HLX","418556768","2.76","United States"
"5154","Beazer Homes USA","BZH","418071488","13.29","United States"
"5155","Southern Missouri Bancorp","SMBC","416549568","44.75","United States"
"5156","Silvercorp Metals","SVM","416220384","2.3","Canada"
"5157","Havertys","HVT","415196800","24.86","United States"
"5158","Aurora Cannabis","ACB","414518752","1.25","Canada"
"5159","Akero Therapeutics","AKRO","414156640","11.03","United States"
"5160","Icelandair","ICEAIR.IC","413847182","0.01","Iceland"
"5161","Tejon Ranch","TRC","410438464","15.5","United States"
"5162","EZCorp","EZPW","410185792","7.24","United States"
"5163","CNB Financial Corp","CCNE","409351104","24.28","United States"
"5164","Daseke","DSKE","408645696","6.44","United States"
"5165","Tiptree","TIPT","406923488","11.66","United States"
"5166","CarParts.com","PRTS","406075488","7.51","United States"
"5167","Paisalo Digital","PAISALO.NS","405939843","0.92","India"
"5168","22nd Century Group","XXII","403758656","2.05","United States"
"5169","Vicarious Surgical","RBOT","402533376","3.32","United States"
"5170","Borussia Dortmund","BVB.F","401672527","3.59","Germany"
"5171","The Restaurant Group plc","RTN.L","401237338","52.25","United Kingdom"
"5172","Lexicon Pharmaceuticals","LXRX","400911936","2.68","United States"
"5173","AGC Networks","AGCNET.NS","400679230","12.11","India"
"5174","Neowiz Games","095660.KQ","399782156","18.89","South Korea"
"5175","Sudarshan Chemical","SUDARSCHEM.NS","398386368","5.75","India"
"5176","Scholar Rock Holding","SRRK","397950176","7.71","United States"
"5177","GreenTree Hospitality","GHG","397772992","3.86","China"
"5178","Bar Harbor Bankshares","BHB","397233376","26.46","United States"
"5179","Mirza International","MIRZAINT.NS","396818531","3.3","India"
"5180","Safe Bulkers","SB","396595296","3.26","Monaco"
"5181","Mishra Dhatu Nigam","MIDHANI.NS","396438749","2.11","India"
"5182","HomeTrust Bancshares","HTBI","394898976","25.12","United States"
"5183","McPhy Energy","MCPHY.PA","394683077","13.68","France"
"5184","LexinFintech Holdings","LX","394592448","2.14","China"
"5185","Financial Institutions","FISI","394080352","25.76","United States"
"5186","Esperion Therapeutics","ESPR","393676352","6.12","United States"
"5187","SmileDirectClub","SDC","391991104","1.01","United States"
"5188","Heliogen","HLGN","391492896","2.07","United States"
"5189","Chuy's","CHUY","391271488","20.66","United States"
"5190","Bed Bath & Beyond","BBBY","390193088","4.88","United States"
"5191","Gran Tierra Energy","GTE","389237280","1.03","Canada"
"5192","Centrus Energy","LEU","388461120","26.81","United States"
"5193","Valens Semiconductor","VLN","388371872","3.96","Israel"
"5194","The Beachbody Company","BODY","387327520","1.25","United States"
"5195","Strides Pharma","STAR.NS","387077111","4.31","India"
"5196","MasterCraft Boat","MCFT","386867648","21.44","United States"
"5197","New Pacific Metals","NEWP","386555328","2.45","Canada"
"5198","DouYu","DOYU","385743072","1.22","China"
"5199","Hersha Hospitality Trust","HT","385133056","9.35","United States"
"5200","Hikal","HIKAL.NS","383512817","3.11","India"
"5201","Franklin Street Properties","FSP","383209664","3.72","United States"
"5202","Vishay Precision Group","VPG","382984256","28.07","United States"
"5203","Penseco Financial Services","PFIS","382982688","53.4","United States"
"5204","Spandana Sphoorty Financial","SPANDANA.NS","381964839","5.38","India"
"5205","Sunlight Financial","SUNL","381922080","2.89","United States"
"5206","Digital Bros","DIB.MI","380869888","26.65","Italy"
"5207","Eastman Kodak Company","KODK","380457536","4.82","United States"
"5208","a.k.a. Brands","AKA","380175520","2.96","United States"
"5209","Enterprise Bancorp","EBTC","380062464","31.4","United States"
"5210","Nordic American Tankers","NAT","377128512","1.87","Bermuda"
"5211","Tallink Grupp","T5N.F","377104314","0.5","Estonia"
"5212","Arbutus Biopharma","ABUS","377025504","2.54","United States"
"5213","Entravision Communications","EVC","376964736","4.4","United States"
"5214","Casa Systems","CASA","376720800","4","United States"
"5215","Arbe Robotics","ARBE","375682656","5.95","Israel"
"5216","Nilkamal","NILKAMAL.NS","375613072","25.13","India"
"5217","Quantum-Si","QSI","375033376","2.7","United States"
"5218","Dynamic Materials Corporation","BOOM","374843424","19.23","United States"
"5219","Citizens & Northern Corp","CZNC","374522400","24","United States"
"5220","MOIL","MOIL.NS","373914047","1.84","India"
"5221","Haynes International","HAYN","373769984","30","United States"
"5222","Vera Therapeutics","VERA","373681920","13.8","United States"
"5223","Allied Motion Technologies","AMOT","373196224","24.08","United States"
"5224","Generation Bio","GBIO","372213760","6.52","United States"
"5225","Rite Aid","RAD","372143296","6.69","United States"
"5226","Hathway","HATHWAY.NS","371794902","0.21","India"
"5227","Shore Bancshares","SHBI","371783008","18.73","United States"
"5228","Gannett","GCI","371608224","2.54","United States"
"5229","Braemar Hotels & Resorts","BHR","369904000","4.52","United States"
"5230","Sify","SIFY","369138848","2.02","India"
"5231","American National Bank & Trust Company","AMNB","367885568","34.36","United States"
"5232","Karyopharm Therapeutics","KPTI","367873984","4.63","United States"
"5233","Automotive Axles","AUTOAXLES.NS","367802348","24.34","India"
"5234","MeiraGTx","MGTX","367521952","8.22","United States"
"5235","The Manitowoc Company","MTW","366966496","10.39","United States"
"5236","Phathom Pharmaceuticals","PHAT","366886080","9.39","United States"
"5237","Lands' End","LE","366885696","10.98","United States"
"5238","Gladstone Capital","GLAD","366714016","10.69","United States"
"5239","NI Holdings","NODK","364396032","17.16","United States"
"5240","Macquarie Infrastructure","MIC","363060416","4.08","United States"
"5241","Nautilus Biotechnology","NAUT","362184416","2.91","United States"
"5242","Satellogic","SATL","362050624","3.99","United States"
"5243","Entrada Therapeutics","TRDA","361331712","11.52","United States"
"5244","Vital Farms","VITL","360192064","8.87","United States"
"5245","Clovis Oncology","CLVS","359697536","2.5","United States"
"5246","ShotSpotter","SSTI","359634208","29.62","United States"
"5247","Willdan Group","WLDN","359324352","27.21","United States"
"5248","Daily Journal","DJCO","359008832","260.01","United States"
"5249","Lordstown Motors","RIDE","358217280","1.74","United States"
"5250","AirSculpt Technologies","AIRS","357766464","6.43","United States"
"5251","Kaveri Seed","KSCL.NS","357156937","6.12","India"
"5252","Vaalco Energy","EGY","356946720","6.06","United States"
"5253","Humacyte","HUMA","356397312","3.46","United States"
"5254","Kirloskar Ferrous Industries","KIRLFER.NS","355108860","2.56","India"
"5255","First Internet Bancorp","INBK","354645760","36.73","United States"
"5256","Hailiang Education","HLG","353675552","13.72","China"
"5257","Radiant Logistics","RLGT","353118688","7.14","United States"
"5258","Regional Management","RM","353027264","36.5","United States"
"5259","Southern First Bancshares","SFST","352541216","44.16","United States"
"5260","Transcontinental Realty Investors","TCI","350842784","40.61","United States"
"5261","Mesoblast","MESO","350637760","2.67","Australia"
"5262","SelectQuote","SLQT","350176288","2.13","United States"
"5263","Summit Financial Group","SMMF","349476608","27.37","United States"
"5264","Markforged","MKFG","348610144","1.86","United States"
"5265","Civeo","CVEO","347738464","24.55","United States"
"5266","Rupa Company","RUPA.NS","347472263","4.37","India"
"5267","Axogen","AXGN","347175392","8.27","United States"
"5268","Tata Steel Long Products","TATASTLLP.NS","347093254","7.7","India"
"5269","Gilat Telecom","GILT","346350976","6.12","Israel"
"5270","Ideanomics","IDEX","345291072","0.69","United States"
"5271","Meta Materials","MMAT","344732928","0.96","Canada"
"5272","Gravity Co.","GRVY","343935808","49.5","South Korea"
"5273","Cosmo Films","COSMOFILMS.NS","343138668","12.59","India"
"5274","Avon Protection","AVON.L","342580257","1132.19","United Kingdom"
"5275","Clipper Realty","CLPR","342011424","8.07","United States"
"5276","F45 Training","FXLV","340603360","3.56","United States"
"5277","Astra Space","ASTR","340466784","1.29","United States"
"5278","Ayr Wellness","AYRWF","340403104","4.95","United States"
"5279","bluebird bio","BLUE","339755168","4.75","United States"
"5280","Reliance Infrastructure","RELINFRA.NS","339371783","1.29","India"
"5281","El Pollo Loco","LOCO","338858048","9.22","United States"
"5282","The Container Store","TCS","338689280","6.69","United States"
"5283","IRSA Propiedades Comerciales","IRCP","338058496","2.5","Argentina"
"5284","Civista Bancshares","CIVB","337325024","21.54","United States"
"5285","Qiwi","QIWI.ME","336599714","5.37","Cyprus"
"5286","Zymeworks","ZYME","335072960","5.8","Canada"
"5287","Gold Royalty Corp","GROY","334705344","2.49","Canada"
"5288","HBL Power Systems","HBLPOWER.NS","334169382","1.21","India"
"5289","Tredegar","TG","333791552","9.86","United States"
"5290","Bushiroad","7803.T","333117428","10.38","Japan"
"5291","SciPlay","SCPL","332008384","13.46","United States"
"5292","Angel Oak REIT","AOMR","331782368","13.31","United States"
"5293","Information Services Group","III","331519936","6.89","United States"
"5294","Bakhu Holdings","BKUH","331374976","1.1","United States"
"5295","ATI Physical Therapy","ATIP","328851744","1.59","United States"
"5296","Blade Air Mobility","BLDE","328687552","4.62","United States"
"5297","Berkeley Lights","BLI","328280768","4.84","United States"
"5298","India Glycols","INDIAGLYCO.NS","327944707","10.59","India"
"5299","First Bancorp","FNLC","327293248","29.68","United States"
"5300","Action Construction Equipment","ACE.NS","327183185","2.75","India"
"5301","Ramkrishna Forgings","RKFORGE.NS","326981445","2.04","India"
"5302","Velo3D","VLD","326349728","1.78","United States"
"5303","Time Technoplast","TIMETECHNO.NS","323969205","1.43","India"
"5304","Ocular Therapeutix","OCUL","323541728","4.22","United States"
"5305","People Can Fly","PCF.WA","323457260","10.8","Poland"
"5306","Sequent Scientific","SEQUENT.NS","322972535","1.29","India"
"5307","Heron Therapeutics","HRTX","322299584","3.15","United States"
"5308","JOANN","JOAN","321679136","7.91","United States"
"5309","OrganiGram Holdings","OGI","321532224","1.03","Canada"
"5310","Bafang Yunji","2753.TW","320918361","4.86","Taiwan"
"5311","Schneider Electric Infrastructure","SCHNEIDER.NS","320878350","1.34","India"
"5312","Somany Ceramics","SOMANYCERA.NS","320607886","7.55","India"
"5313","Sierra Bancorp","BSRR","320577504","21.25","United States"
"5314","North American Construction Group","NOA","320430368","11.25","Canada"
"5315","Duluth Holdings","DLTH","319919520","9.59","United States"
"5316","Burning Rock Biotech","BNR","319245600","3.04","China"
"5317","Hyderabad Industries Limited","HIL.NS","317184980","42.2","India"
"5318","OPTiM","3694.T","317155720","5.76","Japan"
"5319","ReneSola","SOL","316882976","4.72","United States"
"5320","India Tourism Development Corp","ITDC.NS","316235447","3.69","India"
"5321","Global Cord Blood","CO","315935360","2.6","Hong Kong"
"5322","Astronics Corporation","ATRO","314817728","9.97","United States"
"5323","Hemisphere Media Group","HMTV","313913440","7.77","United States"
"5324","AO World","AO.L","313618029","54.7","United Kingdom"
"5325","Priority Technology Holdings","PRTH","313130784","4.07","United States"
"5326","eGain","EGAN","313116672","9.84","United States"
"5327","Precigen","PGEN","312577952","1.51","United States"
"5328","Caesarstone","CSTE","310628768","9.01","Israel"
"5329","Aeroporto G. Marconi Bologna","ADB.MI","310325510","8.49","Italy"
"5330","Arizona Metals","AMC.V","309666055","2.78","Canada"
"5331","Ellomay Capital","ELLO","308640192","24.02","Israel"
"5332","AEye","LIDR","305268736","1.94","United States"
"5333","Marine Products Corporation","MPX","303868224","8.9","United States"
"5334","Siyaram Silk Mills","SIYSIL.NS","303829165","6.48","India"
"5335","Pizza Pizza","PZA.TO","303251677","9.42","Canada"
"5336","Glatfelter","GLT","302086304","6.76","United States"
"5337","Marvelous","7844.T","300155312","4.97","Japan"
"5338","Digimarc","DMRC","299911136","15.04","United States"
"5339","Tupperware Brands","TUP","299346880","6.53","United States"
"5340","Mind Medicine","MNMD","298941824","0.65","United States"
"5341","FutureFuel","FF","298902656","6.83","United States"
"5342","PTC India","PTC.NS","298210972","1.01","India"
"5343","EverQuote","EVER","298059648","9.5","United States"
"5344","Macatawa Bank","MCBC","298009792","8.7","United States"
"5345","Trean Insurance Group","TIG","297938624","5.82","United States"
"5346","Lumber Liquidators","LL","297787008","10","United States"
"5347","Doma","DOMA","297369440","0.92","United States"
"5348","Taseko Mines","TGB","296937920","1.04","Canada"
"5349","Preformed Line Products","PLPC","296405408","60","United States"
"5350","BCB Bancorp","BCBP","296158368","17.43","United States"
"5351","Oil States International","OIS","295217984","4.62","United States"
"5352","Home Bancorp","HBCP","294379840","35.28","United States"
"5353","Groupon","GRPN","294207200","9.82","United States"
"5354","Orient Cement","ORIENTCEM.NS","294002511","1.44","India"
"5355","SpiceJet","SPICEJET.NS","292536677","0.49","India"
"5356","Huttig Building Products","HBP","292397824","10.7","United States"
"5357","Revlon","REV","292392864","5.36","United States"
"5358","SkyWater Technology","SKYT","292249664","7.25","United States"
"5359","Vesuvius India","VESUVIUS.NS","291430327","14.36","India"
"5360","Landec","LNDC","290992256","9.87","United States"
"5361","PCSB Financial","PCSB","290289664","18.93","United States"
"5362","Green Plains Partners","GPP","289881696","12.48","United States"
"5363","Northwest Pipe Company","NWPX","288555008","29.1","United States"
"5364","CIRCOR International","CIR","288473920","14.24","United States"
"5365","Arvind","ARVIND.NS","288361393","1.1","India"
"5366","Rockley Photonics","RKLY","287681152","2.23","United Kingdom"
"5367","NACCO Industries","NC","287634592","39.25","United States"
"5368","Third Coast Bancshares","TCBX","287443680","21.36","United States"
"5369","Unity Bancorp","UNTY","286820160","27.33","United States"
"5370","Purple Innovation","PRPL","286780576","3.47","United States"
"5371","Northeast Bank","NBN","286693504","37.5","United States"
"5372","Kyokuyo","1301.T","285840285","26.46","Japan"
"5373","Ouster","OUST","284808960","1.64","United States"
"5374","Ooma","OOMA","284796000","11.72","United States"
"5375","Kimball International","KBAL","284586912","7.73","United States"
"5376","Grindrod Shipping","GRIN","283042944","14.93","Singapore"
"5377","Zynex","ZYXI","282975008","7.35","United States"
"5378","Vst Tillers Tractors","VSTTILLERS.NS","282664121","32.7","India"
"5379","CompX International","CIX","281537120","22.74","United States"
"5380","Hindustan Oil Exploration Company","HINDOILEXP.NS","281325070","2.12","India"
"5381","Investors Title Company","ITIC","281287744","148.26","United States"
"5382","Blue Bird Corporation","BLBD","281200000","8.79","United States"
"5383","PyroGenesis Canada","PYR","280970240","1.65","Canada"
"5384","PLBY Group (Playboy)","PLBY","280876896","6.16","United States"
"5385","West Coast Paper Mills","WSTCSTPAPR.NS","280326622","4.24","India"
"5386","Solo Brands","DTC","280231552","4.42","United States"
"5387","Avadel Pharmaceuticals","AVDL","280136256","4.75","Ireland"
"5388","Focus Home Interactive","ALFOC.PA","279716746","45.25","France"
"5389","Greenply","GREENPLY.NS","279131458","2.27","India"
"5390","Qudian","QD","278984896","1.11","China"
"5391","Inox Wind","INOXWIND.NS","278642048","1","India"
"5392","Cognyte Software","CGNT","277345696","4.11","Israel"
"5393","Argonaut Gold","AR.TO","276831190","0.35","United States"
"5394","REE Automotive","REE","276596192","1.16","Israel"
"5395","Jain Irrigation Systems","JISLDVREQS.NS","276461444","0.25","India"
"5396","Safari Industries India","SAFARI.NS","276060127","12.33","India"
"5397","Karnataka Bank","KTKBANK.NS","275650620","0.89","India"
"5398","PolyMet","PLM","275643008","2.7","Canada"
"5399","Dish TV","DISHTV.NS","275582232","0.15","India"
"5400","MBM Resources","5983.KL","275551574","0.71","Malaysia"
"5401","Provident Bancorp","PVBC","274295552","15.4","United States"
"5402","EyePoint Pharmaceuticals","EYPT","274079168","8.05","United States"
"5403","Bitfarms","BITF","273781984","1.17","Canada"
"5404","Newpark Resources","NR","273365184","2.96","United States"
"5405","Marathon Gold","MOZ.TO","273205217","1.07","Canada"
"5406","First Guaranty Bancshares","FGBI","272742560","25.45","United States"
"5407","Olympic Steel","ZEUS","272628640","24.5","United States"
"5408","Sutro Biopharma","STRO","272452448","5.81","United States"
"5409","Adaptimmune Therapeutics","ADAP","272191936","1.68","United Kingdom"
"5410","GasLog Partners","GLOP","272078016","5.05","Greece"
"5411","AC Immune","ACIU","271928032","3.26","Switzerland"
"5412","Tidewater Renewables","LCFS.TO","271416624","7.82","Canada"
"5413","Quotient Technology","QUOT","271371296","2.85","United States"
"5414","Alico","ALCO","271122080","35.84","United States"
"5415","National Fertilizers","NFL.NS","270880239","0.55","India"
"5416","HF Foods Group","HFFG","270680256","5.04","United States"
"5417","Vidhi Specialty Food","VIDHIING.NS","270366848","5.41","India"
"5418","A.S. Roma","ASR.MI","270333876","0.43","Italy"
"5419","ACNB Corporation","ACNB","270266208","31.04","United States"
"5420","CymaBay Therapeutics","CBAY","270122528","3.19","United States"
"5421","Inotiv","NOTV","269695648","10.57","United States"
"5422","Benefitfocus","BNFT","269528064","7.94","United States"
"5423","Electrosteel Castings","ELECTCAST.NS","268856272","0.45","India"
"5424","Talkspace","TALK","268131424","1.71","United States"
"5425","Powell Industries","POWL","267773040","22.73","United States"
"5426","First Western Financial","MYFW","267430880","28.25","United States"
"5427","Planet13","PLTH.CN","267045646","1.21","United States"
"5428","Ashoka Buildcon","ASHOKA.NS","266924803","0.95","India"
"5429","Filatex India","FILATEX.NS","266620184","1.2","India"
"5430","Liquidia Technologies","LQDA","266386224","4.14","United States"
"5431","Ashford Hospitality Trust","AHT","266305936","7.35","United States"
"5432","Ocwen","OCN","266136896","28.77","United States"
"5433","G1 Therapeutics","GTHX","266055264","6.23","United States"
"5434","Teekay","TK","265927200","2.62","Canada"
"5435","Aldeyra Therapeutics","ALDX","265854832","4.56","United States"
"5436","Orrstown Financial Services","ORRF","265204656","23.99","United States"
"5437","MM Forgings","MMFL.NS","264884453","10.97","India"
"5438","HIVE Blockchain Technologies","HIVE","264848752","3.21","Canada"
"5439","BlackSky Technology","BKSY","263914576","2.19","United States"
"5440","Big 5 Sporting Goods","BGFV","263902768","11.82","United States"
"5441","First Business Financial Services","FBIZ","263353552","31.1","United States"
"5442","Puravankara","PURVA.NS","263230428","1.11","India"
"5443","Lineage Cell Therapeutics","LCTX","263076848","1.55","United States"
"5444","Prime Focus","PFOCUS.NS","262976605","0.88","India"
"5445","AXT Inc","AXTI","262831280","6.12","United States"
"5446","Viking Therapeutics","VKTX","262683696","3.4","United States"
"5447","Root Insurance","ROOT","261880512","1.03","United States"
"5448","Chicago Atlantic Real Estate Finance","REFI","261513504","14.81","United States"
"5449","Alaunos Therapeutics","TCRT","261300720","1.21","United States"
"5450","Zomedica Pharmaceuticals","ZOM","261241360","0.27","United States"
"5451","Identiv","INVE","261096144","11.69","United States"
"5452","Motorcar Parts of America","MPAA","260970240","13.65","United States"
"5453","RattanIndia Power","RTNPOWER.NS","260035741","0.05","India"
"5454","GreenLight Biosciences","GRNA","259949872","2.11","United States"
"5455","Volta","VLTA","259644976","1.55","United States"
"5456","SRA Holdings","3817.T","258751370","20.93","Japan"
"5457","Hut 8 Mining","HUT","258281328","1.48","Canada"
"5458","Veritone","VERI","256803440","7.12","United States"
"5459","JTEKT India","JTEKTINDIA.NS","256606910","1.05","India"
"5460","Redbox","RDBX","256510000","5.65","United States"
"5461","Brightcove","BCOV","256376464","6.17","United States"
"5462","Miller Industries","MLR","255562832","22.39","United States"
"5463","Surya Roshni","SURYAROSNI.NS","255457029","4.7","India"
"5464","Outlook Therapeutics","OTLK","255315600","1.13","United States"
"5465","Voyager Therapeutics","VYGR","254579376","6.62","United States"
"5466","Hovnanian Enterprises","HOV","254579184","45.18","United States"
"5467","GrowGeneration","GRWG","254548560","4.19","United States"
"5468","Subros","SUBROS.NS","254476045","3.9","India"
"5469","LianBio","LIAN","254446240","2.35","United States"
"5470","Cepton","CPTN","254179200","1.65","United States"
"5471","Stratus Properties","STRS","253989392","30.7","United States"
"5472","Gulf Oil Lubricants","GULFOILLUB.NS","253753548","5.18","India"
"5473","Ring Energy","REI","252881360","2.37","United States"
"5474","Greenlight Reinsurance","GLRE","252770336","7.28","Cayman Islands"
"5475","Parke Bancorp","PKBK","251970528","21.15","United States"
"5476","Republic First Bancorp","FRBK","251827120","3.95","United States"
"5477","Unifi","UFI","251113312","13.59","United States"
"5478","CyberOptics","CYBE","250836688","33.88","United States"
"5479","Marksans Pharma","MARKSANS.NS","250711762","0.61","India"
"5480","Vinco Ventures","BBIG","249460880","1.07","United States"
"5481","Hester Biosciences","HESTERBIO.NS","249241962","29.3","India"
"5482","Epizyme","EPZM","247443616","1.47","United States"
"5483","RumbleON","RMBL","246827600","14.91","United States"
"5484","Weyco Group","WEYS","246763376","25.61","United States"
"5485","11 bit studios","11B.WA","246589856","103.6","Poland"
"5486","Whole Earth Brands","FREE","246444912","5.88","United States"
"5487","UBM Development","UBS.VI","246442940","32.98","Austria"
"5488","Science 37","SNCE","245667712","2.12","United States"
"5489","Park Aerospace","PKE","245498400","12","United States"
"5490","Bankwell Financial Group","BWFG","245406304","31.62","United States"
"5491","Rent the Runway","RENT","245403408","3.83","United States"
"5492","Limoneira","LMNR","245365296","13.34","United States"
"5493","AdTheorent","ADTH","245227824","2.86","United States"
"5494","Comtech Telecommunications","CMTL","244313664","9.21","United States"
"5495","Hindustan Sanitaryware & Industries","HSIL.NS","244026295","3.76","India"
"5496","Village Farms International","VFF","243554080","2.75","Canada"
"5497","Selecta Biosciences","SELB","242894384","1.6","United States"
"5498","Gabriel India","GABRIEL.NS","242724903","1.69","India"
"5499","Absa Bank","ABSP.JO","242177620","54.02","South Africa"
"5500","Cato Fashion","CATO","241983568","11.53","United States"
"5501","Kewal Kiran Clothing","KKCL.NS","241476701","3.92","India"
"5502","Acacia Research","ACTG","240500928","5.25","United States"
"5503","DHI Group","DHX","240458240","5.08","United States"
"5504","Hindustan Construction Company","HCC.NS","239776852","0.16","India"
"5505","Emerald Holding","EEX","239144992","3.41","United States"
"5506","IronNet","IRNT","238704544","2.36","United States"
"5507","Sono","SEV","237888896","2.82","Germany"
"5508","The RealReal","REAL","237820464","2.52","United States"
"5509","Cian","CIAN","237563120","3.4","Russia"
"5510","Build-A-Bear","BBW","237075232","15.21","United States"
"5511","AVEO Oncology","AVEO","236517024","6.86","United States"
"5512","I.g. Petrochemicals","IGPL.NS","236438072","7.68","India"
"5513","Stellus Capital","SCM","236294288","12.09","United States"
"5514","ThredUp","TDUP","235738528","2.38","United States"
"5515","Oriental Aromatics","OAL.NS","235572641","7","India"
"5516","TrueCar","TRUE","235549056","2.61","United States"
"5517","Porch Group","PRCH","234954432","2.37","United States"
"5518","Apollo Pipes","APOLLOPIPE.NS","234891718","5.97","India"
"5519","Arteris","AIP","234753120","7.35","United States"
"5520","Genie Energy","GNE","233926720","8.93","United States"
"5521","Alembic Limited","ALEMBICLTD.NS","233825731","0.91","India"
"5522","Silicom","SILC","232778704","35","Israel"
"5523","Troops","TROO","232659424","2.29","Hong Kong"
"5524","Trecora Resources","TREC","232631408","9.81","United States"
"5525","Northrim BanCorp","NRIM","232313392","39.94","United States"
"5526","Loop Industries","LOOP","231789424","4.89","Canada"
"5527","Jaypee Group","JPASSOCIAT.NS","231542712","0.09","India"
"5528","Lifetime Brands","LCUT","231384848","10.44","United States"
"5529","Pollux Properti Indonesia","POLL.JK","230939540","0.03","Indonesia"
"5530","T’way Air","091810.KS","230828236","1.44","South Korea"
"5531","Gallantt Ispat","GALLISPAT.NS","230482830","0.82","India"
"5532","Portman Ridge","PTMN","230226304","23.7","United States"
"5533","Investar Holding","ISTR","229728288","22.31","United States"
"5534","Astra Microwave","ASTRAMICRO.NS","229634065","2.65","India"
"5535","Tillys","TLYS","229522400","7.64","United States"
"5536","Buzzfeed","BZFD","229511568","1.69","United States"
"5537","The Original BARK Company","BARK","228778224","1.31","United States"
"5538","Urban One","UONE","228769808","5.65","United States"
"5539","Embark Technology","EMBK","228693808","0.51","United States"
"5540","Ardmore Shipping","ASC","228185104","6.6","Bermuda"
"5541","eHealth","EHTH","228109408","8.5","United States"
"5542","Weave Communications","WEAV","227253248","3.5","United States"
"5543","Diebold Nixdorf","DBD","227035024","2.88","United States"
"5544","AeroClean Technologies","AERC","226281392","14.72","United States"
"5545","Bel Fuse","BELFB","225694416","17.07","United States"
"5546","NVE Corporation","NVEC","225599760","46.7","United States"
"5547","Destination XL","DXLG","225515872","3.6","United States"
"5548","Lightning eMotors","ZEV","225231760","2.98","United States"
"5549","Amplify Energy","AMPY","225171712","5.88","United States"
"5550","Ceragon Networks","CRNT","225124544","2.68","Israel"
"5551","Cantabil Retail India","CANTABIL.NS","224141341","13.66","India"
"5552","Anant Raj","ANANTRAJ.NS","224001344","0.76","India"
"5553","Concert Pharmaceuticals","CNCE","223886336","4.82","United States"
"5554","Gati","GATI.NS","223719186","1.82","India"
"5555","SOPHiA GENETICS","SOPH","223703200","3.5","Switzerland"
"5556","Oil-Dri Corporation Of America","ODC","223193216","31.03","United States"
"5557","NextNav","NN","222373120","2.3","United States"
"5558","Tide Water Oil","TIDEWATER.NS","222150087","12.75","India"
"5559","OraSure Technologies","OSUR","221713840","3.06","United States"
"5560","Maruzen","5982.T","221105870","13.65","Japan"
"5561","GTPL Hathway","GTPL.NS","220942790","1.96","India"
"5562","Turtle Beach Corp","HEAR","220583184","13.32","United States"
"5563","Molecular Partners","MOLN","220461280","6.82","Switzerland"
"5564","Conn's","CONN","220418672","9.27","United States"
"5565","Xeris Pharmaceuticals","XERS","220237888","1.63","United States"
"5566","Humanigen","HGEN","220023968","3.12","United States"
"5567","Consolidated Water","CWCO","219652640","14.37","Cayman Islands"
"5568","The Joint Corp.","JYNT","218582544","15.12","United States"
"5569","Innate Pharma","IPH.PA","217327815","2.72","France"
"5570","KORE","KORE","215759200","2.83","United States"
"5571","Zevia","ZVIA","215530192","3.34","United States"
"5572","Pear Therapeutics","PEAR","215439120","1.56","United States"
"5573","Kamada","KMDA","215158880","4.63","Israel"
"5574","Eneti","NETI","215100352","5.28","Monaco"
"5575","Genius Brands","GNUS","214967712","0.68","United States"
"5576","Dave Inc.","DAVE","214640544","0.57","United States"
"5577","Indorama Synthetics","INDORAMA.NS","214616549","0.82","India"
"5578","Vaxxinity","VAXX","212717360","1.69","United States"
"5579","Codorus Valley Bancorp","CVLY","212667632","22.32","United States"
"5580","Savara Pharmaceuticals","SVRA","212116256","1.86","United States"
"5581","Nerdy","NRDY","211696576","2.32","United States"
"5582","CECO Environmental","CECE","211243696","6.01","United States"
"5583","Citizens Inc","CIA","210873408","4.18","United States"
"5584","SeaSpine","SPNE","210865152","5.73","United States"
"5585","Addiko Bank","ZYE1.F","210714787","10.56","Austria"
"5586","Shankara Building","SHANKARA.NS","209258413","9.16","India"
"5587","Verastem Oncology","VSTM","208724304","1.12","United States"
"5588","Sonder Holdings","SOND","208660096","0.96","United States"
"5589","Century Casinos","CNTY","208101728","6.98","United States"
"5590","Timberland Bancorp","TSBK","207811872","25.02","United States"
"5591","Rigel Pharmaceuticals","RIGL","207322672","1.21","United States"
"5592","Wheels India","WHEELS.NS","206675501","8.52","India"
"5593","South Indian Bank","SOUTHBANK.NS","206620816","0.1","India"
"5594","Wendt India","WENDT.NS","206578598","103.22","India"
"5595","Western Copper and Gold","WRN","206064480","1.36","Canada"
"5596","Owlet","OWLT","205395168","1.81","United States"
"5597","Co-Diagnostics","CODX","205285712","6.04","United States"
"5598","Redwire","RDW","204060256","3.23","United States"
"5599","MSTC Limited","MSTCLTD.NS","203963204","2.89","India"
"5600","VBI Vaccines","VBIV","203738944","0.79","United States"
"5601","Sundaram Finance","SUNDARMHLD.NS","203505001","0.92","India"
"5602","EMX Royalty","EMX","202369488","1.85","Canada"
"5603","Air Busan","298690.KS","202316715","1.04","South Korea"
"5604","Nature's Sunshine Products","NATR","202148432","10.38","United States"
"5605","Hycroft Mining","HYMC","202012112","1.03","United States"
"5606","Community Financial Corporation","TCFC","201599696","35.65","United States"
"5607","Inseego","INSG","201258752","1.87","United States"
"5608","Federal-Mogul Goetze","FMGOETZE.NS","201236741","3.61","India"
"5609","Neuland Laboratories","NEULANDLAB.NS","200860256","15.66","India"
"5610","Bassett Furniture","BSET","200853744","21.72","United States"
"5611","Velodyne Lidar","VLDR","200117008","0.96","United States"
"5612","Omaxe","OMAXE.NS","199108246","1.08","India"
"5613","Mahanagar Telephone Nigam","MTNL.NS","199002379","0.32","India"
"5614","Shriram Pistons & Rings","SHRIPISTON.NS","198638155","8.88","India"
"5615","Semler Scientific","SMLR","198484144","29.22","United States"
"5616","Vadilal Industries","VADILALIND.NS","196546752","27.33","India"
"5617","Commercial Vehicle Group (CVG)","CVGI","196358160","5.96","United States"
"5618","Aehr Test Systems","AEHR","195997984","7.28","United States"
"5619","Hallador Energy Company","HNRG","195865200","6","United States"
"5620","Hooker Furniture","HOFT","195034128","16.25","United States"
"5621","Allakos","ALLK","195029488","3.54","United States"
"5622","Vroom","VRM","194663472","1.41","United States"
"5623","Iris Energy","IREN","194477328","3.54","Australia"
"5624","Accuray","ARAY","194420608","2.1","United States"
"5625","Kitex Garments","KITEX.NS","193834262","2.91","India"
"5626","Akoustis Technologies","AKTS","193631296","3.46","United States"
"5627","Indian Metals & Ferro Alloys","IMFA.NS","193300625","3.58","India"
"5628","Sandhar","SANDHAR.NS","193018017","3.19","India"
"5629","Avaya Holdings","AVYA","192703152","2.25","United States"
"5630","Cel-Sci","CVM","192342096","4.44","United States"
"5631","VA Tech Wabag","WABAG.NS","192262870","3.09","India"
"5632","Venator Materials","VNTR","192067344","1.78","United Kingdom"
"5633","RGC Resources","RGCO","192009760","19.61","United States"
"5634","Gatos Silver","GATO","191848240","2.78","United States"
"5635","GEOX","GEO.MI","190670464","0.75","Italy"
"5636","Full House Resorts","FLL","190618640","5.55","United States"
"5637","GTL Infrastructure","GTLINFRA.NS","190521202","0.02","India"
"5638","Territorial Bancorp","TBNK","190511280","20.62","United States"
"5639","Excel Industries","EXCELINDUS.NS","190382455","15.14","India"
"5640","NACL Industries","NACLIND.NS","189636761","0.96","India"
"5641","Dhampur Sugar Mills","DHAMPURSUG.NS","189541790","2.85","India"
"5642","Marinus Pharmaceuticals","MRNS","189357776","5.1","United States"
"5643","Blueknight Energy Partners","BKEP","189180176","4.52","United States"
"5644","Ashiana Housing","ASHIANA.NS","188463195","1.84","India"
"5645","Delta Apparel","DLA","188318544","27.1","United States"
"5646","VistaGen Therapeutics","VTGN","188063968","0.91","United States"
"5647","INEOS Styrolution","INEOSSTYRO.NS","187630451","10.66","India"
"5648","Kossan Rubber Industries","7153.KL","187311781","0.29","Malaysia"
"5649","Nelco","NELCO.NS","187089229","8.17","India"
"5650","Latch","LTCH","186817792","1.29","United States"
"5651","Luna Innovations","LUNA","186442032","5.75","United States"
"5652","AFC Energy","AFC.L","186323289","25.37","United Kingdom"
"5653","Marrone Bio Innovations","MBII","186025552","1.02","United States"
"5654","The Arena Group","AREN","185919696","10.44","United States"
"5655","Honda Siel Power Products","HONDAPOWER.NS","185854229","18.24","India"
"5656","PlayAGS","AGS","185536000","5","United States"
"5657","Lundin Energy","LUNE.ST","185521361","0.65","Sweden"
"5658","Westport Fuel Systems","WPRT","185444640","1.08","Canada"
"5659","Compugen","CGEN","185366720","2.04","Israel"
"5660","Milestone Pharmaceuticals","MIST","183729680","6.14","Canada"
"5661","NGL Energy Partners","NGL","183627872","1.41","United States"
"5662","Immersion Corporation","IMMR","183196832","5.45","United States"
"5663","Oxford Square Capital","OXSQ","182975488","3.68","United States"
"5664","Allot","ALLT","182936992","5","Israel"
"5665","Graphite Bio","GRPH","182605824","3.15","United States"
"5666","Evans Bancorp","EVBN","182276816","33","United States"
"5667","GoHealth","GOCO","182014016","0.56","United States"
"5668","Altisource Portfolio","ASPS","181604672","11.31","Luxembourg"
"5669","Mister Spex","MRX.F","180741647","5.31","Germany"
"5670","Overseas Shipholding Group","OSG","179951024","2.05","United States"
"5671","Lantronix","LTRX","177817792","5.11","United States"
"5672","Fiesta Restaurant Group","FRGI","177542400","6.85","United States"
"5673","Comscore","SCOR","176857184","1.95","United States"
"5674","Jagran Prakashan","JAGRAN.NS","176249058","0.67","India"
"5675","AG Mortgage Investment Trust","MITT","176080640","7.36","United States"
"5676","Bakkt Holdings","BKKT","176050448","2.34","United States"
"5677","Matinas BioPharma","MTNB","175660640","0.81","United States"
"5678","Immutep","IMMP","175445280","1.96","Australia"
"5679","Mangalore Chemicals and Fertilizers","MANGCHEFER.NS","175444159","1.48","India"
"5680","Confidence Petroleum","CONFIPET.NS","175391007","0.62","India"
"5681","Texmaco Rail & Engineering","TEXRAIL.NS","175290175","0.54","India"
"5682","Voxx International","VOXX","175246912","7.34","United States"
"5683","CleanSpark","CLSK","175070016","4.24","United States"
"5684","Méliuz","CASH3.SA","174607866","0.22","Brazil"
"5685","ESSA Bancorp","ESSA","174543616","16.64","United States"
"5686","Central Valley Community Bancorp","CVCY","174294576","14.95","United States"
"5687","MISTRAS Group","MG","174062960","5.84","United States"
"5688","Yellow Corporation","YELL","173614640","3.37","United States"
"5689","KCP Limited","KCP.NS","173578722","1.34","India"
"5690","KULR Technology","KULR","172842144","1.62","United States"
"5691","Rayonier Advanced Materials","RYAM","172392576","2.7","United States"
"5692","CSI Compressco","CCLP","172281088","1.22","United States"
"5693","Sangoma Technologies","SANG","171728800","8.01","Canada"
"5694","USD Partners","USDP","171570112","5.14","United States"
"5695","Lumax Industries","LUMAXIND.NS","171510669","18.31","India"
"5696","Precision BioSciences","DTIL","171504464","1.55","United States"
"5697","Cigniti Technologies","CIGNITITEC.NS","171448990","6.3","India"
"5698","Allied Tecnologia","ALLD3.SA","171438603","1.84","Brazil"
"5699","Tamil Nadu Newsprint and Papers Limited","TNPL.NS","170303127","2.46","India"
"5700","Jounce Therapeutics","JNCE","170008448","3.29","United States"
"5701","LCNB","LCNB","169999344","14.91","United States"
"5702","J.Jill","JILL","169565264","16.78","United States"
"5703","Escalade Sports","ESCA","168591088","12.41","United States"
"5704","Sachem Capital","SACH","168011312","4.59","United States"
"5705","Hinduja Ventures","NXTDIGITAL.NS","167717266","4.97","India"
"5706","Aemetis","AMTX","167712512","4.85","United States"
"5707","Power Mech Projects","POWERMECH.NS","167510465","11.39","India"
"5708","ORIC Pharmaceuticals","ORIC","167387552","4.24","United States"
"5709","MPS Limited","MPSLTD.NS","167200436","9.77","India"
"5710","Western New England Bancorp","WNEB","167195536","7.41","United States"
"5711","LSI Industries","LYTS","167126848","6.27","United States"
"5712","Huhtamaki India","HUHTAMAKI.NS","166704471","2.21","India"
"5713","Spire Global","SPIR","166335200","1.19","United States"
"5714","C&F Financial Corporation","CFFI","166188240","47","United States"
"5715","Accelya","ACCELYA.NS","165880653","11.11","India"
"5716","XL Fleet","XL","165559312","1.17","United States"
"5717","Force Motors","FORCEMOT.NS","165499222","12.56","India"
"5718","Nam Tai Property","NTP","165472480","4.22","China"
"5719","Silvercrest Asset Management Group","SAMG","165158384","16.73","United States"
"5720","Mainz Biomed","MYNZ","164820000","12","Germany"
"5721","XBiotech","XBIT","164372224","5.4","United States"
"5722","LATAM Airlines","LTMAQ","163851456","0.27","Chile"
"5723","Progenity","PROG","162924032","0.88","United States"
"5724","Hydrofarm","HYFM","162503024","3.34","United States"
"5725","Maiden Holdings","MHLD","162364656","1.87","Bermuda"
"5726","First Northwest Bancorp","FNWB","162158352","16.21","United States"
"5727","Adverum Biotechnologies","ADVM","162138592","1.56","United States"
"5728","Aterian","ATER","161353344","2.34","United States"
"5729","Electra Meccanica","SOLO","161310960","1.36","Canada"
"5730","Sesen Bio","SESN","161047232","0.81","United States"
"5731","Mynaric","MYNA","160643984","7.66","Germany"
"5732","Hurco Companies","HURC","160628576","24.46","United States"
"5733","Nuvectis Pharma","NVCT","158336608","12.45","United States"
"5734","Backblaze","BLZE","157696000","5.12","United States"
"5735","Ten Square Games","1HQ.F","155506984","21.3","Poland"
"5736","Camber Energy","CEI","155441600","0.38","United States"
"5737","CARE's Ratings","CARERATING.NS","154736764","5.22","India"
"5738","Geojit Financial Services","GEOJITFSL.NS","154700368","0.65","India"
"5739","AN2 Therapeutics","ANTX","154251456","7.95","United States"
"5740","Sasken Technologies","SASKEN.NS","154100017","10.24","India"
"5741","KVH Industries","KVHI","153987728","8.15","United States"
"5742","Peoples Bancorp of North Carolina","PEBK","153561216","27.15","United States"
"5743","Praxis Precision Medicines","PRAX","152464528","3.35","United States"
"5744","Potbelly Corporation","PBPB","151506592","5.25","United States"
"5745","Cormedix","CRMD","151407168","3.87","United States"
"5746","Momentus","MNTS","150442640","1.84","United States"
"5747","Party City","PRTY","149626944","1.33","United States"
"5748","Greenhill","GHL","149299728","8.24","United States"
"5749","Ovid Therapeutics","OVID","149284656","2.12","United States"
"5750","Quad","QUAD","147843872","2.66","United States"
"5751","Sonida Senior Living","SNDA","147414608","21.82","United States"
"5752","Martin Midstream Partners","MMLP","147166832","3.79","United States"
"5753","Shalby","SHALBY.NS","147063076","1.36","India"
"5754","Barnes & Noble Education","BNED","147029952","2.83","United States"
"5755","Middlefield Banc","MBCN","146704672","25.11","United States"
"5756","ServiceSource","SREV","146351856","1.46","United States"
"5757","Retractable Technologies","RVP","146235840","4.44","United States"
"5758","Pexip","PEXIP.OL","145842939","1.44","Norway"
"5759","Longeveron","LGVN","145725008","6.96","United States"
"5760","TeraWulf","WULF","145570528","1.39","United States"
"5761","Hanover Bancorp","HNVR","143654704","19.69","United States"
"5762","Daktronics","DAKT","143207488","3.18","United States"
"5763","Riverview Bancorp","RVSB","142952688","6.46","United States"
"5764","CalAmp","CAMP","142460560","3.94","United States"
"5765","SEACOR Marine","SMHI","142305136","5.34","United States"
"5766","Pieris Pharmaceuticals","PIRS","142274480","1.92","United States"
"5767","L.B. Foster","FSTR","142218176","13.06","United States"
"5768","Northern Dynasty Minerals","NAK","141927792","0.27","Canada"
"5769","Benessere Capital Acquisition","BENE","141760656","10.33","United States"
"5770","Spectrum Pharmaceuticals","SPPI","141026144","0.78","United States"
"5771","Kingfa Science & Technology","KINGFA.NS","140223431","11.41","India"
"5772","gumi","3903.T","140064678","4.8","Japan"
"5773","U.S. Xpress Enterprises","USX","139601824","2.73","United States"
"5774","Blue Apron Holdings","APRN","139537728","4.06","United States"
"5775","Gencor Industries","GENC","139248144","9.5","United States"
"5776","Smith Micro Software","SMSI","138737712","2.52","United States"
"5777","Yatra","YTRA","138495616","2.21","India"
"5778","Ohio Valley Banc Corp","OVBC","138381328","29","United States"
"5779","Himatsingka Seide","HIMATSEIDE.NS","138197699","1.4","India"
"5780","Velan","VLN.TO","137610397","6.38","Canada"
"5781","Nucleus Software Exports","NUCLEUS.NS","137237233","5.13","India"
"5782","Assertio Therapeutics","ASRT","137209168","3.02","United States"
"5783","High Tide","HITI","136898640","2.2","Canada"
"5784","IO Biotech","IOBT","136872672","4.75","Denmark"
"5785","KAP AG","IUR.F","136684066","17.6","Germany"
"5786","INNOVATE Corp.","VATE","136598032","1.74","United States"
"5787","Tactile Medical","TCMD","135498160","6.8","United States"
"5788","Bodal Chemicals","BODALCHEM.NS","135180076","1.1","India"
"5789","Avita Medical","RCEL","134510688","5.39","United States"
"5790","Atossa Therapeutics","ATOS","132955192","1.05","United States"
"5791","Sterling Tools","STERTOOLS.NS","132573839","3.68","India"
"5792","Summit Midstream","SMLP","132158000","13","United States"
"5793","Vera Bradley","VRA","131967576","4.2","United States"
"5794","Exterran","EXTN","131927400","3.96","United States"
"5795","Southern Petrochemical Industries Corp","SPIC.NS","131659326","0.65","India"
"5796","Paratek Pharmaceuticals","PRTK","131020792","2.41","United States"
"5797","BBX Capital Corporation","BBXIA","130719424","8.1","United States"
"5798","Citius Pharmaceuticals","CTXR","130201824","0.89","United States"
"5799","KLab","3656.T","130163120","3.43","Japan"
"5800","Metromile","MILE","130106992","1","United States"
"5801","Advent Technologies","ADN","129546624","2.51","United States"
"5802","Jakks Pacific","JAKK","129435432","13.5","United States"
"5803","Quantum","QMCO","128660232","1.42","United States"
"5804","Platinum Group Metals","PLG","128635000","1.3","Canada"
"5805","Bird Global","BRDS","128263456","0.46","United States"
"5806","Phunware","PHUN","128153808","1.31","United States"
"5807","Foseco India","FOSECOIND.NS","127696265","19.99","India"
"5808","Drive Shack","DS","127491296","1.38","United States"
"5809","Spok Holdings","SPOK","127024360","6.45","United States"
"5810","Sylogist","SYZ.TO","126565390","5.29","Canada"
"5811","Old Point Financial","OPOF","126510024","24.82","United States"
"5812","BG Staffing","BGSF","126300032","12.07","United States"
"5813","Supermax Corporation Berhad","7106.KL","126294203","0.19","Malaysia"
"5814","Sierra Metals","SMTS","125933632","0.75","Canada"
"5815","Drecom","3793.T","125725050","4.42","Japan"
"5816","Bit Digital","BTBT","125700112","1.53","United States"
"5817","GAN","GAN","125580808","2.97","United Kingdom"
"5818","PTC Financial Services","PFS.NS","125138042","0.19","India"
"5819","Matrix Service","MTRX","125111640","4.67","United States"
"5820","Genius Group","GNS","124841792","5.81","Singapore"
"5821","Srikalahasthi Pipes","SRIPIPES.NS","124125405","2.65","India"
"5822","Lument Finance Trust","LFT","123773720","2.37","United States"
"5823","Seanergy Maritime","SHIP","123715632","0.69","Greece"
"5824","MediciNova","MNOV","123596424","2.52","United States"
"5825","Coffee Day Enterprises","COFFEEDAY.NS","123284364","0.58","India"
"5826","BankFinancial","BFIN","123218984","9.35","United States"
"5827","Red Robin","RRGB","122660328","7.77","United States"
"5828","Express","EXPR","122525824","1.8","United States"
"5829","Quick Heal","QUICKHEAL.NS","122216987","2.1","India"
"5830","Immunic","IMUX","122161600","4","United States"
"5831","India Motor Parts and Accessories","IMPAL.NS","121326351","9.72","India"
"5832","RPG Life Sciences","RPGLIFE.NS","121304997","7.33","India"
"5833","Athira Pharma","ATHA","121187920","3.22","United States"
"5834","Oconee Federal Financial","OFED","121163904","21.6","United States"
"5835","Union Bankshares","UNB","121158312","26.95","United States"
"5836","Intevac","IVAC","121035936","4.83","United States"
"5837","Vigil Neuroscience","VIGL","120981912","4.28","United States"
"5838","Malvern Bancorp","MLVF","120705488","15.83","United States"
"5839","Iteris","ITI","120500064","2.84","United States"
"5840","Modiv","MDV","120485936","16.13","United States"
"5841","PDS Biotechnology","PDSB","119681560","4.21","United States"
"5842","Grupo Supervielle","SUPV","119670424","1.31","Argentina"
"5843","Actinium Pharmaceuticals","ATNM","119636040","5.03","United States"
"5844","Audacy","AUD","119580032","0.83","United States"
"5845","EMCORE Corporation","EMKR","119504384","3.19","United States"
"5846","Talaris Therapeutics","TALS","119410856","2.88","United States"
"5847","Prakash Industries","PRAKASH.NS","119375988","0.67","India"
"5848","Navkar Corp","NAVKARCORP.NS","119361860","0.79","India"
"5849","Sanghi Industries","SANGHIIND.NS","119331967","0.47","India"
"5850","Aptech","APTECHT.NS","119004938","2.88","India"
"5851","FinWise Bancorp","FINW","118680064","9.28","United States"
"5852","Oyster Point Pharma","OYST","118411696","4.44","United States"
"5853","Lakeland Industries","LAKE","117744328","15.35","United States"
"5854","Prudential Bancorp","PBIP","117655272","15.13","United States"
"5855","Endo International","ENDP","117604016","0.5","Ireland"
"5856","Arcimoto","FUV","116339400","3","United States"
"5857","India Nippon Electricals","INDNIPPON.NS","115713181","5.12","India"
"5858","Americas Gold and Silver Corp","USAS","115453568","0.62","Canada"
"5859","Rane Holdings","RANEHOLDIN.NS","115189602","8.07","India"
"5860","MDxHealth","MDXH","115105120","7.38","Belgium"
"5861","Apex Frozen Foods","APEX.NS","115023795","3.68","India"
"5862","Knights Group","KGH.L","114493704","132.3","United Kingdom"
"5863","Zion Oil & Gas","ZNOG","113972592","0.24","United States"
"5864","Pzena Investment Management","PZN","113670752","6.71","United States"
"5865","AquaBounty","AQB","113064416","1.59","United States"
"5866","Kopin Corporation","KOPN","113054592","1.23","United States"
"5867","Xunlei","XNET","113038376","1.68","China"
"5868","Wejo Group","WEJO","112671712","1.19","United Kingdom"
"5869","Igarashi Motors India","IGARASHI.NS","112638708","3.56","India"
"5870","NN, Inc.","NNBR","112578624","2.57","United States"
"5871","ContraFect","CFRX","112491520","2.86","United States"
"5872","Twin Disc","TWIN","112216152","8.22","United States"
"5873","SML Isuzu","SMLISUZU.NS","112212548","7.74","India"
"5874","Cellectis","CLLS","111907368","2.46","France"
"5875","Greenidge Generation Holdings","GREE","111272392","2.69","United States"
"5876","Asure Software","ASUR","110996504","5.53","United States"
"5877","ARC Document Solutions","ARC","110782976","2.56","United States"
"5878","Cadiz","CDZI","110679256","2.18","United States"
"5879","O2Micro","OIIM","108389272","3.72","Cayman Islands"
"5880","Lee Enterprises","LEE","108367656","18.19","United States"
"5881","Galectin Therapeutics","GALT","108087072","1.82","United States"
"5882","Red Cat Holdings","RCAT","107879912","2.01","United States"
"5883","OncoCyte","OCX","107846832","0.91","United States"
"5884","Provident Financial Holdings","PROV","107674960","14.78","United States"
"5885","Carrols Restaurant Group","TAST","107576512","2.02","United States"
"5886","Enzo Biochem","ENZ","107185104","2.2","United States"
"5887","Nok Air","NOK.BK","107172467","0.03","Thailand"
"5888","Surface Oncology","SURF","106925792","1.96","United States"
"5889","Reading International","RDI","106846248","3.61","United States"
"5890","GE Power India","GEPIL.NS","106747095","1.59","India"
"5891","StarTek","SRT","106582920","2.65","United States"
"5892","Superior Industries International","SUP","106070536","3.95","United States"
"5893","Leap Therapeutics","LPTX","105982200","1.2","United States"
"5894","CBAK Energy","CBAT","105879304","1.19","China"
"5895","Westwood Holdings Group","WHG","105852768","12.34","United States"
"5896","Hill International","HIL","105733976","1.85","United States"
"5897","Capricor Therapeutics","CAPR","105567032","4.34","United States"
"5898","Nusantara Pelabuhan Handal","PORT.JK","105158921","0.04","Indonesia"
"5899","Onion Global","OG","105118000","1","China"
"5900","Repco Home Finance","REPCOHOME.NS","104927334","1.68","India"
"5901","Mammoth Energy Services","TUSK","103805024","2.2","United States"
"5902","Forum Energy Technologies","FET","103492168","18.09","United States"
"5903","Dare Bioscience","DARE","103288488","1.22","United States"
"5904","Asensus Surgical","ASXC","103215224","0.44","United States"
"5905","Cheetah Mobile","CMCM","103211536","0.73","China"
"5906","Mangalam Cement","MANGLMCEM.NS","103147029","3.75","India"
"5907","Clearside Biomedical","CLSD","102255680","1.7","United States"
"5908","BitNile","NILE","101762432","0.31","United States"
"5909","Radio City","RADIOCITY.NS","101744335","0.29","India"
"5910","Ellington Residential Mortgage REIT","EARN","101734136","7.76","United States"
"5911","Pkp Cargo","PKP.WA","101706393","2.27","Poland"
"5912","Synchronoss","SNCR","101546488","1.15","United States"
"5913","BrainStorm Cell Therapeutics","BCLI","101427992","2.78","United States"
"5914","Xchanging Solution","XCHANGING.NS","100869444","0.9","India"
"5915","Pixelworks","PXLW","100706272","1.87","United States"
"5916","HEXO","HEXO","100593880","0.2","Canada"
"5917","Fonar Corporation","FONR","100163328","14.99","United States"
"5918","Enochian Biosciences","ENOB","100075496","1.89","United States"
"5919","Capacit'e Infraprojects","CAPACITE.NS","99945174","1.47","India"
"5920","Flexsteel Industries","FLXS","99742264","17.93","United States"
"5921","Cytosorbents","CTSO","98885968","2.27","United States"
"5922","Bliss GVS Pharma","BLISSGVS.NS","98705596","0.95","India"
"5923","Fortress Biotech","FBIO","98282896","0.92","United States"
"5924","Applied Blockchain","APLD","97923752","1.04","United States"
"5925","Xebec Adsorption","XBC.TO","97445935","0.63","Canada"
"5926","İşbir Holding","ISBIR.IS","97116679","3","Turkey"
"5927","Curis","CRIS","96685896","1.06","United States"
"5928","Ardelyx","ARDX","96490912","0.67","United States"
"5929","Fluent","FLNT","96416920","1.21","United States"
"5930","Trilogy Metals","TMQ","96262976","0.66","Canada"
"5931","Paysign","PAYS","95683496","1.84","United States"
"5932","Summit Therapeutics","SMMT","95178728","0.97","United Kingdom"
"5933","So-Young International","SY","95120872","0.9","China"
"5934","Great Elm Capital","GECC","94948480","12.49","United States"
"5935","Hour Loop","HOUR","94938888","2.71","United States"
"5936","Anup Engineering","ANUP.NS","94840894","9.68","India"
"5937","Quicklogic","QUIK","94454472","7.62","United States"
"5938","Seelos Therapeutics","SEEL","93434344","0.88","United States"
"5939","PEDEVCO","PED","93154784","1.09","United States"
"5940","Tanzanian Gold Corporation","TRX","93112688","0.34","Canada"
"5941","Accelerate Diagnostics","AXDX","92145872","1.16","United States"
"5942","Missfresh","MF","92084888","0.39","China"
"5943","3i Infotech","3IINFOLTD.NS","92023303","0.55","India"
"5944","Anixa Biosciences","ANIX","91565360","3.01","United States"
"5945","Falcon Minerals","FLMN","91525936","7.77","United States"
"5946","PAVmed","PAVM","90173448","1.03","United States"
"5947","DIRTT Environmental Solutions","DRTT","90160656","1.05","Canada"
"5948","AgroFresh","AGFS","88980528","1.69","United States"
"5949","Parag Milk Foods","PARAGMILK.NS","88408664","0.93","India"
"5950","aTyr Pharma","LIFE","88365808","3.15","United States"
"5951","Tiziana Life Sciences","TLSA","87965008","0.86","United Kingdom"
"5952","Advanced Emissions Solutions","ADES","87550352","4.58","United States"
"5953","Shift Technologies","SFT","87288480","1.03","United States"
"5954","Harte Hanks","HHS","86013600","12.25","United States"
"5955","Compleo Charging Solutions","C0M.F","85235515","16.81","Germany"
"5956","Farmer Brothers","FARM","85045744","4.61","United States"
"5957","Gaia","GAIA","84762816","4.08","United States"
"5958","UpHealth","UPH","84635456","0.59","United States"
"5959","Park City Group","PCYG","84427200","4.54","United States"
"5960","CytomX Therapeutics","CTMX","84363936","1.29","United States"
"5961","Rekor Systems","REKR","84338120","1.69","United States"
"5962","Liberty TripAdvisor Holdings","LTRPA","84153600","0.72","United States"
"5963","AirAsia","2630.TW","84014403","0.56","Malaysia"
"5964","Kuantum Papers","KUANTUM.NS","83798339","0.96","India"
"5965","Harpoon Therapeutics","HARP","83537352","2.53","United States"
"5966","Jay Bharat Maruti","JAYBARMARU.NS","83240644","1.92","India"
"5967","Spencer's Retail","SPENCERS.NS","81734124","0.91","India"
"5968","Ebixcash India","EBIXFOREX.NS","81507586","7.31","India"
"5969","Cortexyme","CRTX","80074016","2.22","United States"
"5970","Reliance Communications","RCOM.NS","79684997","0.03","India"
"5971","Smart Sand","SND","79218544","1.78","United States"
"5972","Aptose Biosciences","APTO","79156680","0.85","Canada"
"5973","Merrimack Pharmaceuticals","MACK","79120184","5.9","United States"
"5974","MICT","MICT","79022304","0.61","United States"
"5975","geechs","7060.T","79009331","7.37","Japan"
"5976","Xilio Therapeutics","XLO","78854480","2.87","United States"
"5977","GreenPower Motor Company","GP","78714760","3.4","Canada"
"5978","Orchard Therapeutics","ORTX","78690624","0.63","United Kingdom"
"5979","Wrap Technologies","WRAP","78658880","1.92","United States"
"5980","Rubius Therapeutics","RUBY","78592520","0.87","United States"
"5981","Nine Energy Service","NINE","77872176","2.38","United States"
"5982","Rico Auto Industries","RICOAUTO.NS","77589615","0.57","India"
"5983","Imperial Petroleum","IMPP","77071896","0.41","Greece"
"5984","PowerFleet","PWFL","76950512","2.13","United States"
"5985","XpresSpa","XSPA","76326392","0.8","United States"
"5986","Cooper Standard","CPS","76271160","4.47","United States"
"5987","Romeo Power","RMO","76145312","0.5","United States"
"5988","Mesa Air","MESA","75876568","2.1","United States"
"5989","Synlogic","SYBX","75870760","1.08","United States"
"5990","Akebia Therapeutics","AKBA","75817480","0.41","United States"
"5991","ACRES Commercial Realty","ACR","75170544","8.26","United States"
"5992","Sotherly Hotels","SOHO","74760736","2.02","United States"
"5993","Frequency Therapeutics","FREQ","74149960","2.12","United States"
"5994","Lifeway Foods","LWAY","73778824","4.78","United States"
"5995","Energous","WATT","73220216","0.95","United States"
"5996","Kokuyo Camlin","KOKUYOCMLN.NS","73170392","0.73","India"
"5997","Graham Corporation","GHM","73157944","6.9","United States"
"5998","Skipper Limited","SKIPPER.NS","73088512","0.71","India"
"5999","Elevate Credit","ELVT","73034776","2.33","United States"
"6000","Stabilis Solutions","SLNG","72571200","3.97","United States"
"6001","Flotek Industries","FTK","72481768","0.95","United States"
"6002","Solid Biosciences","SLDB","72278648","0.64","United States"
"6003","NCS Multistage","NCSM","71454264","29.67","United States"
"6004","Heritage Insurance","HRTG","71203496","2.69","United States"
"6005","TherapeuticsMD","TXMD","71011248","8.06","United States"
"6006","orion-group-holdings","ORN","70934152","2.32","United States"
"6007","Lipocine","LPCN","70816984","0.8","United States"
"6008","CI Games","CI7.F","70182886","0.35","Poland"
"6009","Biodesix","BDSX","69816600","1.75","United States"
"6010","Asian Granito India","ASIANTILES.NS","69583179","0.55","India"
"6011","Rane Brake Lining","RBL.NS","69513219","8.99","India"
"6012","Genprex","GNPX","69471840","1.45","United States"
"6013","Alkaline Water Company","WTER","69422576","0.57","United States"
"6014","Mogo","MOGO","69355568","0.9","Canada"
"6015","Vista Gold","VGZ","68658632","0.58","United States"
"6016","Nectar Lifesciences","NECLIFE.NS","68258739","0.3","India"
"6017","Palatin Technologies","PTN","67260816","0.29","United States"
"6018","S.S. Lazio","SSL.MI","67159932","0.99","Italy"
"6019","Minerva Surgical","UTRS","66607924","2.31","United States"
"6020","Orient Paper Mills","ORIENTPPR.NS","66051256","0.31","India"
"6021","Augmedix","AUGX","65839312","1.76","United States"
"6022","Charlotte's Web","CWEB.TO","65778060","0.45","United States"
"6023","Petropavlovsk","POG.L","65172200","1.43","United Kingdom"
"6024","Avino Silver & Gold Mines","ASM","64551300","0.55","Canada"
"6025","Tabula Rasa HealthCare","TRHC","64364756","2.49","United States"
"6026","Lumos Pharma","LUMO","64275684","7.68","United States"
"6027","Koss","KOSS","64034600","7","United States"
"6028","ReWalk Robotics","RWLK","63760096","1.02","Israel"
"6029","Conformis","CFMS","63323664","0.34","United States"
"6030","Journey Medical","DERM","62928076","3.61","United States"
"6031","U.S. Well Services","USWS","62881448","0.82","United States"
"6032","Orion Energy Systems","OESX","62322000","2","United States"
"6033","Titan Medical","TMDI","62273680","0.56","Canada"
"6034","Natural Health Trends","NHTC","62252624","5.45","United States"
"6035","LMP Automotive Holdings","LMPX","62071072","5.69","United States"
"6036","Phoenix Motor","PEV","61936000","3.16","United States"
"6037","InflaRx","IFRX","61443280","1.39","Germany"
"6038","Pulse Biosciences","PLSE","61432604","1.66","United States"
"6039","SCYNEXIS","SCYX","61249460","1.88","United States"
"6040","BeyondSpring","BYSI","61118376","1.57","United States"
"6041","Athersys","ATHX","60810392","0.23","United States"
"6042","Manhattan Bridge Capital","LOAN","60808020","5.29","United States"
"6043","Iterum Therapeutics","ITRM","59956428","0.33","Ireland"
"6044","Inuvo","INUV","59938440","0.5","United States"
"6045","Waitr Holdings","WTRH","59825436","0.38","United States"
"6046","Allied Esports","AESE","59445956","1.52","United States"
"6047","Trevena","TRVN","59421680","0.36","United States"
"6048","IZEA Worldwide","IZEA","59325696","0.95","United States"
"6049","Nautilus","NLS","59159276","1.88","United States"
"6050","United Insurance Holdings","UIHC","58796484","1.36","United States"
"6051","FreightCar America","RAIL","58700316","3.55","United States"
"6052","N.B.I. Industrial Finance","NBIFIN.NS","58589791","23.85","India"
"6053","Starbreeze","STAR-B.ST","58501815","0.08","Sweden"
"6054","ProQR","PRQR","57803296","0.81","Netherlands"
"6055","Vapotherm","VAPO","57788892","2.18","United States"
"6056","Unitech Group","UNITECH.NS","57585715","0.02","India"
"6057","Athenex","ATNX","56641896","0.51","United States"
"6058","Salem Media Group","SALM","56606780","2.08","United States"
"6059","iBio","IBIO","56265012","0.26","United States"
"6060","Oncolytics Biotech","ONCY","56061152","0.97","Canada"
"6061","eMagin","EMAN","55800040","0.76","United States"
"6062","Geospace Technologies","GEOS","55722180","4.28","United States"
"6063","Luby's","LUB","55327916","1.78","United States"
"6064","Rafael Holdings","RFL","55267620","2.3","United States"
"6065","AgEagle Aerial Systems","UAVS","55124804","0.67","United States"
"6066","Bionomics","BNOX","54810740","7.29","Australia"
"6067","Verb Technology","VERB","54778144","0.54","United States"
"6068","FingerMotion","FNGR","54327172","1.27","United States"
"6069","IMV","IMV","54176484","0.6","Canada"
"6070","Regis Corporation","RGS","54151072","1.19","United States"
"6071","Aptorum Group","APM","53554952","1.5","Hong Kong"
"6072","Golden Minerals","AUMN","53374956","0.33","United States"
"6073","Sidus Space","SIDU","53318468","3.16","United States"
"6074","Sientra","SIEN","53031024","0.85","United States"
"6075","Indonesia Energy","INDO","52995164","6.93","Indonesia"
"6076","NantHealth","NH","52956564","0.46","United States"
"6077","Redhill Biopharma","RDHL","52780760","0.99","Israel"
"6078","Gulf Island Fabrication","GIFI","52295120","3.32","United States"
"6079","Culp","CULP","52095544","4.26","United States"
"6080","Protalix BioTherapeutics","PLX","52004948","1.11","Israel"
"6081","Syros Pharmaceuticals","SYRS","51657280","0.82","United States"
"6082","CarLotz","LOTZ","51444236","0.45","United States"
"6083","Corvus Pharmaceuticals","CRVS","51208852","1.1","United States"
"6084","Sunworks","SUNW","51069584","1.55","United States"
"6085","vTv Therapeutics","VTVT","51037144","0.66","United States"
"6086","Westwater Resources","WWR","50969200","1.08","United States"
"6087","Achieve Life Sciences","ACHV","50829764","5.25","Canada"
"6088","BIT Mining (500.com)","BTCM","50741056","0.7","China"
"6089","Sellas Life Sciences","SLS","50517576","2.46","United States"
"6090","Future Retail","FRETAIL.NS","50130647","0.09","India"
"6091","Balaji Telefilms","BALAJITELE.NS","50113985","0.49","India"
"6092","Trinity Biotech","TRIB","49928576","1.31","Ireland"
"6093","Kirkland's","KIRK","49383088","3.88","United States"
"6094","Voyager Digital","VOYG.TO","49130968","0.26","United States"
"6095","Zynerba Pharmaceuticals","ZYNE","48827520","1.12","United States"
"6096","Tyme Technologies","TYME","48493492","0.28","United States"
"6097","Cryo-Cell","CCEL","48308772","5.71","United States"
"6098","Hepion Pharmaceuticals","HEPA","48138992","0.63","United States"
"6099","SigmaTron International","SGMA","47932652","7.96","United States"
"6100","Hindustan Media Ventures","HMVL.NS","47858556","0.65","India"
"6101","Logan Ridge Finance","LRFC","47850384","17.65","United States"
"6102","Field Trip Health","FTRP","47644260","0.82","Canada"
"6103","Horizon Global","HZN","47490060","1.72","United States"
"6104","Society Pass","SOPA","47338916","1.99","Singapore"
"6105","Boxlight","BOXL","47219676","0.72","United States"
"6106","Tonix Pharmaceuticals","TNXP","47217912","1.49","United States"
"6107","Agrify","AGFY","47066776","1.77","United States"
"6108","Aptinyx","APTX","47048868","0.69","United States"
"6109","Sonendo","SONX","47040592","1.78","United States"
"6110","PhaseBio Pharmaceuticals","PHAS","46986428","0.97","United States"
"6111","ATARI","ATA.PA","46838616","0.15","France"
"6112","NewAge","NBEV","46833344","0.32","United States"
"6113","KLX Energy Services","KLXE","46816048","4.01","United States"
"6114","SPI Energy","SPI","46691704","1.7","United States"
"6115","Navios Maritime Holdings","NM","46493096","2.04","Monaco"
"6116","Triterras","TRIRF","45914460","0.6","Singapore"
"6117","BioLargo","BLGO","45838360","0.17","United States"
"6118","Great Panther Mining","GPL","45640296","0.1","Canada"
"6119","NuCana","NCNA","44888560","0.86","United Kingdom"
"6120","Remark Holdings","MARK","44818340","0.43","United States"
"6121","AVROBIO","AVRO","44570428","1.02","United States"
"6122","Hallmark Financial Services","HALL","43838864","2.41","United States"
"6123","Exela Technologies","XELA","43622048","0.1","United States"
"6124","Okyo Pharma","OKYO","43322100","1.99","United Kingdom"
"6125","Comstock Mining","LODE","43313048","0.59","United States"
"6126","Foresight Autonomous Holdings","FRSX","43259576","0.67","Israel"
"6127","ATA Creativity Global","AACG","42885620","1.36","China"
"6128","Isoray","ISR","42754040","0.3","United States"
"6129","Avalon GloboCare","AVCO","42665476","0.48","United States"
"6130","The9","NCTY","42662060","1.81","China"
"6131","enish","3667.T","42617665","2.75","Japan"
"6132","Kaival Brands Innovations","KAVL","42386860","1.36","United States"
"6133","Cyngn","CYN","41972484","1.25","United States"
"6134","Intellicheck","IDN","41887184","2.22","United States"
"6135","Aquestive Therapeutics","AQST","41670124","0.85","United States"
"6136","AcelRx Pharmaceuticals","ACRX","41589692","0.28","United States"
"6137","Sphere 3D","ANY","41580820","0.64","Canada"
"6138","Unity Biotechnology","UBX","41466752","0.6","United States"
"6139","Document Security Systems","DSS","41413152","0.35","United States"
"6140","Oragenics","OGEN","41366784","0.36","United States"
"6141","Cocrystal Pharma","COCP","40936980","0.42","United States"
"6142","Evofem Biosciences","EVFM","40699196","1.15","United States"
"6143","Quotient","QTNT","40512256","0.3","Switzerland"
"6144","electroCore","ECOR","39354808","0.56","United States"
"6145","MEP Infrastructure","MEP.NS","39338861","0.21","India"
"6146","NRx Pharmaceuticals","NRXP","39331696","0.59","United States"
"6147","Real Good Food plc","RGF","39055340","6.33","United Kingdom"
"6148","Acasti Pharma","ACST","38884824","0.88","Canada"
"6149","Ampio Pharmaceuticals","AMPE","38468792","0.17","United States"
"6150","Trinity Place Holdings","TPHS","38324416","1.04","United States"
"6151","Biomerica","BMRA","38298664","2.98","United States"
"6152","Digital Ally","DGLY","38273920","0.79","United States"
"6153","Quanergy Systems","QNGY","38004992","0.41","United States"
"6154","AIM ImmunoTech","AIM","37953748","0.79","United States"
"6155","Kingstone Companies","KINS","37787620","3.55","United States"
"6156","Stronghold Digital Mining","SDIG","37665612","1.88","United States"
"6157","Beasley Broadcast Group","BBGI","37624064","1.28","United States"
"6158","Houston American Energy","HUSA","37529124","3.78","United States"
"6159","Capstone Green Energy","CGRN","37400964","2.45","United States"
"6160","Orphazyme","ORPH","37272452","0.87","Denmark"
"6161","SOS Limited","SOS","37080700","6.51","China"
"6162","WonderPlanet","4199.T","37048301","17.22","Japan"
"6163","Corbus Pharmaceuticals","CRBP","37038200","0.3","United States"
"6164","Brooklyn ImmunoTherapeutics","BTX","36894844","0.64","United States"
"6165","Super League Gaming","SLGG","36684164","0.99","United States"
"6166","Dolphin Entertainment","DLPN","36586180","4.02","United States"
"6167","Nymox Pharmaceutical","NYMX","36211308","0.4","Bahamas"
"6168","DAVIDsTEA","DTEA","36208084","1.37","Canada"
"6169","Polar Power","POLA","35998784","2.82","United States"
"6170","Silver One Resources","SVE.V","35855231","0.17","Canada"
"6171","Psychemedics","PMD","35557584","6.32","United States"
"6172","LightPath Technologies","LPTH","35434012","1.31","United States"
"6173","CorEnergy Infrastructure Trust","CORR","35356344","2.26","United States"
"6174","Biofrontera","BFRI","35066196","1.85","United States"
"6175","GlycoMimetics","GLYC","34846184","0.67","United States"
"6176","180 Life Sciences","ATNF","34830092","1.02","United States"
"6177","Microbot Medical","MBOT","34687676","4.88","United States"
"6178","Solitario Zinc","XPL","34651364","0.54","United States"
"6179","Adial Pharmaceuticals","ADIL","34632900","1.35","United States"
"6180","X4 Pharmaceuticals","XFOR","34368316","1.12","United States"
"6181","Almaden Minerals","AAU","33958580","0.23","Canada"
"6182","Ocean Power Technologies","OPTT","33944548","0.61","United States"
"6183","Zovio","ZVO","33891424","0.99","United States"
"6184","Eargo","EAR","33450874","0.85","United States"
"6185","IMTE","IMTE","32604794","2.21","Australia"
"6186","Cyclerion Therapeutics","CYCN","32586300","0.75","United States"
"6187","Actelis Networks","ASNS","32454790","1.87","United States"
"6188","Broadwind","BWEN","32365992","1.61","United States"
"6189","Regulus Therapeutics","RGLS","32115820","2.2","United States"
"6190","Akanda","AKAN","32041358","1.04","United Kingdom"
"6191","U.S. Gold Corp","USAU","31859648","3.82","United States"
"6192","Team Inc","TISI","31784932","0.74","United States"
"6193","ZK International Group","ZKIN","31304686","1.03","China"
"6194","BioSig Technologies","BSGM","31206772","0.71","United States"
"6195","Abeona Therapeutics","ABEO","31065124","5.29","United States"
"6196","Context Therapeutics","CNTX","30971042","1.94","United States"
"6197","Cielo Waste Solutions","CMC.V","30523526","0.05","Canada"
"6198","Pioneer Power Solutions","PPSI","29994518","3.11","United States"
"6199","Appirits","4174.T","29801072","7.48","Japan"
"6200","Nexstim","NXTMH.HE","29550441","4.42","Finland"
"6201","Soligenix","SNGX","29274136","0.68","United States"
"6202","VivoPower","VVPR","28553166","1.38","United Kingdom"
"6203","India Globalization Capital","IGC","28459420","0.55","United States"
"6204","OpGen","OPGN","28431070","0.61","United States"
"6205","VYNE Therapeutics","VYNE","28407848","0.49","United States"
"6206","Aeterna Zentaris","AEZS","28261696","0.23","United States"
"6207","Onconova Therapeutics","ONTX","28240404","1.35","United States"
"6208","Fresh Vine Wine","VINE","28116256","2.24","United States"
"6209","Organovo","ONVO","27881280","3.15","United States"
"6210","Vislink Technologies","VISL","27747098","0.61","United States"
"6211","FGI Industries","FGI","27715000","2.3","United States"
"6212","Biolase","BIOL","27606852","4.47","United States"
"6213","Inpixon","INPX","27491422","0.18","United States"
"6214","RealNetworks","RNWK","27436694","0.58","United States"
"6215","PREIT","PEI","27348068","4.27","United States"
"6216","T2 Biosystems","TTOO","27304272","0.16","United States"
"6217","Lannett Company","LCI","27110096","0.63","United States"
"6218","SeaChange","SEAC","27105816","0.55","United States"
"6219","Marin Software","MRIN","27086232","1.74","United States"
"6220","American Virtual Cloud","AVCT","26845272","0.29","United States"
"6221","Precipio","PRPO","26798536","1.18","United States"
"6222","Agile Therapeutics","AGRX","26140150","0.67","United States"
"6223","Summer Infant","SUMR","25984368","11.99","United States"
"6224","Jaguar Health","JAGX","25975934","0.33","United States"
"6225","Rand Merchant Investment","RMI.JO","25707222","1.67","South Africa"
"6226","Tempest Therapeutics","TPST","25497810","2.47","United States"
"6227","Srei Infrastructure Finance","SREINFRA.NS","25373245","0.05","India"
"6228","Can Fite Biopharma","CANF","25285376","0.93","Israel"
"6229","Aileron Therapeutics","ALRN","25040066","0.28","United States"
"6230","Zee Learn","ZEELEARN.NS","24894727","0.08","India"
"6231","Chembio Diagnostics","CEMI","24818224","0.82","United States"
"6232","Pick n Pay Stores","PIK.JO","24672680","3.37","South Africa"
"6233","Alony Hetz","ALHE.TA","24632518","13.96","Israel"
"6234","Aytu BioScience","AYTU","24302186","0.63","United States"
"6235","Spero Therapeutics","SPRO","24291194","0.74","United States"
"6236","NanoViricides","NNVC","24266868","2.1","United States"
"6237","Wheeler Real Estate Investment Trust","WHLR","24016032","2.47","United States"
"6238","cbdMD","YCBD","23958456","0.4","United States"
"6239","Stryve Foods","SNAX","23886236","0.95","United States"
"6240","Farmmi","FAMI","23868152","1.07","China"
"6241","Astrotech","ASTC","23793930","0.47","United States"
"6242","Ontrak","OTRK","23749982","1.14","United States"
"6243","AgeX Therapeutics","AGE","23725820","0.63","United States"
"6244","Inspira Technologies","IINN","23431100","2.2","Israel"
"6245","Greenlane","GNLN","23240646","0.21","United States"
"6246","Enjoy Technology","ENJY","23175936","0.19","United States"
"6247","Kala Pharmaceuticals","KALA","23142968","0.32","United States"
"6248","BiondVax","BVXV","22910226","1.23","Israel"
"6249","Cryptyde","TYDE","22742160","1.12","United States"
"6250","Ekso Bionics","EKSO","22477876","1.75","United States"
"6251","Austin Gold","AUST","22031188","1.66","United States"
"6252","Rave Restaurant Group","RAVE","21987584","1.22","United States"
"6253","Arcadia Biosciences","RKDA","21967012","0.99","United States"
"6254","Air Industries Group","AIRI","21928300","0.68","United States"
"6255","Carver Bancorp","CARV","21876450","5.75","United States"
"6256","iSpecimen","ISPC","21780242","2.46","United States"
"6257","Aprea Therapeutics","APRE","21637730","0.92","United States"
"6258","G Medical Innovations","GMVD","21487122","0.88","Israel"
"6259","Ensysce Biosciences","ENSC","21472748","0.62","United States"
"6260","Allena Pharmaceuticals","ALNA","21297232","0.2","United States"
"6261","Genetic Technologies","GENE","20622466","1.34","Australia"
"6262","Shikun & Binui","SKBN.TA","19892179","4.32","Israel"
"6263","Cimbeton","CMBTN.IS","19830623","11.2","Turkey"
"6264","SG Blocks","SGBX","19811384","1.65","United States"
"6265","Marpai","MRAI","19487712","0.96","United States"
"6266","FC Porto","FCP.LS","19230685","0.85","Portugal"
"6267","Energix Renewable Energies","ENRG.TA","19195410","3.69","Israel"
"6268","Tivic Health Systems","TIVC","18954316","1.97","United States"
"6269","NuZee","NUZE","18877268","0.97","United States"
"6270","Blackboxstocks","BLBX","18855550","1.43","United States"
"6271","Titan Pharmaceuticals","TTNP","18432792","1.26","United States"
"6272","Blue Hat","BHAT","18370942","2.97","China"
"6273","Guardforce AI","GFAI","18165426","0.44","Singapore"
"6274","Future Supply Chain Solutions","FSC.NS","18113131","0.41","India"
"6275","Advanced Human Imaging","AHI","17784470","0.63","Australia"
"6276","Esports Entertainment","GMBL","17772816","0.43","Malta"
"6277","HTG Molecular Diagnostics","HTGM","17663658","1.6","United States"
"6278","Cingulate","CING","17642664","1.56","United States"
"6279","Top Ships","TOPS","17642028","0.37","Greece"
"6280","Biocept","BIOC","17599816","1.04","United States"
"6281","HyreCar","HYRE","17488682","0.8","United States"
"6282","Petros Pharmaceuticals","PTPI","17375148","0.84","United States"
"6283","Neovasc","NVCN","17242438","6.27","Canada"
"6284","Winc","WBEV","16934294","1.28","United States"
"6285","Stealth BioTherapeutics","MITO","16644048","0.23","Cayman Islands"
"6286","Minerva Neurosciences","NERV","16394948","3.07","United States"
"6287","Aethlon Medical","AEMD","15988502","1.01","United States"
"6288","Galmed Pharmaceuticals","GLMD","15853360","0.63","Israel"
"6289","Kaspien","KSPN","15509734","6.2","United States"
"6290","Pulmatrix","PULM","15479367","4.57","United States"
"6291","Diffusion Pharmaceuticals","DFFN","15309811","7.51","United States"
"6292","Expion360","XPON","15278760","2.25","United States"
"6293","Celsion Corporation","CLSN","14907353","2.1","United States"
"6294","BIO-key International","BKYI","14392763","1.71","United States"
"6295","OLB Group","OLB","14036763","0.95","United States"
"6296","Calithera Biosciences","CALA","13710445","2.82","United States"
"6297","Rail Vision","RVSN","13670646","0.86","Israel"
"6298","Impac Mortgage Holdings","IMH","13524084","0.63","United States"
"6299","Heart Test Laboratories","HSCS","13350268","1.66","United States"
"6300","Nabriva Therapeutics","NBRV","12950663","0.2","Ireland"
"6301","Versus Systems","VS","12229940","0.59","Canada"
"6302","Rockwell Medical","RMTI","11918404","1.27","United States"
"6303","SINTX Technologies","SINT","11861088","0.48","United States"
"6304","Hillstream BioPharma","HILS","11838260","1.02","United States"
"6305","Kidpik","PIK","11773136","1.53","United States"
"6306","Yield10 Bioscience","YTEN","11763000","2.4","United States"
"6307","Jump Networks","JUMPNET.NS","11669324","0.12","India"
"6308","Bellerophon Therapeutics","BLPH","11584358","1.21","United States"
"6309","Sonim Technologies","SONM","11370066","0.59","United States"
"6310","Ra Medical Systems","RMED","11300324","0.35","United States"
"6311","Calyxt","CLXT","11295081","0.26","United States"
"6312","Evoke Pharma","EVOK","11065528","3.31","United States"
"6313","Trillium Gold Mines","TGM.V","10834748","0.18","Canada"
"6314","Acorda Therapeutics","ACOR","10796338","0.44","United States"
"6315","Edible Garden","EDBL","10732126","1.24","United States"
"6316","SaverOne 2014","SVRE","10666321","2.35","Israel"
"6317","Phio Pharmaceuticals","PHIO","10244025","0.75","United States"
"6318","ION Geophysical","IO","10205100","0.35","United States"
"6319","Akerna","KERN","10178391","0.15","United States"
"6320","SOBR Safe","SOBR","10156100","1","United States"
"6321","Eastside Distilling","EAST","10090156","0.66","United States"
"6322","Neptune Wellness Solutions","NEPT","9582251","1.38","Canada"
"6323","Benitec Biopharma","BNTC","9560877","1.17","United States"
"6324","ShiftPixy","PIXY","9543063","0.28","United States"
"6325","AppTech Payments","APCX","9441742","0.58","United States"
"6326","Pintec Technology","PT","8851519","1.02","China"
"6327","Grom Social Enterprises","GROM","8498461","0.45","United States"
"6328","Avinger","AVGR","8352907","1.47","United States"
"6329","Liquid Media Group","YVR","8299771","0.43","Canada"
"6330","PainReform","PRFX","8176037","0.78","Israel"
"6331","Altamira Therapeutics","CYTO","7937793","0.51","Bermuda"
"6332","JanOne","JAN","7916748","2.8","United States"
"6333","Connexa Sports Technologies","CNXA","7863532","0.94","United States"
"6334","Cemtrex","CETX","7776563","0.3","United States"
"6335","Advaxis","ADXS","7737040","4.25","United States"
"6336","Armstrong Flooring","AFI","7648996","0.35","United States"
"6337","Allied Healthcare Products","AHPI","7283371","1.81","United States"
"6338","Energy Focus","EFOI","7167840","0.92","United States"
"6339","Viveve Medical","VIVE","7129135","0.67","United States"
"6340","PolarityTE","PTE","7098269","1.59","United States"
"6341","Staffing 360 Solutions","STAF","6665355","3.78","United States"
"6342","FedNat Holding Company","FNHC","6550429","0.37","United States"
"6343","VIP Gloves","VIP.AX","6382324","0.01","Malaysia"
"6344","Wolverine Energy and Infrastructure","WEII.V","6356629","0.06","Canada"
"6345","Performance Shipping","PSHG","6226605","0.6","Greece"
"6346","Applied DNA Sciences","APDN","6175740","0.75","United States"
"6347","Baudax Bio","BXRX","5651386","0.88","United States"
"6348","Helius Medical Technologies","HSDT","5392663","1.42","United States"
"6349","Quoin Pharmaceuticals","QNRX","5216989","0.52","United States"
"6350","ToughBuilt Industries","TBLT","5004087","2.35","United States"
"6351","B Communications","BCOM.TA","4863381","4.4","Israel"
"6352","Afristrat Investment","ATI.JO","4067586","0.01","South Africa"
"6353","Direct Digital Holdings","DRCT","3961440","1.41","United States"
"6354","Youngevity International","YGYI","3915083","0.12","United States"
"6355","Zosano Pharma","ZSAN","2733500","0.56","United States"
"6356","Mallinckrodt Pharmaceuticals","MNKKQ","1695660","0.02","United Kingdom"
"6357","Genocea Biosciences","GNCA","881752","0.02","United States"
"6358","iFresh","IFMK","725468","0.02","United States"
"6359","Trulite","TRUL","212013","0","United States"
"6360","Pareteum Corporation","TEUM","142697","0","United States"
"6361","Intensity Therapeutics","INTS","0","0","United States"
"6362","Justworks","JW","0","0","United States"
"6363","Verdant Earth Technologies","VDNT","0","0","Australia"
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/application/CurrentApplication.kt
================================================
package com.istudio.app.application
import android.app.Application
import dagger.hilt.android.HiltAndroidApp
@HiltAndroidApp
class CurrentApplication : Application() { }
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/data/mock/FlowMockApi.kt
================================================
package com.istudio.app.data.mock
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.GET
interface FlowMockApi {
@GET("current-stock-prices")
suspend fun getCurrentStockPrices(): List
}
fun createFlowMockApi(interceptor: MockNetworkInterceptor): FlowMockApi {
val okHttpClient = OkHttpClient.Builder()
.addInterceptor(interceptor)
.build()
val retrofit = Retrofit.Builder()
.baseUrl("http://localhost")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()
return retrofit.create(FlowMockApi::class.java)
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/data/mock/FlowMockData.kt
================================================
package com.istudio.app.data.mock
import android.content.Context
import androidx.compose.runtime.Immutable
import com.opencsv.CSVReader
import java.io.InputStreamReader
import java.util.UUID
import kotlin.random.Random
@Immutable
data class Stock(
val id : String = UUID.randomUUID().toString(),
val rank: Int,
val name: String,
val symbol: String,
val marketCap: Float,
val country: String,
val currentPrice: Float,
val currency: Currency = Currency.DOLLAR,
val priceTrend: PriceTrend = PriceTrend.UNKNOWN
)
enum class Currency {
DOLLAR, EURO
}
enum class PriceTrend {
UP, DOWN, NEUTRAL, UNKNOWN
}
var initialStockData: List? = null
fun readAndParseStockData(context: Context) {
if (initialStockData == null) {
val stream = context.assets.open("stockdata.csv")
val csvReader = CSVReader(InputStreamReader(stream))
val stockData = csvReader
.readAll()
.drop(1)
.mapNotNull { line ->
val id = UUID.randomUUID().toString()
val rank = line[0].toInt()
val name = line[1]
val symbol = line[2]
val marketCap = line[3].toFloat()
val priceUsd = line[4].toFloat()
val country = line[5]
Stock(id,rank, name, symbol, marketCap, country, priceUsd)
}.also {
csvReader.close()
}
initialStockData = stockData
}
}
fun fakeCurrentStockPrices(context: Context): List {
readAndParseStockData(context)
return initialStockData!!.map { stock ->
val currentPrice = stock.currentPrice
if (stock.currentPrice == 0f) {
return@map stock
}
val randomRangeInPercent = 0.03
val randomLowerBound = (currentPrice * (1 - randomRangeInPercent))
val randomUpperBound = (currentPrice * (1 + randomRangeInPercent))
val randomPrice = Random.nextDouble(randomLowerBound, randomUpperBound).toFloat()
stock.copy(currentPrice = randomPrice)
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/data/mock/MockNetworkInterceptor.kt
================================================
package com.istudio.app.data.mock
import okhttp3.*
import kotlin.random.Random
class MockNetworkInterceptor : Interceptor {
private val mockResponses = mutableListOf()
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()
val mockResponse = findMockResponseInList(request)
?: throw RuntimeException("No mock response found for url ${request.url()}. Please define a mock response in your MockApi!")
removeResponseIfItShouldNotBePersisted(mockResponse)
simulateNetworkDelay(mockResponse)
return if (mockResponse.status < 400) {
if (mockResponse.errorFrequencyInPercent == 0) {
createSuccessResponse(mockResponse, request)
} else {
maybeReturnErrorResponse(mockResponse, request)
}
} else {
createErrorResponse(request, mockResponse.body())
}
}
private fun maybeReturnErrorResponse(
mockResponse: MockResponse,
request: Request
) = when (Random.nextInt(0, 101)) {
in 0..mockResponse.errorFrequencyInPercent -> createErrorResponse(request)
else -> createSuccessResponse(mockResponse, request)
}
private fun findMockResponseInList(request: Request): MockResponse? {
return mockResponses.find { mockResponse ->
mockResponse.path.contains(request.url().encodedPath())
}
}
private fun removeResponseIfItShouldNotBePersisted(mockResponse: MockResponse) {
if (!mockResponse.persist) {
mockResponses.remove(mockResponse)
}
}
private fun simulateNetworkDelay(mockResponse: MockResponse) {
Thread.sleep(mockResponse.delayInMs)
}
private fun createErrorResponse(request: Request, errorBody: String = "Error"): Response {
return Response.Builder()
.code(500)
.request(request)
.protocol(Protocol.HTTP_1_1)
.message("Internal Server Error: $errorBody")
.body(
ResponseBody.create(
MediaType.get("text/plain"),
errorBody
)
)
.build()
}
private fun createSuccessResponse(
mockResponse: MockResponse,
request: Request
): Response {
return Response.Builder()
.code(mockResponse.status)
.request(request)
.protocol(Protocol.HTTP_1_1)
.message("OK")
.body(
ResponseBody.create(
MediaType.get("application/json"),
mockResponse.body.invoke()
)
)
.build()
}
fun mock(
path: String,
body: () -> String,
status: Int,
delayInMs: Long = 250,
persist: Boolean = true,
errorFrequencyInPercent:Int = 0
) = apply {
val mockResponse =
MockResponse(
path,
body,
status,
delayInMs,
persist,
errorFrequencyInPercent
)
mockResponses.add(mockResponse)
}
companion object {
const val INTERNAL_SERVER_ERROR_HTTP_CODE = 500
}
}
data class MockResponse(
val path: String,
val body: () -> String,
val status: Int,
val delayInMs: Long,
val persist: Boolean,
val errorFrequencyInPercent: Int
)
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/main/MainActivity.kt
================================================
package com.istudio.app.main
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.ui.Modifier
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import com.istudio.app.modules.module_demos.basic_fundamentals.ui.KotlinBasicsDemo
import com.istudio.app.modules.module_demos.channels.ChannelsDemo
import com.istudio.app.modules.module_demos.coroutines.CoroutinesDemo
import com.istudio.app.modules.module_demos.coroutines.compare_join_and_async.CompareJoinAsyncDemo
import com.istudio.app.modules.module_demos.coroutines.coroutine_cancellation.CoroutinesCancellationSelection
import com.istudio.app.modules.module_demos.coroutines.coroutine_cancellation.ensure_active_demo.EnsureActiveDemo
import com.istudio.app.modules.module_demos.coroutines.coroutine_cancellation.is_active_demo.IsActiveDemo
import com.istudio.app.modules.module_demos.coroutines.coroutine_cancellation.non_cancellable_job.NonCancellableDemo
import com.istudio.app.modules.module_demos.coroutines.coroutine_cancellation.root_children_cencel_demo.RootChildrenCancelDemo
import com.istudio.app.modules.module_demos.coroutines.dispatchers.DispatchersDemo
import com.istudio.app.modules.module_demos.coroutines.exception_handeling.ExceptionHandlingSelectionDemo
import com.istudio.app.modules.module_demos.coroutines.exception_handeling.using_async.UsingAsyncExceptionHandleDemo
import com.istudio.app.modules.module_demos.coroutines.exception_handeling.using_launch.UsingLaunchExceptionHandleDemo
import com.istudio.app.modules.module_demos.coroutines.job.JobDemoSelection
import com.istudio.app.modules.module_demos.coroutines.launch_and_withcontext.LaunchAndWithContextDemo
import com.istudio.app.modules.module_demos.coroutines.simple_structured_concurrency.SimpleStructuredConcurrencyDemo
import com.istudio.app.modules.module_demos.coroutines.suspend_and_launch_demo.SuspendAndLaunchDemo
import com.istudio.app.modules.module_demos.coroutines.using_async_await.UsingAsyncAwaitDemo
import com.istudio.app.modules.module_demos.coroutines.using_join.UsingJoinDemo
import com.istudio.app.modules.module_demos.flows.FlowsDemo
import com.istudio.app.modules.module_demos.flows.modules.collect_as_state_with_lifecycle.CollectAsStateWithLifeCycleDemo
import com.istudio.app.modules.module_demos.flows.modules.compose_and_flatten_flows.ComposeAndFlattenFlows
import com.istudio.app.modules.module_demos.flows.modules.flatten_flows.FlattenFlowsDemo
import com.istudio.app.modules.module_demos.flows.modules.flow_basics.chapters.display_data_from_server.DisplayDataFromServerDemo
import com.istudio.app.modules.module_demos.flows.modules.intermediate_operators.IntermediateOperators
import com.istudio.app.modules.module_demos.flows.modules.terminal_operators.TerminalOperators
import com.istudio.app.modules.module_demos.flows.modules.flow_basics.ui.FlowBasics
import com.istudio.app.modules.module_demos.flows.modules.mutable_state_of_flow.MutableStateOfFlowDemo
import com.istudio.app.modules.module_demos.flows.modules.state_and_shared_flows.StateAndSharedFlowDemo
import com.istudio.app.modules.module_demos.higher_order_functions.ui.HigherOrderFunctionDemo
import com.istudio.app.modules.module_demos.kotlin_annotations.ui.KotlinAnnotationsDemo
import com.istudio.app.modules.module_demos.nested_vs_inner.ui.NestedVsInner
import com.istudio.app.modules.module_demos.sealed_class.ui.SealedClassDemo
import com.istudio.app.modules.module_demos.type_alias.ui.TypeAlias
import com.istudio.app.modules.module_exercises.ExerciseSelection
import com.istudio.app.modules.module_exercises.exercise_1.Exercise1
import com.istudio.app.modules.module_exercises.exercise_2.Exercise2
import com.istudio.app.modules.module_selection.ModuleDemo
import com.istudio.app.modules.module_selection.ModuleSelectionScreen
import com.istudio.app.ui.theme.KotlinConceptsTheme
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
private val viewModel: MainViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
KotlinConceptsTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
val navController = rememberNavController()
NavHost(
navController = navController,
startDestination = ModuleDemo.DemoSelection.rout
) {
// Selection Screen
composable(ModuleDemo.DemoSelection.rout) {
ModuleSelectionScreen(navController = navController)
}
// Kotlin basics Screen
composable(ModuleDemo.KotlinBasicsDemo.rout) {
KotlinBasicsDemo(navController = navController)
}
// Channel demo
composable(ModuleDemo.ChannelsDemo.rout) {
ChannelsDemo(navController = navController)
}
// Sealed Class demo
composable(ModuleDemo.SealedClassDemo.rout) {
SealedClassDemo(navController = navController)
}
// Higher Order functions demo
composable(ModuleDemo.HigherOrderFunctions.rout) {
HigherOrderFunctionDemo(navController = navController)
}
// Kotlin Annotations demo
composable(ModuleDemo.AnnotationsInKotlin.rout) {
KotlinAnnotationsDemo(navController = navController)
}
// Type Alias
composable(ModuleDemo.TypeAlias.rout) {
TypeAlias(navController = navController)
}
// Kotlin Flow Selection
composable(ModuleDemo.FlowsSelection.rout) {
FlowsDemo(navController = navController)
}
// Flow Basics
composable(ModuleDemo.FlowBasics.rout) {
FlowBasics(navController = navController)
}
// Display data from server
composable(ModuleDemo.DisplayDataFromServer.rout) {
DisplayDataFromServerDemo(navController = navController)
}
// Terminal Operators
composable(ModuleDemo.TerminalOperators.rout) {
TerminalOperators(navController = navController)
}
// Intermediate Operators
composable(ModuleDemo.IntermediateOperators.rout) {
IntermediateOperators(navController = navController)
}
// NestedVsInner Demo
composable(ModuleDemo.NestedVsInner.rout) {
NestedVsInner(navController = navController)
}
// Coroutines Demo
composable(ModuleDemo.CoroutinesDemo.rout) {
CoroutinesDemo(navController = navController)
}
// Simple structured concurrency
composable(ModuleDemo.SimpleStructuredConcurrencyDemo.rout) {
SimpleStructuredConcurrencyDemo(navController = navController)
}
// Dispatchers Demo
composable(ModuleDemo.DispatchersDemo.rout) {
DispatchersDemo(navController = navController)
}
// Exercises
composable(ModuleDemo.Exercises.rout) {
ExerciseSelection(navController = navController)
}
// Exercise-1
composable(ModuleDemo.Exercise1.rout) {
Exercise1(navController = navController)
}
// Exercise-2
composable(ModuleDemo.Exercise2.rout) {
Exercise2(navController = navController)
}
// Coroutine cancellation demo
composable(ModuleDemo.CoroutinesCancellationSelection.rout) {
CoroutinesCancellationSelection(navController = navController)
}
// CoRoutine cancellation selection
composable(ModuleDemo.RootChildrenCancelDemo.rout) {
RootChildrenCancelDemo(navController = navController)
}
// CoRoutine isActive Demo
composable(ModuleDemo.CoroutinesCancellationIsActiveDemo.rout) {
IsActiveDemo(navController = navController)
}
// CoRoutine EnsureActive Demo
composable(ModuleDemo.EnsureActiveDemo.rout) {
EnsureActiveDemo(navController = navController)
}
// CoRoutine NonCancellable Demo
composable(ModuleDemo.NonCancellableDemo.rout) {
NonCancellableDemo(navController = navController)
}
// Suspend and Launch demo
composable(ModuleDemo.SuspendAndLaunchDemo.rout) {
SuspendAndLaunchDemo(navController = navController)
}
// Launch And WithContext demo
composable(ModuleDemo.LaunchAndWithContextDemo.rout) {
LaunchAndWithContextDemo(navController = navController)
}
// Job Demo
composable(ModuleDemo.JobDemoSelection.rout) {
JobDemoSelection(navController = navController)
}
// Using Join Demo
composable(ModuleDemo.UsingJoinDemo.rout) {
UsingJoinDemo(navController = navController)
}
// Using Async Await Demo
composable(ModuleDemo.UsingAsyncAwaitDemo.rout) {
UsingAsyncAwaitDemo(navController = navController)
}
// Exception Handling Selection Demo
composable(ModuleDemo.ExceptionHandlingSelectionDemo.rout) {
ExceptionHandlingSelectionDemo(navController = navController)
}
// Using Launch Exception Handle Demo
composable(ModuleDemo.UsingLaunchExceptionHandleDemo.rout) {
UsingLaunchExceptionHandleDemo(navController = navController)
}
// Using Async Exception Handle Demo
composable(ModuleDemo.UsingAsyncExceptionHandleDemo.rout) {
UsingAsyncExceptionHandleDemo(navController = navController)
}
// Compose And Flatten Flows
composable(ModuleDemo.ComposingAndFlatteningTheFlows.rout) {
ComposeAndFlattenFlows(navController = navController)
}
// State And Shared Flows
composable(ModuleDemo.StateAndSharedFlowDemo.rout) {
StateAndSharedFlowDemo(navController = navController)
}
// Mutable state of flow demo
composable(ModuleDemo.MutableStateOfFlowDemo.rout) {
MutableStateOfFlowDemo(navController = navController)
}
// Flatten Flows
composable(ModuleDemo.FlattenFlowsDemo.rout) {
FlattenFlowsDemo(navController = navController)
}
// Compare Join Async Demo
composable(ModuleDemo.CompareJoinAsyncDemo.rout) {
CompareJoinAsyncDemo(navController = navController)
}
// Collect As Life Cycle Demo
composable(ModuleDemo.CollectAsStateWithLifeCycle.rout) {
CollectAsStateWithLifeCycleDemo(navController = navController)
}
}
}
}
}
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/main/MainViewModel.kt
================================================
package com.istudio.app.main
import androidx.lifecycle.ViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@HiltViewModel
class MainViewModel @Inject constructor( ) : ViewModel() {
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/basic_fundamentals/ui/KotlinBasicsDemo.kt
================================================
package com.istudio.app.modules.module_demos.basic_fundamentals.ui
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.istudio.app.ui.composables.AppButton
import com.istudio.app.ui.composables.AppText
@Composable
fun KotlinBasicsDemo(navController: NavHostController) {
val viewModel: KotlinBasicsDemoVm = hiltViewModel()
val scrollState = rememberScrollState()
Column(
modifier = Modifier
.verticalScroll(state = scrollState)
.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Strings in kotlin", onClick = {
viewModel.stringsInKotlin()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Comparison operators", onClick = {
viewModel.comparisionOperators()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Large tree in conditions", onClick = {
viewModel.largeTreeConditions()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Defining & using nullable", onClick = {
viewModel.definingAndUsingNullable()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Pairs & Triplets", onClick = {
viewModel.storingPairsAndTriplets()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Arrays in kotlin", onClick = {
viewModel.arraysInKotlin()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "List in kotlin", onClick = {
viewModel.listInKotlin()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Map in kotlin", onClick = {
viewModel.mapInKotlin()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Set in kotlin", onClick = {
viewModel.setInKotlin()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Custom Accessors", onClick = {
viewModel.customAccessors()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Enum in kotlin", onClick = {
viewModel.enumInKotlin()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Members are private by default", onClick = {
viewModel.membersPrivateDemo()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Init block significance", onClick = {
viewModel.initBlockSignificanceDemo()
})
Spacer(modifier = Modifier.height(16.dp))
AppText(text = "Constructors Demo")
Spacer(modifier = Modifier.height(5.dp))
AppButton(text = "Primary Constructor", onClick = {
viewModel.primaryConstructorDemo()
})
Spacer(modifier = Modifier.height(5.dp))
AppButton(text = "Secondary Constructor", onClick = {
viewModel.secondaryConstructorDemo()
})
Spacer(modifier = Modifier.height(16.dp))
AppText(text = "Multiple Inheritance")
Spacer(modifier = Modifier.height(5.dp))
AppButton(text = "Multiple Inheritance In Kotlin", onClick = {
viewModel.multipleInheritanceInKotlin()
})
Spacer(modifier = Modifier.height(16.dp))
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/basic_fundamentals/ui/KotlinBasicsDemoVm.kt
================================================
package com.istudio.app.modules.module_demos.basic_fundamentals.ui
import androidx.lifecycle.ViewModel
import com.istudio.app.modules.module_demos.basic_fundamentals.utils.Student
import com.istudio.app.modules.module_demos.basic_fundamentals.utils.multipleInheritance.in_kotlin.KotlinImplementation
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@HiltViewModel
class KotlinBasicsDemoVm @Inject constructor( ) : ViewModel() {
/**
* Concatenating of strings
*/
fun stringsInKotlin() {
// Assigning explicitly the data type and then setting a value to it
// This will always accept only the integer
var age : Int = 21
var firstName : String = "Tony"
// Kotlin can infer the values so that we need not have to explicitly mention them, Meaning datatype , we need not have to add
var lastName : String = "Stark"
println("My name is $firstName $lastName and I am $age years old scientist")
// Appending the variables in the string is reformatting it is called string interpolation
}
/**
* Comparison Operators
*/
fun comparisionOperators() {
val conditionCheck = 25 > 21
println("Condition Check Result:-> $conditionCheck")
var firstValue = Student("Mahesh",22)
var secondValue = Student("Mahesh",22)
// DoubleEqual => Check if both variables are equal by value
val resultValueOne = firstValue==secondValue
println("DoubleEqual:-> $resultValueOne")// Result: true
// TripleEqual => Check if both variables are equal by reference
val resultValueTwo = firstValue===secondValue
println("TripleEqual:-> $resultValueTwo")// Result: false
}
/**
* Large tree conditions
*/
fun largeTreeConditions() {
val input = "Hello"
// We explicitly specify that the output will be string
// if we does not specify and there can be possibility that value returned will be the value of input
val finalOutput : String = if( input == "a" ) {
"a"
} else if( input == "b" ){
"b"
} else if( input == "c" ){
"c"
} else{
"Hello"
}
println("Result:-> $finalOutput")
}
/**
* Defining and using nullable values
*/
fun definingAndUsingNullable() {
// If we need to assign a null value to a variable, We explicitly need to mention it
var name : String ? = null
println(name) // This will print null
//name.length // This will throw a compiler error referring, null check is needed
name = "hello"
println(name) // We can re-assign a different value to a null variable
println("<-------------------------------------------->")
// For forcing-ly to use a null value
var city : String ? = null
println(city!!.length) // This will crash since city is null here
}
/**
* Storing pairs and triplets
*/
fun storingPairsAndTriplets() {
// Demo: Pair
val details : Pair = Pair("Mahesh","USA")
val (name,city) = details;
println("Name:-> $name")
println("City:-> $city")
println("<-------------------------------------------->")
// Demo: Triplets
val fullDetails : Triple = Triple("Mahesh","USA",21)
val (nameX,cityX,ageX) = fullDetails
println("Name:-> $nameX")
println("City:-> $cityX")
println("Age:-> $ageX")
println("<-------------------------------------------->")
}
/**
* Arrays in kotlin
*/
fun arraysInKotlin() {
// Declaring the array
var listOfCities = listOf("Bangalore","NewYork","Tokyo")
// This will print the address of the array
println(listOfCities)
// This will print the size of the array
println(listOfCities.size)
// This will access the element from a index
println(listOfCities[1])
// Check if the array has a particular element
println(listOfCities.contains("Bangalore"))
// Another way to check if the element is present in the arrays
println("Bangalore" in listOfCities)
// Getting the first element in the array
println(listOfCities.first())
// Getting the last element in the array
println(listOfCities.last())
// This will throw the error Index out of bound
println(listOfCities[-1])
}
/**
* List in kotlin
*/
fun listInKotlin() {
// List of cities
var cityList = listOf("Bangalore","Delhi","Chennai","Calcutta")
// Not possible since its just a list and not a mutable list
// cityList.add()
// we can convert one list to another list
var mutableCityList = cityList.toMutableList()
// Since now its a mutable list, we can modify the list
mutableCityList.add("Texas")
// We can directly add a element at a position also
mutableCityList.add(1,"Colombo")
// We can remove a element at a position from th elist
mutableCityList.removeAt(2)
}
/**
* Map in kotlin
*/
fun mapInKotlin() {
val listOfCities = mapOf(
1 to "Bangalore",
2 to "Mumbai",
3 to "Chennai",
)
//listOfCities[1] = "Shanghai" // Not possible
println(listOfCities[1])
val listOfNames = mutableMapOf(
1 to "Manish",
2 to "John",
3 to "Sam",
)
listOfNames[4] = "Anudeep"
println(listOfNames[4])
}
/**
* Set in kotlin
*/
fun setInKotlin() {
var students = setOf("Mahesh","Suresh","Venkatesh","Mahesh")
// students.add // Not possible
println(students)
var cities = mutableSetOf("bangalore","Hassan","Mumbai")
cities.add("Colombo")
println(students.contains("Colombo"))
}
enum class DaysOfTheWeek { MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY }
enum class DaysOfTheWeekWithValues(val isWeekend: Boolean = false) {
MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY(isWeekend = true), SUNDAY(isWeekend = true);
}
/**
* Enum in kotlin
*/
fun enumInKotlin() {
// Looping the enum values, And accessing the position
for(week in DaysOfTheWeek.values()){
println("$week at position ${week.ordinal}")
}
// Looping the enum values, And accessing the position with default values
for (week in DaysOfTheWeekWithValues.values()){
// Ordinal helps in printing the position of the current enum class
println("Week-Name: $week -- at position -- ${week.ordinal} -- is weekend ${week.isWeekend}")
}
}
// backing field
private var myProperty: Int = 0
// custom getter
private val customProperty: Int
get() {
println("Getting customProperty value")
return myProperty
}
// custom setter
private var anotherProperty: String
get() {
println("Getting anotherProperty value")
return "Getter value"
}
set(value) {
println("Setting anotherProperty value to $value")
}
/**
* Having custom accessors
*/
fun customAccessors() {
// Using the custom getter
println(customProperty) // Output: Getting customProperty value
// Using the custom setter
anotherProperty = "New Value"
println(anotherProperty) // Output: Setting anotherProperty value to New Value
}
/**
* Members are private by default
*/
fun membersPrivateDemo() {
val person = Person("Donald")
//person.name // Unresolved reference: name
val student = Student("Einstein")
student.name // We can access the name variable
}
class Person(name: String)
class Student(val name: String)
/**
* Init block significance
*/
fun initBlockSignificanceDemo() {
println("Before City Class construction")
val demo = City("New York")
println("After City Class construction")
demo.demo()
}
class City(val name: String){
init {
println("City is created with Name:-> $name")
}
fun demo(){
println("City construction is in progress")
}
}
/**
* Primary constructor demo
*/
fun primaryConstructorDemo() {
val science = Science()
val history = History()
// val maths = Maths() // Cannot access '': it is private in 'Maths'
}
// Class with default constructor(way 1)
class Science()
// Class with default constructor(way 2)
class History constructor()
// Class with private constructor
class Maths private constructor()
// Class with protected constructor constructor
class Computers protected constructor()
/**
* Secondary constructor demo
*/
fun secondaryConstructorDemo(){
val mechanical = Mechanical(name = "CustomName", noOfPages = 10)
}
class Mechanical(val name:String){
constructor(name: String, noOfPages:Int) : this(name)
}
/**
* Multiple Inheritance Alternatively using delegation
*/
fun multipleInheritanceInKotlin(){
val kotlinImplementation = KotlinImplementation()
kotlinImplementation.methodA()
kotlinImplementation.methodB()
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/basic_fundamentals/utils/Student.kt
================================================
package com.istudio.app.modules.module_demos.basic_fundamentals.utils
data class Student(val name : String , val age : Int)
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/basic_fundamentals/utils/multipleInheritance/in_java/InJava.java
================================================
package com.istudio.app.modules.module_demos.basic_fundamentals.utils.multipleInheritance.in_java;
public class InJava implements Sony,Samsung{
@Override
public void content() {
System.out.println("Television content");
}
@Override
public void methodSonyName() {
System.out.println("Sony name");
}
@Override
public void methodSamsungName() {
System.out.println("Samsung name");
}
}
interface Telivision{
void content();
}
interface Sony extends Telivision{
void methodSonyName();
}
interface Samsung extends Telivision{
void methodSamsungName();
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/basic_fundamentals/utils/multipleInheritance/in_kotlin/InKotlin.kt
================================================
package com.istudio.app.modules.module_demos.basic_fundamentals.utils.multipleInheritance.in_kotlin
class KotlinImplementation : KotlinInterfaceA, KotlinInterfaceB {
private val implementationA = ClassA()
private val implementationB = ClassB()
override fun methodA() {
implementationA.methodA()
}
override fun methodB() {
implementationB.methodB()
}
}
interface KotlinInterfaceA {
fun methodA()
}
interface KotlinInterfaceB {
fun methodB()
}
class ClassA : KotlinInterfaceA {
override fun methodA() {
println("Implementation of methodA from ClassA")
}
}
class ClassB : KotlinInterfaceB {
override fun methodB() {
println("Implementation of methodB from ClassB")
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/channels/ChannelsDemo.kt
================================================
package com.istudio.app.modules.module_demos.channels
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.istudio.app.ui.composables.AppButton
import com.istudio.app.ui.composables.AppText
@Composable
fun ChannelsDemo(navController: NavHostController) {
val viewModel: ChannelsDemoVm = hiltViewModel()
val scrollState = rememberScrollState()
Column(
modifier = Modifier
.verticalScroll(state = scrollState)
.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
//
AppText(text = "Basics")
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Simple Communication", onClick = {
viewModel.simpleCommunication()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Sending/Receiving multiple values", onClick = {
viewModel.sendingMultipleValues()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Canceling a channel", onClick = {
viewModel.cancellingChannel()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Closing a channel", onClick = {
viewModel.closingChannel()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Using Produce", onClick = {
viewModel.usingProduce()
})
Spacer(modifier = Modifier.height(20.dp))
//
//
AppText(text = "Channel Types")
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Channel - Buffered", onClick = {
viewModel.usingBuffered()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Channel - Conflated", onClick = {
viewModel.usingConflated()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Channel - Rendezvous", onClick = {
viewModel.usingRendezvous()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Channel - Unlimited", onClick = {
viewModel.usingUnlimited()
})
//
AppText(text = "Types of communication")
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "1-1 --> Communication", onClick = {
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "1-n --> Communication", onClick = {
viewModel.usingOneToMany()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "n-1 --> Communication", onClick = {
viewModel.usingManyToOne()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "n-n --> Communication", onClick = {
})
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/channels/ChannelsDemoVm.kt
================================================
package com.istudio.app.modules.module_demos.channels
import android.widget.TextView.BufferType
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.channels.Channel.Factory.CONFLATED
import kotlinx.coroutines.channels.Channel.Factory.UNLIMITED
import kotlinx.coroutines.channels.ReceiveChannel
import kotlinx.coroutines.channels.consumeEach
import kotlinx.coroutines.channels.produce
import kotlinx.coroutines.delay
import kotlinx.coroutines.joinAll
import kotlinx.coroutines.launch
import java.lang.Exception
import javax.inject.Inject
@HiltViewModel
class ChannelsDemoVm @Inject constructor( ) : ViewModel() {
//
// A channel of languages
private var languageChannel = Channel()
/**
* Sending and receiving only one value
*/
fun simpleCommunication() {
// Co-Routine - 1
viewModelScope.launch {
languageChannel.send(Languages.English)
}
// Co-Routine - 2
viewModelScope.launch {
println(languageChannel.receive())
}
}
/**
* Sending and receiving multiple values
*/
fun sendingMultipleValues() {
// Co-Routine - 1
viewModelScope.launch {
languageChannel.send(Languages.English)
languageChannel.send(Languages.Hindi)
languageChannel.send(Languages.French)
}
// Co-Routine - 2
viewModelScope.launch {
languageChannel.consumeEach {
println(languageChannel.receive())
}
}
}
/**
* Canceling a channel
*/
fun cancellingChannel() {
// Co-Routine - 1
viewModelScope.launch {
println("Sending value - 1")
languageChannel.send(Languages.English)
println("Sending value - 2")
languageChannel.send(Languages.Hindi)
println("Sending value - 3")
languageChannel.send(Languages.French)
}
// Co-Routine - 2
viewModelScope.launch {
try {
println(languageChannel.receive())
languageChannel.cancel(CancellationException("Custom Exception"))
println(languageChannel.receive())
println(languageChannel.receive())
}catch (ex : Exception){
println(ex.message)
println("Is it closed for Send: -> "+languageChannel.isClosedForSend)
println("Is it closed for Receive: -> "+languageChannel.isClosedForReceive)
}
}
}
/**
* Closing a channel
*/
fun closingChannel() {
// Co-Routine - 1
viewModelScope.launch {
languageChannel.send(Languages.English)
languageChannel.close()
languageChannel.send(Languages.Hindi)
languageChannel.send(Languages.French)
}
// Co-Routine - 2
viewModelScope.launch {
languageChannel.consumeEach {
println(languageChannel.receive())
}
}
}
enum class Languages { English , Hindi , French }
//
//
private var receiveChannel : ReceiveChannel = Channel()
fun usingProduce() {
// Co-Routine - 1
viewModelScope.launch {
receiveChannel = produce {
send(Superheroes.Batman)
send(Superheroes.Superman)
send(Superheroes.Spiderman)
}
}
// Co-Routine - 2
viewModelScope.launch {
println("Is closed to receive -->"+ receiveChannel.isClosedForReceive)
receiveChannel.consumeEach { superHero ->
println(superHero)
}
println("Is closed to receive -->"+ receiveChannel.isClosedForReceive)
}
}
enum class Superheroes { Batman , Superman , Spiderman }
//
//
private var receiveBufferChannel : ReceiveChannel = Channel()
fun usingBuffered() {
// Co-Routine - 1
viewModelScope.launch {
// We are limiting the buffer capacity to 2
receiveBufferChannel = produce(capacity = 2) {
println("Send Action : ----> USA")
send(Countries.USA)
println("Send Action : ----> Russia")
send(Countries.Russia)
println("Send Action : ----> India")
send(Countries.India)
println("Send Action : ----> France")
send(Countries.France)
println("Send Action : ----> Spain")
send(Countries.Spain)
println("Send Action : ----> Germany")
send(Countries.Germany)
println("Send Action : ----> Italy")
send(Countries.Italy)
}
}
// Co-Routine - 2
viewModelScope.launch {
receiveBufferChannel.consumeEach { countries ->
println("Receive Action : ----> $countries")
println("---------------------------------")
}
}
}
enum class Countries { USA , Russia , India , France , Spain , Germany , Italy }
//
//
private var receiveConflatedChannel : ReceiveChannel = Channel()
fun usingConflated() {
// Co-Routine - 1
viewModelScope.launch {
receiveConflatedChannel = produce(capacity = CONFLATED) {
send(Birds.Eagle)
send(Birds.Peacock)
send(Birds.Robin)
send(Birds.Ostrich)
send(Birds.Pigeon)
send(Birds.Kingfisher)
send(Birds.Dodo)
}
}
// Co-Routine - 2
viewModelScope.launch {
receiveConflatedChannel.consumeEach { birds ->
println("BIRD : ----> $birds")
}
}
}
enum class Birds { Eagle , Peacock , Robin , Ostrich , Pigeon , Kingfisher , Dodo }
//
//
private var receiveRendezvousChannel : ReceiveChannel = Channel()
fun usingRendezvous() {
// Co-Routine - 1
viewModelScope.launch {
receiveRendezvousChannel = produce {
println("SENT : ----> ${Cars.Maruthi}")
send(Cars.Maruthi)
println("SENT : ----> ${Cars.BMW}")
send(Cars.BMW)
println("SENT : ----> ${Cars.Tesla}")
send(Cars.Tesla)
println("SENT : ----> ${Cars.Byd}")
send(Cars.Byd)
println("SENT : ----> ${Cars.TATA}")
send(Cars.TATA)
println("SENT : ----> ${Cars.Ferrari}")
send(Cars.Ferrari)
println("SENT : ----> ${Cars.Porshe}")
send(Cars.Porshe)
}
}
// Co-Routine - 2
viewModelScope.launch {
println("CAR : ----> ${receiveRendezvousChannel.receive()}")
println("CAR : ----> ${receiveRendezvousChannel.receive()}")
println("CAR : ----> ${receiveRendezvousChannel.receive()}")
}
}
enum class Cars { Maruthi , BMW , Tesla , Byd , TATA , Ferrari , Porshe }
//
//
private var receiveUnlimitedChannel : ReceiveChannel = Channel()
fun usingUnlimited() {
// Co-Routine - 1
viewModelScope.launch {
receiveUnlimitedChannel = produce(capacity = UNLIMITED) {
println("SENT : ----> ${Cars.Maruthi}")
send(Cars.Maruthi)
println("SENT : ----> ${Cars.BMW}")
send(Cars.BMW)
println("SENT : ----> ${Cars.Tesla}")
send(Cars.Tesla)
println("SENT : ----> ${Cars.Byd}")
send(Cars.Byd)
println("SENT : ----> ${Cars.TATA}")
send(Cars.TATA)
println("SENT : ----> ${Cars.Ferrari}")
send(Cars.Ferrari)
println("SENT : ----> ${Cars.Porshe}")
send(Cars.Porshe)
}
}
// Co-Routine - 2
viewModelScope.launch {
println("CAR : ----> ${receiveUnlimitedChannel.receive()}")
println("CAR : ----> ${receiveUnlimitedChannel.receive()}")
println("CAR : ----> ${receiveUnlimitedChannel.receive()}")
}
}
//
//
private var one_to_n_channel : ReceiveChannel = Channel()
fun usingOneToMany() {
viewModelScope.launch {
// Producer -1
one_to_n_channel = produce(capacity = UNLIMITED){
repeat(10){ currentValue -> send(currentValue) }
}
}
viewModelScope.launch {
// Coroutine - 1
viewModelScope.launch {
// Consumer - 1
one_to_n_channel.consumeEach {
println("Consumer-1 <-> (1-n) : ----> $it")
delay(300)
}
}
// Coroutine - 2
viewModelScope.launch {
// Consumer - 2
one_to_n_channel.consumeEach {
println("Consumer-2 <-> (1-n) : ----> $it")
delay(100)
}
}
// Coroutine - 3
viewModelScope.launch {
// Consumer - 3
one_to_n_channel.consumeEach {
println("Consumer-3 <-> (1-n) : ----> $it")
delay(150)
}
}
}
}
//
//
private var n_to_one_channel : Channel = Channel()
fun usingManyToOne() {
viewModelScope.launch {
// Producer -1
val firstProducer = viewModelScope.async {
repeat(3){ currentValue ->
n_to_one_channel.send("FromProducer-1 $currentValue")
delay(150)
}
}
// Producer -2
val secondProducer = viewModelScope.async {
repeat(3){ currentValue ->
n_to_one_channel.send("FromProducer-2 $currentValue")
delay(100)
}
}
awaitAll(secondProducer,firstProducer)
}
// Consumer-1
viewModelScope.launch {
n_to_one_channel.consumeEach {
println("Consumer <-> (N-1) : ----> $it")
}
}
}
//
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/coroutines/CoroutinesDemo.kt
================================================
package com.istudio.app.modules.module_demos.coroutines
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavController
import com.istudio.app.modules.module_selection.ModuleDemo
import com.istudio.app.ui.composables.AppButton
@Composable
fun CoroutinesDemo(navController: NavController){
val viewModel: CoroutinesDemoVm = hiltViewModel()
val scrollState = rememberScrollState()
Column(
modifier = Modifier.fillMaxSize() .verticalScroll(state = scrollState),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Create a Coroutine scope", onClick = {
viewModel.createCoroutineScopeDemo()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Wait for coroutine to finish", onClick = {
viewModel.waitForCoRoutineToFinish()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Sequential coroutines", onClick = {
viewModel.sequentialCoroutiens()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Scope and context relationship", onClick = {
viewModel.scopeAndContextRelationshipDemo()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Simple structured concurrency", onClick = {
navController.navigate(ModuleDemo.SimpleStructuredConcurrencyDemo.rout)
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Dispatchers Demo", onClick = {
navController.navigate(ModuleDemo.DispatchersDemo.rout)
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Coroutine Cancellation Demos", onClick = {
navController.navigate(ModuleDemo.CoroutinesCancellationSelection.rout)
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Suspend And Launch Demo", onClick = {
navController.navigate(ModuleDemo.SuspendAndLaunchDemo.rout)
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Launch and with context demo", onClick = {
navController.navigate(ModuleDemo.LaunchAndWithContextDemo.rout)
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Job Demos", onClick = {
navController.navigate(ModuleDemo.JobDemoSelection.rout)
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Using Join Demo", onClick = {
navController.navigate(ModuleDemo.UsingJoinDemo.rout)
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Using Async Await Demo", onClick = {
navController.navigate(ModuleDemo.UsingAsyncAwaitDemo.rout)
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Compare Join Async Demo", onClick = {
navController.navigate(ModuleDemo.CompareJoinAsyncDemo.rout)
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Exception Handling Selection", onClick = {
navController.navigate(ModuleDemo.ExceptionHandlingSelectionDemo.rout)
})
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/coroutines/CoroutinesDemoVm.kt
================================================
package com.istudio.app.modules.module_demos.coroutines
import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineName
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
@HiltViewModel
class CoroutinesDemoVm @Inject constructor(val context: Application) : AndroidViewModel(context) {
/**
* **************** DEMO: Create a coroutine scope ****************
*/
fun createCoroutineScopeDemo() {
println("Before the scope")
CoroutineScope(context = prepareContext()).launch {
val name = coroutineContext[CoroutineName]?.name
println("$name:-> Before the delay")
delay(1000)
println("$name:-> After the delay")
}
println("After the scope")
}
private fun prepareContext(): CoroutineContext {
val context = EmptyCoroutineContext
val name = "MyCoroutine"
val job = Job()
val exceptionHandler = CoroutineExceptionHandler{ _ , throwable ->
println("Error in coroutine: $throwable")
}
val dispatcher = Dispatchers.Default
return (context + job + CoroutineName(name) + dispatcher + exceptionHandler)
}
/**
* **************** DEMO: Create a coroutine scope ****************
*/
/**
* **************** DEMO: Wait for coroutine to finish ****************
*/
fun waitForCoRoutineToFinish() {
//println("Before the view model scope")
viewModelScope.launch {
println("Before the coroutine scope") // - 1
CoroutineScope(EmptyCoroutineContext).launch {
println("Before the delay") // - 2
delay(1000)
println("After the delay") // - 3
}.join()
println("After the coroutine scope") // - 4
}
//println("After the view model scope")
}
/**
* **************** DEMO: Wait for coroutine to finish ****************
*/
/**
* **************** DEMO: Sequential coroutines ***********************
*/
fun sequentialCoroutiens() {
viewModelScope.launch {
println("JOB-1: Before the coroutine scope")
CoroutineScope(EmptyCoroutineContext).launch {
println("JOB-1: ----> Before the delay")
delay(1000)
println("JOB-1: ----> After the delay")
}.join()
println("JOB-1: After the coroutine scope")
println("---------------------------------")
println("JOB-2: Before the coroutine scope")
CoroutineScope(EmptyCoroutineContext).launch {
println("JOB-2: ----> Before the delay")
delay(1000)
println("JOB-2: ----> After the delay")
}.join()
println("JOB-2: After the coroutine scope")
}
}
/**
* **************** DEMO: Sequential coroutines ***********************
*/
/**
* **************** DEMO: Scope And Context Relationship **************
*/
fun scopeAndContextRelationshipDemo() {
viewModelScope.launch(CoroutineName("Pikachuu")) {
val name = coroutineContext[CoroutineName]?.name
println("OuterMostCoroutine:-> $name")
launch {
val name = coroutineContext[CoroutineName]?.name
println("InnerCoroutine1:-> $name")
launch {
val name = coroutineContext[CoroutineName]?.name
println("InnermostCoroutine1:-> $name")
}.join()
}.join()
launch {
val name = coroutineContext[CoroutineName]?.name
println("InnerCoroutine2:-> $name")
launch(CoroutineName("Goku ")) {
val name = coroutineContext[CoroutineName]?.name
println("InnermostCoroutine2:-> $name")
}.join()
}.join()
}
}
/**
* **************** DEMO: Scope And Context Relationship **************
*/
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/coroutines/compare_join_and_async/CompareJoinAsyncDemo.kt
================================================
package com.istudio.app.modules.module_demos.coroutines.compare_join_and_async
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.istudio.app.ui.composables.AppButton
@Composable
fun CompareJoinAsyncDemo(navController: NavHostController) {
val viewModel: CompareJoinAsyncDemoVm = hiltViewModel()
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.height(20.dp))
AppButton(text = "Join Demo") {
viewModel.joinDemo()
}
Spacer(modifier = Modifier.height(5.dp))
AppButton(text = "Async Demo") {
viewModel.asyncDemo()
}
Spacer(modifier = Modifier.height(20.dp))
AppButton(text = "Cancel-Root") {
viewModel.rootCancel()
}
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/coroutines/compare_join_and_async/CompareJoinAsyncDemoVm.kt
================================================
package com.istudio.app.modules.module_demos.coroutines.compare_join_and_async
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.CoroutineName
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import javax.inject.Inject
class CompareJoinAsyncDemoVm @Inject constructor( ) : ViewModel() {
private val scopeJob = Job()
private val ourScope = CoroutineScope(scopeJob + Dispatchers.Default)
fun joinDemo() {
try {
ourScope.launch(CoroutineName("GrandParent")) {
try {
println("Before calling Join")
parent1Block().join()
println("After calling Join")
}catch (ex:Exception){
println("Exception caught inside GrandParent scope")
}
}.invokeOnCompletion {
println("GrandParent invokeOnCompletion triggered")
}
}catch (ex:Exception){
println("Exception caught outside GrandParent scope")
}
}
fun asyncDemo() {
try {
ourScope.launch(CoroutineName("GrandParent")) {
try {
println("Before calling Async")
parent2Block().await()
println("After calling Async")
}catch (ex:Exception){
println("Exception caught inside GrandParent scope")
}
}.invokeOnCompletion {
println("GrandParent invokeOnCompletion triggered")
}
}catch (ex:Exception){
println("Exception caught outside GrandParent scope")
}
}
private suspend fun parent1Block() = ourScope.launch(CoroutineName("Parent-1")) {
try {
repeat(10){
println("Parent-1 ----- tick ----->$it")
delay(1000)
}
}catch (ex:Exception){
println("Exception caught inside Parent-1 coroutine")
}
}
private suspend fun parent2Block() = ourScope.async (CoroutineName("Parent-2")) {
try {
repeat(10){
println("Parent-1 ----- tick ----->$it")
delay(1000)
}
}catch (ex:Exception){
println("Exception caught inside Parent-1 coroutine")
}
}
fun rootCancel() {
scopeJob?.cancel()
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/coroutines/coroutine_cancellation/CoroutinesCancellationSelection.kt
================================================
package com.istudio.app.modules.module_demos.coroutines.coroutine_cancellation
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.navigation.NavController
import com.istudio.app.modules.module_selection.ModuleDemo
import com.istudio.app.ui.composables.AppButton
@Composable
fun CoroutinesCancellationSelection(navController: NavController){
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Root Children Cancel Demo", onClick = {
navController.navigate(ModuleDemo.RootChildrenCancelDemo.rout)
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Is Active Demo", onClick = {
navController.navigate(ModuleDemo.CoroutinesCancellationIsActiveDemo.rout)
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Ensure Active Demo", onClick = {
navController.navigate(ModuleDemo.EnsureActiveDemo.rout)
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Non Cancellable Job", onClick = {
navController.navigate(ModuleDemo.NonCancellableDemo.rout)
})
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/coroutines/coroutine_cancellation/ensure_active_demo/EnsureActiveDemo.kt
================================================
package com.istudio.app.modules.module_demos.coroutines.coroutine_cancellation.ensure_active_demo
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.istudio.app.ui.composables.AppButton
@Composable
fun EnsureActiveDemo(navController: NavHostController){
val viewModel: EnsureActiveDemoVm = hiltViewModel()
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.height(100.dp))
AppButton(text = "Start \n with Thread-Sleep") {
viewModel.startWithThreadSleep()
}
Spacer(modifier = Modifier.height(100.dp))
Button(
modifier = Modifier
.background(
color = MaterialTheme.colorScheme.primary,
shape = RectangleShape
),
onClick = {
viewModel.cancel()
}
) {
Text(text = "Cancel")
}
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/coroutines/coroutine_cancellation/ensure_active_demo/EnsureActiveDemoVm.kt
================================================
package com.istudio.app.modules.module_demos.coroutines.coroutine_cancellation.ensure_active_demo
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.currentCoroutineContext
import kotlinx.coroutines.delay
import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import javax.inject.Inject
import kotlin.coroutines.cancellation.CancellationException
class EnsureActiveDemoVm @Inject constructor( ) : ViewModel() {
private var job: Job? = null
fun startWithThreadSleep() {
job = CoroutineScope(Dispatchers.Default).launch {
startSuspendWithThreadSleep()
}
}
private suspend fun startSuspendWithThreadSleep() {
try {
repeat(10) { index ->
currentCoroutineContext().ensureActive()
// Simulate some work
Thread.sleep(500)
// Check if the coroutine has been canceled
if (!currentCoroutineContext().isActive) {
println("Coroutine canceled at index $index")
}
// Continue with the main logic
println("Working at index $index")
}
// Additional logic after the loop
println("Coroutine completed")
} catch (e: CancellationException) {
// Handle cancellation-specific tasks
println("Coroutine canceled")
}
}
fun cancel(){
job?.cancel()
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/coroutines/coroutine_cancellation/is_active_demo/IsActiveDemo.kt
================================================
package com.istudio.app.modules.module_demos.coroutines.coroutine_cancellation.is_active_demo
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.istudio.app.ui.composables.AppButton
@Composable
fun IsActiveDemo(navController: NavHostController){
val viewModel: IsActiveDemoVm = hiltViewModel()
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.height(100.dp))
AppButton(text = "Start \n with Thread-Sleep") {
viewModel.startWithTreadSleep()
}
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Start \n with Thread-Delay") {
viewModel.startWithDelay()
}
Spacer(modifier = Modifier.height(100.dp))
Button(
modifier = Modifier
.background(
color = MaterialTheme.colorScheme.primary,
shape = RectangleShape
),
onClick = {
viewModel.cancel()
}
) {
Text(text = "Cancel")
}
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/coroutines/coroutine_cancellation/is_active_demo/IsActiveDemoVm.kt
================================================
package com.istudio.app.modules.module_demos.coroutines.coroutine_cancellation.is_active_demo
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
import kotlinx.coroutines.cancelChildren
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject
import kotlin.coroutines.cancellation.CancellationException
class IsActiveDemoVm @Inject constructor( ) : ViewModel() {
private var job: Job? = null
fun startWithTreadSleep() {
// Start a coroutine
job = CoroutineScope(Dispatchers.Default).launch {
try {
repeat(5000) { index ->
// Simulate some work
Thread.sleep(500)
// Check if the coroutine has been canceled
if (!isActive) {
println("Coroutine canceled at index $index")
return@launch
}
// Continue with the main logic
println("Working at index $index")
}
// Additional logic after the loop
println("Coroutine completed")
} catch (e: CancellationException) {
// Handle cancellation-specific tasks
println("Coroutine canceled")
}
}
}
fun startWithDelay() {
// Start a coroutine
job = CoroutineScope(Dispatchers.Default).launch {
try {
repeat(5000) { index ->
// Simulate some work
delay(500)
// Check if the coroutine has been canceled
if (!isActive) {
println("Coroutine canceled at index $index")
return@launch
}
// Continue with the main logic
println("Working at index $index")
}
// Additional logic after the loop
println("Coroutine completed")
} catch (e: CancellationException) {
// Handle cancellation-specific tasks
println("Coroutine canceled")
}
}
}
fun cancel(){
job?.cancel()
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/coroutines/coroutine_cancellation/non_cancellable_job/NonCancellableDemo.kt
================================================
package com.istudio.app.modules.module_demos.coroutines.coroutine_cancellation.non_cancellable_job
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.istudio.app.ui.composables.AppButton
@Composable
fun NonCancellableDemo(navController: NavHostController){
val viewModel: NonCancellableDemoVm = hiltViewModel()
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.height(100.dp))
AppButton(text = "Start \n with Thread-Sleep") {
viewModel.startWithTreadSleep()
}
Spacer(modifier = Modifier.height(100.dp))
Button(
modifier = Modifier
.background(
color = MaterialTheme.colorScheme.primary,
shape = RectangleShape
),
onClick = {
viewModel.cancel()
}
) {
Text(text = "Cancel")
}
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/coroutines/coroutine_cancellation/non_cancellable_job/NonCancellableDemoVm.kt
================================================
package com.istudio.app.modules.module_demos.coroutines.coroutine_cancellation.non_cancellable_job
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject
import kotlin.coroutines.cancellation.CancellationException
import kotlin.coroutines.coroutineContext
class NonCancellableDemoVm @Inject constructor( ) : ViewModel() {
private var job: Job? = null
fun startWithTreadSleep() {
// Start a coroutine
job = CoroutineScope(Dispatchers.Default ).launch {
coRoutineOne(1)
coRoutineOne(2)
}
}
private suspend fun coRoutineOne(coroutineNo: Int) {
withContext(NonCancellable){
try {
repeat(100) { index ->
//coroutineContext.ensureActive()
// Simulate some work
Thread.sleep(500)
// Check if the coroutine has been canceled
if (!kotlin.coroutines.coroutineContext.isActive) {
println("Coroutine-No:$coroutineNo canceled at index $index")
}else{
// Continue with the main logic
println("Coroutine-No:$coroutineNo Working at index $index")
}
}
// Additional logic after the loop
println("Coroutine-No:$coroutineNo completed")
}
catch (e: CancellationException) {
// Handle cancellation-specific tasks
println("Coroutine-No:$coroutineNo canceled")
}
}
}
fun cancel(){
job?.cancel()
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/coroutines/coroutine_cancellation/root_children_cencel_demo/RootChildrenCancelDemo.kt
================================================
package com.istudio.app.modules.module_demos.coroutines.coroutine_cancellation.root_children_cencel_demo
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.istudio.app.ui.composables.AppButton
import com.istudio.app.ui.composables.AppText
@Composable
fun RootChildrenCancelDemo(navController: NavHostController){
val viewModel: RootChildrenCancelDemoVm = hiltViewModel()
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
AppText(text = "CoRoutine Functionalities")
Spacer(modifier = Modifier.height(100.dp))
AppButton(text = "Start") {
viewModel.start()
}
Spacer(modifier = Modifier.height(16.dp))
Row(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 5.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceEvenly
) {
Button(
modifier = Modifier
.weight(1f)
.background(
color = MaterialTheme.colorScheme.primary,
shape = RectangleShape
),
onClick = {
viewModel.cancelRoot()
}
) {
Text(text = "Cancel-Root")
}
Spacer(modifier = Modifier.width(5.dp))
Button(
modifier = Modifier
.weight(1f)
.background(
color = MaterialTheme.colorScheme.primary,
shape = RectangleShape
),
onClick = {
viewModel.cancelChildren()
}
) {
Text(text = "Cancel-Children")
}
}
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/coroutines/coroutine_cancellation/root_children_cencel_demo/RootChildrenCancelDemoVm.kt
================================================
package com.istudio.app.modules.module_demos.coroutines.coroutine_cancellation.root_children_cencel_demo
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.cancel
import kotlinx.coroutines.cancelChildren
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject
class RootChildrenCancelDemoVm @Inject constructor( ) : ViewModel() {
private val rootScope = CoroutineScope(Dispatchers.Default)
fun start() {
rootScope.launch {
longRunningOperation()
}.invokeOnCompletion {
it?.let {
val message = it?.message
println("Exception thrown:-> $message")
}?:run {
println("Scope completed without exception")
}
}
}
fun cancelRoot(){
rootScope.cancel()
}
fun cancelChildren(){
rootScope.coroutineContext.cancelChildren()
}
private suspend fun longRunningOperation() = withContext(Dispatchers.Default){
for (i in 1..30){
println("Current count $i")
delay(1000)
}
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/coroutines/dispatchers/DispatchersDemo.kt
================================================
package com.istudio.app.modules.module_demos.coroutines.dispatchers
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.istudio.app.ui.composables.AppButton
import com.istudio.app.ui.composables.AppText
@Composable
fun DispatchersDemo(navController: NavHostController) {
val viewModel: DispatchersDemoVm = hiltViewModel()
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.height(20.dp))
AppButton(text = "Demo") {
viewModel.demo()
}
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/coroutines/dispatchers/DispatchersDemoVm.kt
================================================
package com.istudio.app.modules.module_demos.coroutines.dispatchers
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.util.concurrent.CancellationException
import javax.inject.Inject
import kotlin.coroutines.EmptyCoroutineContext
class DispatchersDemoVm @Inject constructor( ) : ViewModel() {
// Create a root co-routine scope
private val rootScope = CoroutineScope(EmptyCoroutineContext)
fun demo() {
rootScope.launch() {
println("Empty co-routine-context Executes on thread -> ${Thread.currentThread().name}")
}
viewModelScope.launch {
println("View-model-scope executes onExecutes on thread -> ${Thread.currentThread().name}")
}
viewModelScope.launch(Dispatchers.Main) {
println("View-model-scope + Main, executes onExecutes on thread -> ${Thread.currentThread().name}")
}
viewModelScope.launch(Dispatchers.Default) {
println("View-model-scope + Default, executes onExecutes on thread -> ${Thread.currentThread().name}")
}
viewModelScope.launch(Dispatchers.IO) {
println("View-model-scope + IO, executes onExecutes on thread -> ${Thread.currentThread().name}")
}
rootScope.launch {
viewModelScope.launch(Dispatchers.Unconfined) {
println("View-model-scope + Unconfined, executes onExecutes on thread -> ${Thread.currentThread().name}")
}
}
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/coroutines/exception_handeling/ExceptionHandlingSelectionDemo.kt
================================================
package com.istudio.app.modules.module_demos.coroutines.exception_handeling
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.navigation.NavHostController
import com.istudio.app.modules.module_selection.ModuleDemo
import com.istudio.app.ui.composables.AppButton
@Composable
fun ExceptionHandlingSelectionDemo(navController: NavHostController) {
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.height(20.dp))
AppButton(text = "Using Launch") {
navController.navigate(ModuleDemo.UsingLaunchExceptionHandleDemo.rout)
}
Spacer(modifier = Modifier.height(20.dp))
AppButton(text = "Using Async") {
navController.navigate(ModuleDemo.UsingAsyncExceptionHandleDemo.rout)
}
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/coroutines/exception_handeling/using_async/UsingAsyncExceptionHandleDemo.kt
================================================
package com.istudio.app.modules.module_demos.coroutines.exception_handeling.using_async
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.istudio.app.ui.composables.AppButton
@Composable
fun UsingAsyncExceptionHandleDemo(navController: NavHostController) {
val viewModel: UsingAsyncExceptionHandleDemoVm = hiltViewModel()
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.height(20.dp))
AppButton(text = "Demo") {
viewModel.demo()
}
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/coroutines/exception_handeling/using_async/UsingAsyncExceptionHandleDemoVm.kt
================================================
package com.istudio.app.modules.module_demos.coroutines.exception_handeling.using_async
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineName
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import javax.inject.Inject
class UsingAsyncExceptionHandleDemoVm @Inject constructor( ) : ViewModel() {
private val scopeJob = Job()
private val ourScope = CoroutineScope(scopeJob + Dispatchers.Default)
// <-----------------------> Using Exception Handler <------------------->
fun demo() {
val handler = CoroutineExceptionHandler { _, exception ->
println("Caught an exception: $exception")
}
viewModelScope.launch {
val deferredResult = async(handler) {
// Call the function that performs the asynchronous task
performAsyncTask()
}
try {
// Wait for the result of the async task
val result = deferredResult.await()
println("Async task result: $result")
} catch (e: Exception) {
// Exception will be caught by the exception handler
println("Exception caught in main: $e")
}
}
}
private suspend fun performAsyncTask(): String {
// Simulate some asynchronous work
delay(1000)
// Simulate an exception
throw RuntimeException("Simulated exception in async task")
}
// <-----------------------> Using Exception Handler <------------------->
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/coroutines/exception_handeling/using_launch/UsingLaunchExceptionHandleDemo.kt
================================================
package com.istudio.app.modules.module_demos.coroutines.exception_handeling.using_launch
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.istudio.app.ui.composables.AppButton
@Composable
fun UsingLaunchExceptionHandleDemo(navController: NavHostController) {
val viewModel: UsingLaunchExceptionHandleDemoVm = hiltViewModel()
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.height(20.dp))
AppButton(text = "No Exception Handler") {
viewModel.demo1()
}
Spacer(modifier = Modifier.height(20.dp))
AppButton(text = "Catch locally using try catch") {
viewModel.demo2()
}
Spacer(modifier = Modifier.height(20.dp))
AppButton(text = "Try to catch on external catch") {
viewModel.demo3()
}
Spacer(modifier = Modifier.height(20.dp))
AppButton(text = "Using Exception Handler") {
viewModel.demo4()
}
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/coroutines/exception_handeling/using_launch/UsingLaunchExceptionHandleDemoVm.kt
================================================
package com.istudio.app.modules.module_demos.coroutines.exception_handeling.using_launch
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineName
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import javax.inject.Inject
class UsingLaunchExceptionHandleDemoVm @Inject constructor( ) : ViewModel() {
private val scopeJob = Job()
private val ourScope = CoroutineScope(scopeJob + Dispatchers.Default)
// <-----------------------> No Exception Handler <----------------------->
fun demo1() {
ourScope.launch(CoroutineName("Parent")) {
try {
ourScope.launch(CoroutineName("Child-1")) {
try {
delay(10000)
}catch (ex : Exception){
println("Child-1 throws exception(Normal catch) ${ex.localizedMessage}")
}
}.invokeOnCompletion { throwable ->
if(throwable!=null){
// Exception thrown
println("Child-1 throws exception ${throwable.localizedMessage}")
}else{
// Normal completion of coroutine
println("Child-1 is complete")
}
}
ourScope.launch(CoroutineName("Child-2")) {
/*try {
throw RuntimeException("Child-2 throws exception")
delay(10000)
}catch (ex : Exception){
println("Child-2 throws exception(Normal catch) ${ex.localizedMessage}")
}*/
throw RuntimeException("Child-2 throws exception")
}.invokeOnCompletion{ throwable ->
if(throwable!=null){
// Exception thrown
println("Child-1 throws exception ${throwable.localizedMessage}")
}else{
// Normal completion of coroutine
println("Child-2 is complete")
}
}
}catch (ex : Exception){
println("Parent throws exception(Normal catch) ${ex.localizedMessage}")
}
// Outer delay
delay(15000)
}.invokeOnCompletion{ throwable ->
if(throwable!=null){
// Exception thrown
println("Parent throws exception ${throwable.localizedMessage}")
}else{
// Normal completion of coroutine
println("Parent is complete")
}
}
}
// <-----------------------> No Exception Handler <----------------------->
// <-----------------------> Catch locally using try catch <------------->
fun demo2() {
ourScope.launch(CoroutineName("Parent")) {
try {
ourScope.launch(CoroutineName("Child-1")) {
try {
delay(10000)
}catch (ex : Exception){
println("Child-1 throws exception(Normal catch) ${ex.localizedMessage}")
}
}.invokeOnCompletion { throwable ->
if(throwable!=null){
// Exception thrown
println("Child-1 throws exception ${throwable.localizedMessage}")
}else{
// Normal completion of coroutine
println("Child-1 is complete")
}
}
ourScope.launch(CoroutineName("Child-2")) {
try {
throw RuntimeException("Child-2 throws exception")
delay(10000)
}catch (ex : Exception){
println("Child-2 throws exception(Normal catch) ${ex.localizedMessage}")
}
}.invokeOnCompletion{ throwable ->
if(throwable!=null){
// Exception thrown
println("Child-1 throws exception ${throwable.localizedMessage}")
}else{
// Normal completion of coroutine
println("Child-2 is complete")
}
}
}catch (ex : Exception){
println("Parent throws exception(Normal catch) ${ex.localizedMessage}")
}
// Outer delay
delay(15000)
}.invokeOnCompletion{ throwable ->
if(throwable!=null){
// Exception thrown
println("Parent throws exception ${throwable.localizedMessage}")
}else{
// Normal completion of coroutine
println("Parent is complete")
}
}
}
// <-----------------------> Catch locally using try catch <------------->
// <-----------------------> Try to catch on external catch <------------>
fun demo3() {
ourScope.launch(CoroutineName("Parent")) {
try {
ourScope.launch(CoroutineName("Child-1")) {
try {
delay(10000)
}catch (ex : Exception){
println("Child-1 throws exception(Normal catch) ${ex.localizedMessage}")
}
}.invokeOnCompletion { throwable ->
if(throwable!=null){
// Exception thrown
println("Child-1 throws exception ${throwable.localizedMessage}")
}else{
// Normal completion of coroutine
println("Child-1 is complete")
}
}
try {
ourScope.launch(CoroutineName("Child-2")) {
throw RuntimeException("Child-2 throws exception")
delay(10000)
}.invokeOnCompletion{ throwable ->
if(throwable!=null){
// Exception thrown
println("Child-1 throws exception ${throwable.localizedMessage}")
}else{
// Normal completion of coroutine
println("Child-2 is complete")
}
}
}catch (ex : Exception){
println("Child-2 throws exception(Outer normal catch) ${ex.localizedMessage}")
}
}catch (ex : Exception){
println("Parent throws exception(Normal catch) ${ex.localizedMessage}")
}
// Outer delay
delay(15000)
}.invokeOnCompletion{ throwable ->
if(throwable!=null){
// Exception thrown
println("Parent throws exception ${throwable.localizedMessage}")
}else{
// Normal completion of coroutine
println("Parent is complete")
}
}
}
// <-----------------------> Try to catch on external catch <------------>
// <-----------------------> Using Exception Handler <------------------->
fun demo4() {
val handler = CoroutineExceptionHandler { _, exception ->
println("Caught an exception: $exception")
}
ourScope.launch(CoroutineName("Parent")) {
try {
ourScope.launch(CoroutineName("Child-1")) {
try {
delay(10000)
}catch (ex : Exception){
println("Child-1 throws exception(Normal catch) ${ex.localizedMessage}")
}
}.invokeOnCompletion { throwable ->
if(throwable!=null){
// Exception thrown
println("Child-1 throws exception ${throwable.localizedMessage}")
}else{
// Normal completion of coroutine
println("Child-1 is complete")
}
}
try {
ourScope.launch(CoroutineName("Child-2") + handler) {
throw RuntimeException("Child-2 throws exception")
delay(10000)
}.invokeOnCompletion{ throwable ->
if(throwable!=null){
// Exception thrown
println("Child-1 throws exception ${throwable.localizedMessage}")
}else{
// Normal completion of coroutine
println("Child-2 is complete")
}
}
}catch (ex : Exception){
println("Child-2 throws exception(Outer normal catch) ${ex.localizedMessage}")
}
}catch (ex : Exception){
println("Parent throws exception(Normal catch) ${ex.localizedMessage}")
}
// Outer delay
delay(15000)
}.invokeOnCompletion{ throwable ->
if(throwable!=null){
// Exception thrown
println("Parent throws exception ${throwable.localizedMessage}")
}else{
// Normal completion of coroutine
println("Parent is complete")
}
}
}
// <-----------------------> Using Exception Handler <------------------->
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/coroutines/job/JobDemoSelection.kt
================================================
package com.istudio.app.modules.module_demos.coroutines.job
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.istudio.app.ui.composables.AppButton
@Composable
fun JobDemoSelection(navController: NavHostController) {
val viewModel: JobDemoSelectionVm = hiltViewModel()
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.height(20.dp))
AppButton(text = "Demo") {
viewModel.demo()
}
Spacer(modifier = Modifier.height(20.dp))
AppButton(text = "Cancel-Root") {
viewModel.rootCancel()
}
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/coroutines/job/JobDemoSelectionVm.kt
================================================
package com.istudio.app.modules.module_demos.coroutines.job
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineName
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject
class JobDemoSelectionVm @Inject constructor( ) : ViewModel() {
private val scopeJob = Job()
private val ourScope = CoroutineScope(scopeJob + Dispatchers.Default)
fun demo() {
try {
ourScope.launch(CoroutineName("GrandParent")) {
try {
parent1Block()
parent2Block()
}catch (ex:Exception){
println("Exception caught inside GrandParent scope")
}
}.invokeOnCompletion {
println("GrandParent invokeOnCompletion triggered")
}
}catch (ex:Exception){
println("Exception caught outside GrandParent scope")
}
}
private fun parent1Block(){
try {
ourScope.launch(CoroutineName("Parent-1")) {
try {
parent1Child1Block()
parent1Child2Block()
}catch (ex:Exception){
println("Exception caught inside Parent-1 scope")
}
}.invokeOnCompletion {
println("Parent-1 invokeOnCompletion triggered")
}
}catch (ex:Exception){
println("Exception caught outside Parent-1 scope")
}
}
private fun parent2Block(){
try {
ourScope.launch(CoroutineName("Parent-2")) {
try {
parent2Child1Block()
parent2Child2Block()
}catch (ex:Exception){
println("Exception caught inside Parent-2 scope")
}
}.invokeOnCompletion {
println("Parent-2 invokeOnCompletion triggered")
}
}catch (ex:Exception){
println("Exception caught outside Parent-2 scope")
}
}
private fun parent1Child1Block(){
try {
ourScope.launch(CoroutineName("Parent-1-child-1")) {
try {
repeat(10){
println("Parent-1-child-1 ------------------>$it")
delay(1000)
}
}catch (ex:Exception){
println("Exception caught inside Parent-1-child-1 scope")
}
}.invokeOnCompletion {
println("Parent-1-child-1 invokeOnCompletion triggered")
}
}catch (ex:Exception){
println("Exception caught outside Parent-1-child-1 scope")
}
}
private fun parent1Child2Block(){
try {
ourScope.launch(CoroutineName("Parent-1-child-2")) {
try {
repeat(10){
println("Parent-1-child-2 ------------------>$it")
delay(1000)
}
}catch (ex:Exception){
println("Exception caught inside Parent-1-child-2 scope")
}
}.invokeOnCompletion {
println("Parent-1-child-2 invokeOnCompletion triggered")
}
}catch (ex:Exception){
println("Exception caught outside Parent-1-child-2 scope")
}
}
private fun parent2Child1Block(){
try {
ourScope.launch(CoroutineName("Parent-2-child-1")) {
try {
repeat(10){
println("Parent-2-child-1 ------------------>$it")
delay(1000)
}
}catch (ex:Exception){
println("Exception caught inside Parent-2-child-1 scope")
}
}.invokeOnCompletion {
println("Parent-2-child-1 invokeOnCompletion triggered")
}
}catch (ex:Exception){
println("Exception caught outside Parent-2-child-1 scope")
}
}
private fun parent2Child2Block(){
try {
ourScope.launch(CoroutineName("Parent-2-child-2")) {
try {
repeat(10){
println("Parent-2-child-2 ------------------>$it")
delay(1000)
}
}catch (ex:Exception){
println("Exception caught inside Parent-2-child-2 scope")
}
}.invokeOnCompletion {
println("Parent-2-child-2 invokeOnCompletion triggered")
}
}catch (ex:Exception){
println("Exception caught outside Parent-2-child-2 scope")
}
}
fun rootCancel() {
scopeJob?.cancel()
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/coroutines/launch_and_withcontext/LaunchAndWithContextDemo.kt
================================================
package com.istudio.app.modules.module_demos.coroutines.launch_and_withcontext
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.istudio.app.ui.composables.AppButton
import com.istudio.app.ui.composables.AppText
@Composable
fun LaunchAndWithContextDemo(navController: NavHostController) {
val viewModel: LaunchAndWithContextDemoVm = hiltViewModel()
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.height(20.dp))
AppButton(text = "Demo") {
viewModel.demo()
}
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/coroutines/launch_and_withcontext/LaunchAndWithContextDemoVm.kt
================================================
package com.istudio.app.modules.module_demos.coroutines.launch_and_withcontext
import androidx.lifecycle.ViewModel
import com.istudio.app.utils.extensions.printCoroutineScopeInfo
import kotlinx.coroutines.CoroutineName
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.cancel
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.concurrent.CancellationException
import javax.inject.Inject
class LaunchAndWithContextDemoVm @Inject constructor( ) : ViewModel() {
// Create a root co-routine scope
private val rootScope = CoroutineScope(
Dispatchers.Main + CoroutineName("Root-Coroutine")
)
private val childScope = CoroutineScope(
Dispatchers.Main + CoroutineName("Child-Coroutine")
)
fun demo() = rootScope.launch {
printCoroutineScopeInfo()
childScope.launch {
printCoroutineScopeInfo()
val result = withContext(Dispatchers.Main + CoroutineName("Child-nested-Coroutine")){
printCoroutineScopeInfo()
100
}
println("Returned value $result")
}
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/coroutines/simple_structured_concurrency/SimpleStructuredConcurrencyDemo.kt
================================================
package com.istudio.app.modules.module_demos.coroutines.simple_structured_concurrency
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Shapes
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.istudio.app.ui.composables.AppButton
import com.istudio.app.ui.composables.AppText
@Composable
fun SimpleStructuredConcurrencyDemo(navController: NavHostController) {
val viewModel: SimpleStructuredConcurrencyDemoVm = hiltViewModel()
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
AppText(text = "Co-Routines")
Spacer(modifier = Modifier.height(20.dp))
AppButton(text = "Start nested \n Independent Co-routines") {
viewModel.startNestedIndependentCoroutines()
}
Spacer(modifier = Modifier.height(5.dp))
AppButton(text = "Start nested \n Linked Co-routines") {
viewModel.startNestedLinkedCoroutines()
}
Spacer(modifier = Modifier.height(20.dp))
AppButton(text = "Start nested \n Linked Co-routines \n with join") {
viewModel.startNestedChildrenCoroutines()
}
Spacer(modifier = Modifier.height(20.dp))
AppButton(text = "CANCEL") {
viewModel.cancel()
}
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/coroutines/simple_structured_concurrency/SimpleStructuredConcurrencyDemoVm.kt
================================================
package com.istudio.app.modules.module_demos.coroutines.simple_structured_concurrency
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.cancel
import kotlinx.coroutines.cancelChildren
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.concurrent.CancellationException
import javax.inject.Inject
class SimpleStructuredConcurrencyDemoVm @Inject constructor( ) : ViewModel() {
// Create a root co-routine scope
private val rootScope = CoroutineScope(Dispatchers.Default)
fun startNestedIndependentCoroutines() {
// Launch a co-routine within the scope
rootScope.launch {
println("Start outer coroutine")
// Create a nested co-routine scope
val nestedScope = CoroutineScope(Dispatchers.Default)
// Launch a new co-routine within the nested scope
nestedScope.launch {
println("Start inner coroutine")
delay(10000) // Observe we keep delay longer here than the outer delay
println("End inner coroutine")
}
delay(5000) // Observe we have kept outer delay lesser than inner delay
println("End outer coroutine")
}
}
fun startNestedLinkedCoroutines() {
// Launch a co-routine within the scope
rootScope.launch {
println("Start outer coroutine")
// Launch a new co-routine within the nested scope
launch {
println("Start inner coroutine")
delay(10000) // Observe we keep delay longer here than the outer delay
println("End inner coroutine")
}
delay(5000) // Observe we have kept outer delay lesser than inner delay
println("End outer coroutine")
}
}
fun startNestedChildrenCoroutines() {
// Launch a co-routine within the scope
rootScope.launch {
println("Start outer coroutine")
// Launch a new co-routine within the nested scope
launch {
println("Start inner coroutine-1")
delay(10000) // Observe we keep delay longer here than the outer delay
println("End inner coroutine-1")
}.join()
launch {
println("Start inner coroutine-2")
delay(10000) // Observe we keep delay longer here than the outer delay
println("End inner coroutine-2")
}.join()
println("End outer coroutine")
}
}
fun cancel() {
println("User invokes cancel")
rootScope.cancel(cause = CancellationException("Cancelled explicitly by user"))
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/coroutines/suspend_and_launch_demo/NonCancellableDemoVm.kt
================================================
package com.istudio.app.modules.module_demos.coroutines.suspend_and_launch_demo
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.delay
import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject
import kotlin.coroutines.cancellation.CancellationException
import kotlin.coroutines.coroutineContext
class NonCancellableDemoVm @Inject constructor() : ViewModel() {
private var job: Job? = null
fun startTwoCoroutines() {
// Start a root coroutine
job = CoroutineScope(Dispatchers.IO).launch {
// Start a coroutine-1
launch {
coRoutineOne(1)
}
// Start a coroutine-2
launch {
coRoutineOne(2)
}
}
}
fun startTwoSuspendFunctions() {
// Start a coroutine
job = CoroutineScope(Dispatchers.IO).launch {
// Start a suspend function-1
coRoutineOne(1)
// Start a suspend function-2
coRoutineOne(2)
}
}
private suspend fun coRoutineOne(coroutineNo: Int) {
try {
repeat(10) { index ->
delay(500)
// Check if the coroutine has been canceled
if (!coroutineContext.isActive) {
println("Coroutine-No:$coroutineNo canceled at index $index")
} else {
// Continue with the main logic
println("Coroutine-No:$coroutineNo Working at index $index")
}
}
// Additional logic after the loop
println("Coroutine-No:$coroutineNo completed")
} catch (e: CancellationException) {
// Handle cancellation-specific tasks
println("Coroutine-No:$coroutineNo canceled")
}
}
fun cancel() {
job?.cancel()
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/coroutines/suspend_and_launch_demo/SuspendAndLaunchDemo.kt
================================================
package com.istudio.app.modules.module_demos.coroutines.suspend_and_launch_demo
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.material3.Button
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.istudio.app.ui.composables.AppButton
@Composable
fun SuspendAndLaunchDemo(navController: NavHostController){
val viewModel: NonCancellableDemoVm = hiltViewModel()
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.height(100.dp))
AppButton(text = "Start \n 2 co-routines") {
viewModel.startTwoCoroutines()
}
Spacer(modifier = Modifier.height(100.dp))
AppButton(text = "Start \n 2 suspend-functions") {
viewModel.startTwoSuspendFunctions()
}
Spacer(modifier = Modifier.height(100.dp))
Button(
modifier = Modifier
.background(
color = MaterialTheme.colorScheme.primary,
shape = RectangleShape
),
onClick = {
viewModel.cancel()
}
) {
Text(text = "Cancel")
}
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/coroutines/using_async_await/UsingAsyncAwaitDemo.kt
================================================
package com.istudio.app.modules.module_demos.coroutines.using_async_await
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.istudio.app.ui.composables.AppButton
@Composable
fun UsingAsyncAwaitDemo(navController: NavHostController) {
val viewModel: UsingAsyncAwaitDemoVm = hiltViewModel()
Column(
modifier = Modifier
.fillMaxSize()
.verticalScroll(rememberScrollState()),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
) {
Spacer(modifier = Modifier.height(20.dp))
AppButton(text = "Demo") {
viewModel.demo()
}
Spacer(modifier = Modifier.height(20.dp))
AppButton(text = "Cancel-Root") {
viewModel.rootCancel()
}
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/coroutines/using_async_await/UsingAsyncAwaitDemoVm.kt
================================================
package com.istudio.app.modules.module_demos.coroutines.using_async_await
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.CoroutineName
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import javax.inject.Inject
class UsingAsyncAwaitDemoVm @Inject constructor( ) : ViewModel() {
private val scopeJob = Job()
private val ourScope = CoroutineScope(scopeJob + Dispatchers.Default)
fun demo() {
try {
ourScope.launch(CoroutineName("GrandParent")) {
val endResult = (1..15).toList().map { inputValue ->
async {
delay(100)
inputValue
}
}.awaitAll().sum()
println("Final Result:-> $endResult")
}
}catch (ex:Exception){
println("Exception caught outside GrandParent scope")
}
}
fun rootCancel() {
scopeJob?.cancel()
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/coroutines/using_join/UsingJoinDemo.kt
================================================
package com.istudio.app.modules.module_demos.coroutines.using_join
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.istudio.app.ui.composables.AppButton
@Composable
fun UsingJoinDemo(navController: NavHostController) {
val viewModel: UsingJoinDemoVm = hiltViewModel()
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.height(20.dp))
AppButton(text = "Demo") {
viewModel.demo()
}
Spacer(modifier = Modifier.height(20.dp))
AppButton(text = "Cancel-Root") {
viewModel.rootCancel()
}
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/coroutines/using_join/UsingJoinDemoVm.kt
================================================
package com.istudio.app.modules.module_demos.coroutines.using_join
import androidx.lifecycle.ViewModel
import kotlinx.coroutines.CoroutineName
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import javax.inject.Inject
class UsingJoinDemoVm @Inject constructor( ) : ViewModel() {
private val scopeJob = Job()
private val ourScope = CoroutineScope(scopeJob + Dispatchers.Default)
fun demo() {
try {
ourScope.launch(CoroutineName("GrandParent")) {
try {
parent1Block().join()
parent2Block().join()
println("Both parent code blocks are completed")
}catch (ex:Exception){
println("Exception caught inside GrandParent scope")
}
}.invokeOnCompletion {
println("GrandParent invokeOnCompletion triggered")
}
}catch (ex:Exception){
println("Exception caught outside GrandParent scope")
}
}
private suspend fun parent1Block() = ourScope.launch(CoroutineName("Parent-1")) {
try {
repeat(10){
println("Parent-1 ----- tick ----->$it")
delay(1000)
}
}catch (ex:Exception){
println("Exception caught inside Parent-1 coroutine")
}
}
private suspend fun parent2Block() = ourScope.launch(CoroutineName("Parent-2")) {
try {
parent2Child1Block().join()
println("Parent-2-Child-1 block is completed")
repeat(10){
println("Parent-2-Child-1 ----- tick ----->$it")
delay(1000)
}
}catch (ex:Exception){
println("Exception caught inside Parent-2 coroutine")
}
}
private suspend fun parent2Child1Block() = ourScope.launch(CoroutineName("Parent-2-Child-1")) {
try {
repeat(10){
println("Parent-2-Child-1 ----- tick ----->$it")
delay(1000)
}
}catch (ex:Exception){
println("Exception caught inside Parent-2-Child-1 coroutine")
}
}
fun rootCancel() {
scopeJob?.cancel()
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/flows/FlowsDemo.kt
================================================
package com.istudio.app.modules.module_demos.flows
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.istudio.app.modules.module_selection.ModuleDemo
import com.istudio.app.ui.composables.AppButton
@Composable
fun FlowsDemo (navController: NavHostController) {
val viewModel: FlowsDemoVm = hiltViewModel()
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Flow basics", onClick = {
navController.navigate(ModuleDemo.FlowBasics.rout)
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Terminal Operators", onClick = {
// New composable is launched
navController.navigate(ModuleDemo.TerminalOperators.rout)
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Intermediate Operators", onClick = {
// New composable is launched
navController.navigate(ModuleDemo.IntermediateOperators.rout)
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Composing and Flattening the flows", onClick = {
navController.navigate(ModuleDemo.ComposingAndFlatteningTheFlows.rout)
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "State And Shared Flow", onClick = {
navController.navigate(ModuleDemo.StateAndSharedFlowDemo.rout)
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Mutable State of Flow Demo", onClick = {
navController.navigate(ModuleDemo.MutableStateOfFlowDemo.rout)
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Flatten Flows", onClick = {
navController.navigate(ModuleDemo.FlattenFlowsDemo.rout)
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Collect As State With Life Cycle", onClick = {
navController.navigate(ModuleDemo.CollectAsStateWithLifeCycle.rout)
})
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/flows/FlowsDemoVm.kt
================================================
package com.istudio.app.modules.module_demos.flows
import androidx.lifecycle.ViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@HiltViewModel
class FlowsDemoVm @Inject constructor( ) : ViewModel() {
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/flows/modules/collect_as_state_with_lifecycle/CollectAsStateWithLifeCycleDemo.kt
================================================
package com.istudio.app.modules.module_demos.flows.modules.collect_as_state_with_lifecycle
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavHostController
import com.istudio.app.ui.composables.AppButton
import kotlinx.coroutines.launch
@Composable
fun CollectAsStateWithLifeCycleDemo(navController: NavHostController){
val viewModel: CollectAsStateWithLifeCycleVm = hiltViewModel()
//val time = viewModel.data.collectAsStateWithLifecycle()
//val time = viewModel.newTimer.collectAsStateWithLifecycle()
val time: Int by viewModel.data.collectAsStateWithLifecycle()
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.height(16.dp))
Text(
text = time.toString(),
fontSize = 30.sp
)
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/flows/modules/collect_as_state_with_lifecycle/CollectAsStateWithLifeCycleVm.kt
================================================
package com.istudio.app.modules.module_demos.flows.modules.collect_as_state_with_lifecycle
import android.content.Context
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class CollectAsStateWithLifeCycleVm @Inject constructor(
@ApplicationContext private val context: Context,
) : ViewModel() {
companion object {
const val INITIAL_VALUE = 0
}
private var currentTime = INITIAL_VALUE
private val _data = MutableStateFlow(0)
val data = _data.asStateFlow()
init {
initiate()
}
private fun initiate() {
viewModelScope.launch {
while(true){
delay(1000L)
println("Flow is active current time ---> $currentTime")
_data.emit(currentTime++)
}
}
}
val newTimer = flow {
while(true){
delay(1000L)
println("Flow is active current time ---> $currentTime")
emit(currentTime++)
}
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000L),0)
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/flows/modules/compose_and_flatten_flows/ComposeAndFlattenFlows.kt
================================================
package com.istudio.app.modules.module_demos.flows.modules.compose_and_flatten_flows
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.istudio.app.ui.composables.AppButton
import com.istudio.app.ui.composables.AppText
@Composable
fun ComposeAndFlattenFlows(navController: NavHostController){
val viewModel: ComposeAndFlattenFlowsVm = hiltViewModel()
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Buffering", onClick = { viewModel.buffering() })
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Conflating", onClick = { viewModel.conflating() })
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Collect Latest", onClick = { viewModel.collectLatest() })
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Zipping", onClick = { viewModel.zipping() })
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Combining", onClick = { viewModel.combining() })
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/flows/modules/compose_and_flatten_flows/ComposeAndFlattenFlowsVm.kt
================================================
package com.istudio.app.modules.module_demos.flows.modules.compose_and_flatten_flows
import android.content.Context
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.buffer
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.lastOrNull
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.singleOrNull
import kotlinx.coroutines.flow.take
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.flow.toSet
import kotlinx.coroutines.flow.zip
import kotlinx.coroutines.launch
import javax.inject.Inject
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.system.measureTimeMillis
@HiltViewModel
class ComposeAndFlattenFlowsVm @Inject constructor(
@ApplicationContext private val context: Context,
) : ViewModel() {
/** *********************** Buffering *********************** **/
private val bufferDemoFlow = flow {
// Make 10 emissions in iteration
repeat(10){
// Give some delay
delay(50)
println("Emission -> $it")
emit(it)
}
}.flowOn(Dispatchers.Default)
fun buffering() = viewModelScope.launch{
// It will show the time taken to execute this block of code
val time = measureTimeMillis {
bufferDemoFlow.buffer(5).collect {
delay(100)
println("Collection -> $it")
}
}
println("Time Taken:-> $time")
}
/** *********************** Buffering *********************** **/
/** *********************** Conflating *********************** **/
private val conflatingDemoFlow = flow {
// Make 10 emissions in iteration
repeat(10){
// Give some delay
println("Emission -> $it")
emit(it)
}
}.flowOn(Dispatchers.Default)
fun conflating() = viewModelScope.launch{
// It will show the time taken to execute this block of code
val time = measureTimeMillis {
conflatingDemoFlow.take(5).conflate().collect {
delay(100)
println("Collection -> $it")
}
}
println("Time Taken:-> $time")
}
/** *********************** Conflating *********************** **/
/** *********************** Collect Latest ******************* **/
private val collectLatestDemoFlow = flow {
// Make 10 emissions in iteration
repeat(3){
// Give some delay
println("Emission -> $it")
emit(it)
}
}.flowOn(Dispatchers.Default)
fun collectLatest() = viewModelScope.launch{
// It will show the time taken to execute this block of code
val time = measureTimeMillis {
collectLatestDemoFlow.collectLatest {
println("Processing emission -> $it")
delay(1000)
println("Processed emission -> $it")
}
}
println("Time Taken:-> $time")
}
/** *********************** Collect Latest ******************* **/
/** *********************** Zipping ************************** **/
private val flowOne = flow {
emit("x")
emit("y")
emit("z")
}.flowOn(Dispatchers.Default)
private val flowTwo = flow {
emit("x")
emit("y")
emit("z")
}.flowOn(Dispatchers.Default)
fun zipping() = viewModelScope.launch{
// It will show the time taken to execute this block of code
val time = measureTimeMillis {
flowOne.zip(flowTwo){ one , two ->
one+two
}.collect{
println("Result:-> $it")
}
}
println("Time Taken:-> $time")
}
/** *********************** Zipping ************************** **/
/** *********************** Combining ************************ **/
private val flowCombineOne = flow {
emit("x")
delay(5000)
emit("y")
emit("z")
}.flowOn(Dispatchers.Default)
private val flowCombineTwo = flow {
emit("x")
emit("y")
emit("z")
}.flowOn(Dispatchers.Default)
fun combining() = viewModelScope.launch{
// It will show the time taken to execute this block of code
val time = measureTimeMillis {
flowCombineOne.combine(flowCombineTwo){ one , two ->
one+two
}.collect{
println("Result:-> $it")
}
}
println("Time Taken:-> $time")
}
/** *********************** Combining ************************ **/
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/flows/modules/flatten_flows/FlattenFlowsDemo.kt
================================================
package com.istudio.app.modules.module_demos.flows.modules.flatten_flows
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.istudio.app.ui.composables.AppButton
import com.istudio.app.ui.composables.AppText
@Composable
fun FlattenFlowsDemo(navController: NavHostController){
val viewModel: FlattenFlowsDemoVm = hiltViewModel()
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.height(16.dp))
AppText(text = "Flattening")
AppButton(text = "FlatMapConcat", onClick = { viewModel.flatMapConcat() })
Spacer(modifier = Modifier.height(10.dp))
AppButton(text = "FlatMapMerge", onClick = { viewModel.flatMapMerge() })
Spacer(modifier = Modifier.height(10.dp))
AppButton(text = "FlatMapLatest", onClick = { viewModel.flatMaplatest() })
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/flows/modules/flatten_flows/FlattenFlowsDemoVm.kt
================================================
package com.istudio.app.modules.module_demos.flows.modules.flatten_flows
import android.content.Context
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.CoroutineName
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.flatMapConcat
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flatMapMerge
import kotlinx.coroutines.flow.flattenConcat
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.lastOrNull
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.singleOrNull
import kotlinx.coroutines.flow.take
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.flow.toSet
import kotlinx.coroutines.launch
import javax.inject.Inject
import kotlin.coroutines.EmptyCoroutineContext
@HiltViewModel
class FlattenFlowsDemoVm @Inject constructor(
@ApplicationContext private val context: Context,
) : ViewModel() {
private val rootScope = CoroutineScope(context = Dispatchers.IO)
/**
* Flow of integers
*/
fun generateIntegers() = flow {
repeat(100){
delay(1000)
emit(it)
}
}
/**
* Generate a flow of strings
*/
fun generateFlowOfStrings(value : Int) = flow {
val content = "Current string no -->$value at the thread${Thread.currentThread().name}"
println(" -->$value")
emit(content)
}
fun flatMapConcat() = rootScope.launch(CoroutineName("FlatMapConcatDemo")){
// Way-1
/* val result : Flow> = generateIntegers()
.take(5)
.map {
generateFlowOfStrings(it)
}
result.flattenConcat().collect{
println(it)
}*/
//Way-2
generateIntegers()
.take(5)
.flatMapConcat {
generateFlowOfStrings(it)
}.collect{
println(it)
}
}
fun flatMapMerge() = rootScope.launch(CoroutineName("flatMapMerge")){
generateIntegers()
.take(5)
.flatMapMerge() {
generateFlowOfStrings(it)
}.collect{
println(it)
}
}
fun flatMaplatest() = rootScope.launch(CoroutineName("flatMapLatest")){
generateIntegers()
.take(5)
.flatMapLatest {
generateFlowOfStrings(it)
}.collect{
delay(2000)
println("collected: ---> $it")
}
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/flows/modules/flow_basics/chapters/display_data_from_server/DisplayDataFromServerDemo.kt
================================================
package com.istudio.app.modules.module_demos.flows.modules.flow_basics.chapters.display_data_from_server
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.grid.rememberLazyGridState
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.istudio.app.modules.module_demos.flows.modules.flow_basics.chapters.display_data_from_server.composables.StockItem
import com.istudio.app.modules.module_demos.flows.modules.flow_basics.state.UiState
import com.istudio.app.modules.module_demos.flows.modules.flow_basics.ui.FlowBasicsVm
import com.istudio.app.ui.composables.AppButton
@Composable
fun DisplayDataFromServerDemo(navController: NavHostController){
//
// View model reference
val viewModel: DisplayDataFromServerVm = hiltViewModel()
// View state reference from view model
val stockList = viewModel.viewState.value.stockList
val isLoading = viewModel.viewState.value.isLoading
val error = viewModel.viewState.value.error
//
// LaunchedEffect will run the provided block when the composition is first committed
LaunchedEffect(true){
// This is called only once
viewModel.getDataFromServerUsingCollect()
}
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
if(isLoading){
// Display a loading indicator
CircularProgressIndicator(
modifier = Modifier.width(64.dp),
color = MaterialTheme.colorScheme.secondary,
trackColor = MaterialTheme.colorScheme.surfaceVariant,
)
}else{
// Either data is there or, there can be error
if(!error.isError){
// Error is not there ---> Display the data
LazyColumn(
modifier = Modifier.background(color = MaterialTheme.colorScheme.background),
state = rememberLazyListState(),
contentPadding = PaddingValues(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
){
items(
count = stockList.size,
key = {
stockList[it].id
},
itemContent = {
StockItem(data = stockList[it])
}
)
}
}else{
// Error is there
Text(text = error.errorMessage)
}
}
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/flows/modules/flow_basics/chapters/display_data_from_server/DisplayDataFromServerVm.kt
================================================
package com.istudio.app.modules.module_demos.flows.modules.flow_basics.chapters.display_data_from_server
import android.content.Context
import android.util.Log
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.istudio.app.modules.module_demos.flows.modules.flow_basics.data.StockData
import com.istudio.app.modules.module_demos.flows.modules.flow_basics.state.UiError
import com.istudio.app.modules.module_demos.flows.modules.flow_basics.state.UiState
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class DisplayDataFromServerVm @Inject constructor(
@ApplicationContext private val context: Context,
) : ViewModel() {
var viewState: MutableState = mutableStateOf(UiState())
fun getDataFromServerUsingCollect() {
viewModelScope.launch {
StockData.getData(context)
.map { stockList ->
// We converted data from one form to another - Here UiState
viewState.value = viewState.value.copy(
error = UiError(errorMessage = "", isError = false),
stockList = stockList
)
}.onStart {
// We indicate the UI will start loading
viewState.value = viewState.value.copy(
error = UiError(errorMessage = "", isError = false),
isLoading = true
)
}.catch { error ->
// Emit the error if the error is found
viewState.value = viewState.value.copy(
error = UiError(errorMessage = error.localizedMessage, isError = true)
)
}.onCompletion {
// This indicates flow is completed
Log.d("Flow","Flow has completed.")
viewState.value = viewState.value.copy(
error = UiError(errorMessage = "", isError = false),
isLoading = false
)
}.collect()
}
}
fun getDataFromServerUsingLaunchIn() {
viewModelScope.launch {
StockData.getData(context)
.onEach { stockList ->
// We converted data from one form to another - Here UiState
viewState.value = viewState.value.copy(
error = UiError(errorMessage = "", isError = false),
stockList = stockList
)
}.onStart {
// We indicate the UI will start loading
viewState.value = viewState.value.copy(
error = UiError(errorMessage = "", isError = false),
isLoading = true
)
}.catch { error ->
// Emit the error if the error is found
viewState.value = viewState.value.copy(
error = UiError(errorMessage = error.localizedMessage, isError = true)
)
}.onCompletion {
// This indicates flow is completed
Log.d("Flow","Flow has completed.")
viewState.value = viewState.value.copy(
error = UiError(errorMessage = "", isError = false),
isLoading = false
)
}.launchIn(viewModelScope)
}
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/flows/modules/flow_basics/chapters/display_data_from_server/composables/StockItem.kt
================================================
package com.istudio.app.modules.module_demos.flows.modules.flow_basics.chapters.display_data_from_server.composables
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.CornerSize
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.CardElevation
import androidx.compose.material3.MaterialTheme.typography
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import com.istudio.app.R
import com.istudio.app.data.mock.Stock
@Composable
fun StockItem(data : Stock){
Card(
modifier = Modifier
.padding(horizontal = 8.dp, vertical = 8.dp)
.fillMaxWidth(),
elevation = CardDefaults.cardElevation(2.dp),
shape = RoundedCornerShape(corner = CornerSize(16.dp))
) {
Row(
modifier = Modifier.fillMaxSize().padding(10.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
Image(
painter = painterResource(id = R.mipmap.ic_launcher),
contentDescription = "Data Image")
Column(
modifier = Modifier
.padding(16.dp)
.fillMaxWidth()
.align(Alignment.CenterVertically)) {
Text(text = data.name, style = typography.bodyLarge)
Text(text = data.country, style = typography.bodyMedium)
Text(text = data.currentPrice.toString(), style = typography.bodySmall)
}
}
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/flows/modules/flow_basics/data/StockData.kt
================================================
package com.istudio.app.modules.module_demos.flows.modules.flow_basics.data
import android.content.Context
import com.istudio.app.data.mock.Stock
import com.istudio.app.modules.module_demos.flows.modules.flow_basics.data.api.mockApi
import kotlinx.coroutines.flow.Flow
object StockData {
suspend fun getData(context : Context): Flow> {
return NetworkStockPriceDataSource(mockApi(context)).getLatestStockList()
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/flows/modules/flow_basics/data/StockPriceDataSource.kt
================================================
package com.istudio.app.modules.module_demos.flows.modules.flow_basics.data
import android.util.Log
import com.istudio.app.data.mock.FlowMockApi
import com.istudio.app.data.mock.Stock
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.flow
interface StockPriceDataSource {
suspend fun getLatestStockList() : Flow>
}
class NetworkStockPriceDataSource(val mockApi: FlowMockApi) : StockPriceDataSource {
override suspend fun getLatestStockList(): Flow> = flow {
emit(mockApi.getCurrentStockPrices())
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/flows/modules/flow_basics/data/api/MockApiBehavior.kt
================================================
package com.istudio.app.modules.module_demos.flows.modules.flow_basics.data.api
import android.content.Context
import com.google.gson.Gson
import com.istudio.app.data.mock.MockNetworkInterceptor
import com.istudio.app.data.mock.createFlowMockApi
import com.istudio.app.data.mock.fakeCurrentStockPrices
fun mockApi(context: Context) =
createFlowMockApi(
MockNetworkInterceptor()
.mock(
path = "/current-stock-prices",
body = { Gson().toJson(fakeCurrentStockPrices(context)) },
status = 200,
delayInMs = 1500,
)
)
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/flows/modules/flow_basics/state/UiState.kt
================================================
package com.istudio.app.modules.module_demos.flows.modules.flow_basics.state
import com.istudio.app.data.mock.Stock
data class UiState(
val isLoading: Boolean = false,
val stockList: List = emptyList(),
val error: UiError = UiError()
)
data class UiError(
val errorMessage: String = "",
val isError: Boolean = false
)
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/flows/modules/flow_basics/ui/FlowBasics.kt
================================================
package com.istudio.app.modules.module_demos.flows.modules.flow_basics.ui
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.istudio.app.modules.module_selection.ModuleDemo
import com.istudio.app.ui.composables.AppButton
import com.istudio.app.ui.composables.AppText
@Composable
fun FlowBasics(navController: NavHostController){
val viewModel: FlowBasicsVm = hiltViewModel()
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Flow Builders", onClick = {
viewModel.flowBuilders()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Flow into Mutable State Flow ", onClick = {
// New composable is launched
navController.navigate(ModuleDemo.DisplayDataFromServer.rout)
})
Spacer(modifier = Modifier.height(16.dp))
AppText(text = "Stopping Flow - Demo")
AppButton(text = "Start", onClick = {
viewModel.stoppingFlowDemoStart()
})
Spacer(modifier = Modifier.height(5.dp))
AppButton(text = "Cancel", onClick = {
viewModel.invokeCancel()
})
Spacer(modifier = Modifier.height(5.dp))
AppButton(text = "Flow Context", onClick = {
viewModel.flowContextDemo()
})
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/flows/modules/flow_basics/ui/FlowBasicsVm.kt
================================================
package com.istudio.app.modules.module_demos.flows.modules.flow_basics.ui
import android.content.Context
import android.util.Log
import androidx.compose.runtime.MutableState
import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.asLiveData
import androidx.lifecycle.viewModelScope
import com.istudio.app.modules.module_demos.flows.modules.flow_basics.data.StockData
import com.istudio.app.modules.module_demos.flows.modules.flow_basics.data.StockPriceDataSource
import com.istudio.app.modules.module_demos.flows.modules.flow_basics.state.UiState
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject
@HiltViewModel
class FlowBasicsVm @Inject constructor(
@ApplicationContext private val context: Context,
) : ViewModel() {
/**
* FLOW builders in kotlin
*/
fun flowBuilders() {
viewModelScope.launch {
// Builder: FlowOf ---> Just one value
val demo1 = flowOf(10)
// Builder: FlowOf ---> Multiple values
val demo2 = flowOf("x","y","z")
// Builder: AsFlow ---> Collections are converted to flow
val demo3 = listOf("A","B","C").asFlow()
// Builder: Emit
val demo4 = flow {
emit("USA")
delay(500)
emit("INDIA")
}
println("<-------- Builder: FlowOf ---> Just one value -------->")
demo1.collect{
println(it)
}
println("<-------- Builder: FlowOf ---> Just one value -------->")
println("<----------------------------------------------------->")
println("<-------- Builder: FlowOf ---> Multiple one value ---->")
demo2.collect{
println(it)
}
println("<-------- Builder: FlowOf ---> Multiple one value ---->")
println("<----------------------------------------------------->")
println("<---------------- Builder: asFlow -------------------->")
demo3.collect{
println(it)
}
println("<---------------- Builder: asFlow -------------------->")
println("<----------------------------------------------------->")
println("<---------------- Builder: emit ---------------------->")
demo4.collect{
println(it)
}
println("<---------------- Builder: emit ---------------------->")
}
}
/**
* **************************** Cancelling the flow ****************************
*/
private val input = listOf(1,2,3,4,5,6,7,8,9).asFlow()
private var jobIp : Job? = null
fun stoppingFlowDemoStart() {
jobIp = viewModelScope.launch {
input.collect{
println("CurrentElement -> $it")
delay(1500)
}
}
}
fun invokeCancel(){
jobIp?.let {
it.cancel(cause = CancellationException("Cancelled by the user"))
}
}
/**
* **************************** Cancelling the flow ****************************
*/
/**
* **************************** Flow Context ****************************
*/
private fun generateIntegers() = flow {
var currentValue = 0
repeat(15){
// Increment value
currentValue ++
// keep a delay
delay(1000)
// Emit a value
println("Value on emission: $currentValue")
emit(currentValue)
}
}.flowOn(Dispatchers.IO)
fun flowContextDemo() = viewModelScope.launch {
generateIntegers().collect{
println("Value on received: $it")
}
}
/**
* **************************** Flow Context ****************************
*/
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/flows/modules/intermediate_operators/IntermediateOperators.kt
================================================
package com.istudio.app.modules.module_demos.flows.modules.intermediate_operators
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.istudio.app.ui.composables.AppButton
import com.istudio.app.ui.composables.AppText
@Composable
fun IntermediateOperators(navController: NavHostController) {
val viewModel: IntermediateOperatorsVm = hiltViewModel()
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
Spacer(modifier = Modifier.height(16.dp))
AppText(text = "Intermediate Operators")
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Map Operator", onClick = { viewModel.mapOperator() })
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Filter Operator", onClick = { viewModel.filterOperator() })
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Take Operator", onClick = { viewModel.takeOperator() })
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Drop Operator", onClick = { viewModel.dropOperator() })
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Transform Operator", onClick = { viewModel.transformOperator() })
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/flows/modules/intermediate_operators/IntermediateOperatorsVm.kt
================================================
package com.istudio.app.modules.module_demos.flows.modules.intermediate_operators
import android.content.Context
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.flow.dropWhile
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.filterIsInstance
import kotlinx.coroutines.flow.filterNot
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.flow.take
import kotlinx.coroutines.flow.takeWhile
import kotlinx.coroutines.flow.transform
import kotlinx.coroutines.launch
import javax.inject.Inject
import kotlin.coroutines.EmptyCoroutineContext
@HiltViewModel
class IntermediateOperatorsVm @Inject constructor(
@ApplicationContext private val context: Context,
) : ViewModel() {
private val flowOfIntegers = flowOf(1, 2, 3, 4, 5)
/**
* ****************************************
* OPERATOR: Map Operator
* DESCRIPTION: Using the map operator, We shall transform Integers into Strings
* ****************************************
* Types of map Operators:-
* ****************************************
* (1) flowOfIntegers.map { }
*
* (2) flowOfIntegers.mapNotNull { }
*
* (3) flowOfIntegers.mapLatest { }
* ****************************************
*/
fun mapOperator() {
viewModelScope.launch {
flowOfIntegers.map {
it.toString()
}.collect {
if(it is String){
// Use smart cast to check if it is string
println("Received value: -->$it")
}
}
}
}
/**
* OPERATOR: Filter Operator
* DESCRIPTION: Using the filter operator, We can con apply a filter to remove emissions that does not meet the criteria
* ****************************************
* Useful Filter Operators:-
* ****************************************
* (1) flowOfIntegers.filter { }
*
* (2) flowOfIntegers.filterNot { }
*
* (3) flowOfIntegers.filterIsInstance{ }
* ****************************************
*/
fun filterOperator() {
viewModelScope.launch {
flowOfIntegers.filter {
// We use modulus function to check if the number is divisible by 2
it%2 == 0
}.collect{
println("Received value: -->$it")
}
}
}
/**
* OPERATOR: Take Operator
* DESCRIPTION: They are called sizing operators that limit the size of emission based on a predicate condition
* ****************************************
* useful take Operators:-
* ****************************************
* (1) flowOfIntegers.take{ }
*
* (2) flowOfIntegers.takeIf { }
*
* (3) flowOfIntegers.takeWhile { }
*
* (4) flowOfIntegers.takeUnless { }
* ****************************************
*/
fun takeOperator() {
val scope = CoroutineScope(EmptyCoroutineContext)
scope.launch {
flowOfIntegers.take(2).collect{
println("Received value: -->$it")
}
}
}
/**
* OPERATOR: Drop Operator
* DESCRIPTION: We basically drop the mentioned initial emissions specified
* ****************************************
* Useful drop Operators:-
* ****************************************
* (1) flowOfIntegers.drop{ }
*
* (2) flowOfIntegers.dropWhile { }
* ****************************************
*/
fun dropOperator() {
val scope = CoroutineScope(EmptyCoroutineContext)
scope.launch {
flowOfIntegers.drop(1).collect{
println("Received value: -->$it")
}
}
}
/**
* OPERATOR: Transform Operator
* DESCRIPTION:
* We can transform the data apply some predicate conditions and emit the new value,
* We can also emit multiple emissions
* This is basically applying a collection of operators together and emitting the emission downstream
*/
fun transformOperator() {
val scope = CoroutineScope(EmptyCoroutineContext)
scope.launch {
flowOfIntegers.transform {
if((it%2)==0){
// Elements that are divisible by 2
emit(it)
}
}.collect{
println("Received value: -->$it")
}
}
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/flows/modules/mutable_state_of_flow/MutableStateOfFlowDemo.kt
================================================
package com.istudio.app.modules.module_demos.flows.modules.mutable_state_of_flow
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.istudio.app.ui.composables.AppButton
import com.istudio.app.ui.composables.AppText
import kotlinx.coroutines.launch
@Composable
fun MutableStateOfFlowDemo(navController: NavHostController){
val viewModel: MutableStateOfFlowDemoVm = hiltViewModel()
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
val coroutineScope = rememberCoroutineScope()
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Start producing emissions", onClick = {
coroutineScope.launch {
repeat(100){
viewModel.produce(it)
}
}
})
Spacer(modifier = Modifier.height(10.dp))
LaunchedEffect(key1 = true){
coroutineScope.launch {
viewModel.data.collect{
println("Consumed -> $it")
}
}
}
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/flows/modules/mutable_state_of_flow/MutableStateOfFlowDemoVm.kt
================================================
package com.istudio.app.modules.module_demos.flows.modules.mutable_state_of_flow
import android.content.Context
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import javax.inject.Inject
@HiltViewModel
class MutableStateOfFlowDemoVm @Inject constructor(
@ApplicationContext private val context: Context,
) : ViewModel() {
private val _data = MutableSharedFlow(0)
val data = _data.asSharedFlow()
suspend fun produce(value : Int) {
println("Emitted value -> $value")
_data.emit(value)
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/flows/modules/state_and_shared_flows/StateAndSharedFlowsDemo.kt
================================================
package com.istudio.app.modules.module_demos.flows.modules.state_and_shared_flows
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.istudio.app.ui.composables.AppButton
import com.istudio.app.ui.composables.AppText
@Composable
fun StateAndSharedFlowDemo(navController: NavHostController){
val viewModel: StateAndSharedFlowsDemoVm = hiltViewModel()
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.height(16.dp))
AppText(text = "Using Shared-In\nto convert into Hot-Flow")
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "First subscription", onClick = { viewModel.demo() })
Spacer(modifier = Modifier.height(10.dp))
AppButton(text = "Add second subscription", onClick = { viewModel.addNewSubscriber() })
Spacer(modifier = Modifier.height(16.dp))
AppText(text = "Using State-In\nto convert into Hot-Flow")
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "First subscription", onClick = { viewModel.demoTwo() })
Spacer(modifier = Modifier.height(10.dp))
AppButton(text = "Add second subscription", onClick = { viewModel.addNewSubscriberDemoTwo() })
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/flows/modules/state_and_shared_flows/StateAndSharedFlowsDemoVm.kt
================================================
package com.istudio.app.modules.module_demos.flows.modules.state_and_shared_flows
import android.content.Context
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.lastOrNull
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.flow.singleOrNull
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.flow.toSet
import kotlinx.coroutines.launch
import javax.inject.Inject
import kotlin.coroutines.EmptyCoroutineContext
@HiltViewModel
class StateAndSharedFlowsDemoVm @Inject constructor(
@ApplicationContext private val context: Context,
) : ViewModel() {
/**
* ********************************* SharedIn *********************************
*/
// Cold Flow
private fun generateDemoFlow() = flow {
repeat(1000){
emit("Emitting value => $it")
delay(2000)
}
}.shareIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(),
replay = 5
)
fun demo() = viewModelScope.launch{
// Give a delay of 1 second before subscribing
delay(1000)
generateDemoFlow().collect{
println("Collected value (A) => $it")
}
}
fun addNewSubscriber() = viewModelScope.launch{
generateDemoFlow().collect{
println("Collected value (B) => $it")
}
}
/**
* ********************************* SharedIn *********************************
*/
/**
* ********************************* StateIn *********************************
*/
private suspend fun generateDemoFlowTwo() = flow {
repeat(1000){
emit("Emitting value => $it")
delay(2000)
}
}.stateIn(
scope = viewModelScope
)
fun demoTwo() = viewModelScope.launch {
println("Before second subscriber subscription -> ${generateDemoFlowTwo().value}")
// Give a delay of 1 second before subscribing
delay(1000)
generateDemoFlowTwo().collect{
println("Collected value (A) => $it")
}
}
fun addNewSubscriberDemoTwo() = viewModelScope.launch{
generateDemoFlow().collect{
println("Collected value (B) => $it")
}
}
/**
* ********************************* StateIn *********************************
*/
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/flows/modules/terminal_operators/TerminalOperators.kt
================================================
package com.istudio.app.modules.module_demos.flows.modules.terminal_operators
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.istudio.app.modules.module_selection.ModuleDemo
import com.istudio.app.ui.composables.AppButton
import com.istudio.app.ui.composables.AppText
@Composable
fun TerminalOperators(navController: NavHostController){
val viewModel: TerminalOperatorsVm = hiltViewModel()
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.height(16.dp))
AppText(text = "Terminal Operators")
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "First", onClick = { viewModel.demoFirst() })
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Last", onClick = { viewModel.demoLast() })
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Single", onClick = { viewModel.single() })
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "ToList And ToSet", onClick = { viewModel.toListAndToSet() })
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "LaunchIn", onClick = { viewModel.launchIn() })
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/flows/modules/terminal_operators/TerminalOperatorsVm.kt
================================================
package com.istudio.app.modules.module_demos.flows.modules.terminal_operators
import android.content.Context
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.lastOrNull
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.single
import kotlinx.coroutines.flow.singleOrNull
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.flow.toSet
import kotlinx.coroutines.launch
import javax.inject.Inject
import kotlin.coroutines.EmptyCoroutineContext
@HiltViewModel
class TerminalOperatorsVm @Inject constructor(
@ApplicationContext private val context: Context,
) : ViewModel() {
companion object {
const val emissionDelay : Long = 100
}
private val terminalOperatorDemo = flow {
delay(emissionDelay)
println("Emitting first value")
emit(1)
delay(emissionDelay)
println("Emitting second value")
emit(2)
}
/** *********************** DEMO's *********************** **/
/**
* Terminal Operator: First
*/
fun demoFirst() {
viewModelScope.launch {
val result = terminalOperatorDemo.firstOrNull()
println("Result:-> $result")
}
}
/**
* Terminal Operator: Last
*/
fun demoLast() {
viewModelScope.launch {
val result = terminalOperatorDemo.lastOrNull()
println("Result:-> $result")
}
}
/**
* Terminal Operator: Single
*/
fun single() {
viewModelScope.launch {
val result = terminalOperatorDemo.singleOrNull()
println("Result:-> $result")
}
}
/**
* Terminal Operator: ToListAndToSet
*/
fun toListAndToSet() {
viewModelScope.launch {
val resultList = terminalOperatorDemo.toList()
val resultSet = terminalOperatorDemo.toSet()
println("Result List:-> $resultList")
println("Result Set:-> $resultSet")
}
}
/**
* Terminal Operator: LaunchIn
*/
fun launchIn() {
val scope = CoroutineScope(EmptyCoroutineContext)
viewModelScope.launch {
terminalOperatorDemo
.onEach { println("Result Collect <1>:-> $it") }
.launchIn(scope)
terminalOperatorDemo
.onEach { println("Result Collect <2>:-> $it") }
.launchIn(scope)
}
}
fun launch() {
val scope = CoroutineScope(EmptyCoroutineContext)
scope.launch {
// Collect -> Starting first collection
terminalOperatorDemo.collect{
println("Result Collect <1>:-> $it")
}
// <--- Until first collection is complete, collection is suspended --->
// Collect -> Starting second collection
terminalOperatorDemo.collect{
println("Result Collect <2>:-> $it")
}
}
}
/** *********************** DEMO's *********************** **/
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/higher_order_functions/ui/HigherOrderFunctionDemo.kt
================================================
package com.istudio.app.modules.module_demos.higher_order_functions.ui
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.istudio.app.ui.composables.AppButton
@Composable
fun HigherOrderFunctionDemo(navController: NavHostController) {
val viewModel: HigherOrderFunctionDemoVm = hiltViewModel()
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Passing Functions as parameter", onClick = {
// Here will will calculate the square of a number
val input = 5
// Call the functionality
val result = viewModel.performOperation(input) { input ->
input * input
}
println(result)
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Returning Function", onClick = {
// We pass a operation here
val addFunction = viewModel.createCalculator("add")
// We use the operation passed above to pass values for it
val resultAdd = addFunction(5, 3) // Result is 8
println("Result (Add): $resultAdd")
})
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/higher_order_functions/ui/HigherOrderFunctionDemoVm.kt
================================================
package com.istudio.app.modules.module_demos.higher_order_functions.ui
import androidx.lifecycle.ViewModel
import javax.inject.Inject
class HigherOrderFunctionDemoVm @Inject constructor( ) : ViewModel() {
// <-------------- Passing Functions as Parameters -------------->
fun performOperation(input: Int, operation: (Int) -> Int): Int {
return operation(input)
}
// <-------------- Passing Functions as Parameters -------------->
// <-------------- Returning Functions as Parameters ------------>
fun createCalculator(operator: String): (Int, Int) -> Int {
return when (operator) {
"add" -> { a, b -> a + b }
"subtract" -> { a, b -> a - b }
"multiply" -> { a, b -> a * b }
"divide" -> { a, b -> if (b != 0) a / b else 0 }
else -> throw IllegalArgumentException("Unknown operator: $operator")
}
}
// <-------------- Returning Functions as Parameters ------------>
// 1- With Parameters and Return Value
fun type1() {
val add1:(Int,Int) -> Int = { a:Int , b:Int -> a+b }
println(add1(1,2))
}
// 2- With Parameters and no return value
fun type2() {
val add2 : (Int,Int) -> Unit = { a,b -> println(a+b) }
add2(1,2)
}
// 3- No Parameters but with return value
fun type3() {
val add3 : () -> String = { "Hello world" }
println(add3())
}
// 4- No Parameters and no return value
fun type4() {
val add4 : () -> Unit = { println("Hello World") }
add4.invoke()
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/kotlin_annotations/ui/KotlinAnnotationsDemoVm.kt
================================================
package com.istudio.app.modules.module_demos.kotlin_annotations.ui
import androidx.lifecycle.ViewModel
import com.istudio.app.modules.module_demos.kotlin_annotations.utils.jvmField.init.JavaInstanceJf
import com.istudio.app.modules.module_demos.kotlin_annotations.utils.jvmField.init.KotlinInstanceJf
import com.istudio.app.modules.module_demos.kotlin_annotations.utils.jvmOverloads.init.JavaInstanceJo
import com.istudio.app.modules.module_demos.kotlin_annotations.utils.jvmOverloads.init.KotlinInstanceJo
import com.istudio.app.modules.module_demos.kotlin_annotations.utils.jvmstatic.init.JavaInstanceJs
import com.istudio.app.modules.module_demos.kotlin_annotations.utils.jvmstatic.init.KotlinInstanceJs
import com.istudio.app.modules.module_demos.kotlin_annotations.utils.nullableAndNotNull.SuperHero
import com.istudio.app.modules.module_demos.kotlin_annotations.utils.stringDef.UserManager
import com.istudio.app.modules.module_demos.kotlin_annotations.utils.stringDef.UserStatus
import com.istudio.app.modules.module_demos.kotlin_annotations.utils.stringRes.init.JavaInstanceSr
import com.istudio.app.modules.module_demos.kotlin_annotations.utils.stringRes.init.KotlinInstanceSr
import javax.inject.Inject
class KotlinAnnotationsDemoVm @Inject constructor( ) : ViewModel() {
fun jvmFieldDemo() {
// Creating instance in JAVA
JavaInstanceJf().initilize()
// Creating instance in KOTLIN
KotlinInstanceJf().initilize()
}
fun jvmOverloadsDemo() {
// Creating instance in JAVA
JavaInstanceJo().initilize()
// Creating instance in KOTLIN
KotlinInstanceJo().initilize()
}
fun jvmStaticDemo() {
// Creating instance in JAVA
JavaInstanceJs().initilize()
// Creating instance in KOTLIN
KotlinInstanceJs().initilize()
}
fun stringResDemo() {
// Creating instance in JAVA
JavaInstanceSr().initilize()
// Creating instance in KOTLIN
KotlinInstanceSr().initilize()
}
fun nullableNotNull() {
val superHero = SuperHero()
val heroName : String? = superHero.name
println(heroName)
//superHero.setName(null)
}
fun stringDef() {
val userManager = UserManager()
userManager.modifyUserStatus(UserStatus.ACTIVE)
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/kotlin_annotations/ui/kotlinAnnotationsDemo.kt
================================================
package com.istudio.app.modules.module_demos.kotlin_annotations.ui
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.istudio.app.ui.composables.AppButton
@Composable
fun KotlinAnnotationsDemo(navController: NavHostController) {
val viewModel: KotlinAnnotationsDemoVm = hiltViewModel()
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "@JvmField", onClick = {
viewModel.jvmFieldDemo()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "@JvmOverloads", onClick = {
viewModel.jvmOverloadsDemo()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "@JvmStatic", onClick = {
viewModel.jvmStaticDemo()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "@StringRes", onClick = {
viewModel.stringResDemo()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "@Nullable And @NotNull", onClick = {
viewModel.nullableNotNull()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "@StringDef", onClick = {
viewModel.stringDef()
})
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/kotlin_annotations/utils/jvmField/JavaPerson.java
================================================
package com.istudio.app.modules.module_demos.kotlin_annotations.utils.jvmField;
public class JavaPerson {
private String name;
private int age;
public JavaPerson(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/kotlin_annotations/utils/jvmField/KotlinPerson.kt
================================================
package com.istudio.app.modules.module_demos.kotlin_annotations.utils.jvmField
data class KotlinPerson(@JvmField val name : String, val age : Int)
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/kotlin_annotations/utils/jvmField/init/JavaInstanceJf.java
================================================
package com.istudio.app.modules.module_demos.kotlin_annotations.utils.jvmField.init;
import com.istudio.app.modules.module_demos.kotlin_annotations.utils.jvmField.KotlinPerson;
public class JavaInstanceJf {
public void initilize() {
KotlinPerson person = new KotlinPerson("Suresh",21);
// We are able to access the variable without getter method even if its a kotlin class
System.out.println(person);
System.out.println(person.getAge()+"");
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/kotlin_annotations/utils/jvmField/init/KotlinInstanceJf.kt
================================================
package com.istudio.app.modules.module_demos.kotlin_annotations.utils.jvmField.init
import com.istudio.app.modules.module_demos.kotlin_annotations.utils.jvmField.KotlinPerson
class KotlinInstanceJf {
fun initilize() {
val (name, age) = KotlinPerson("Suresh", 21)
println(name)
println(age)
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/kotlin_annotations/utils/jvmOverloads/Student1.kt
================================================
package com.istudio.app.modules.module_demos.kotlin_annotations.utils.jvmOverloads
data class Student1(val name: String,val age : Int = 27)
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/kotlin_annotations/utils/jvmOverloads/Student2.kt
================================================
package com.istudio.app.modules.module_demos.kotlin_annotations.utils.jvmOverloads
data class Student2 @JvmOverloads constructor(val name: String,val age : Int = 27)
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/kotlin_annotations/utils/jvmOverloads/init/JavaInstanceJo.java
================================================
package com.istudio.app.modules.module_demos.kotlin_annotations.utils.jvmOverloads.init;
import com.istudio.app.modules.module_demos.kotlin_annotations.utils.jvmOverloads.Student1;
import com.istudio.app.modules.module_demos.kotlin_annotations.utils.jvmOverloads.Student2;
public class JavaInstanceJo {
public void initilize() {
Student1 stud1 = new Student1("Student1",20);
Student2 stud2 = new Student2("Student1");// Observe we did not pass age, Default value is taken from kotlin class
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/kotlin_annotations/utils/jvmOverloads/init/KotlinInstanceJo.kt
================================================
package com.istudio.app.modules.module_demos.kotlin_annotations.utils.jvmOverloads.init
import com.istudio.app.modules.module_demos.kotlin_annotations.utils.jvmOverloads.Student1
import com.istudio.app.modules.module_demos.kotlin_annotations.utils.jvmOverloads.Student2
class KotlinInstanceJo {
fun initilize() {
val (name, age) = Student1("Student1", 20)
val (name1, age1) = Student2("Student1") // Observe we did not pass age, Default value is taken from kotlin class
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/kotlin_annotations/utils/jvmstatic/Cinema.kt
================================================
package com.istudio.app.modules.module_demos.kotlin_annotations.utils.jvmstatic
object Cinema {
fun getActorName(): String{ return "John" }
@JvmStatic
fun getActressName(): String{ return "Sarah" }
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/kotlin_annotations/utils/jvmstatic/init/JavaInstanceJs.java
================================================
package com.istudio.app.modules.module_demos.kotlin_annotations.utils.jvmstatic.init;
import com.istudio.app.modules.module_demos.kotlin_annotations.utils.jvmstatic.Cinema;
public class JavaInstanceJs {
public void initilize() {
System.out.println(Cinema.getActressName());
System.out.println(Cinema.INSTANCE.getActorName());
//System.out.println(Cinema.getActorName());// Not possible
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/kotlin_annotations/utils/jvmstatic/init/KotlinInstanceJs.kt
================================================
package com.istudio.app.modules.module_demos.kotlin_annotations.utils.jvmstatic.init
import com.istudio.app.modules.module_demos.kotlin_annotations.utils.jvmstatic.Cinema
class KotlinInstanceJs {
fun initilize() {
println(Cinema.getActorName())
println(Cinema.getActressName())
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/kotlin_annotations/utils/nullableAndNotNull/SuperHero.java
================================================
package com.istudio.app.modules.module_demos.kotlin_annotations.utils.nullableAndNotNull;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class SuperHero {
private String name;
public @Nullable String getName() {
return name;
}
public void setName(@NotNull String name) {
this.name = name;
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/kotlin_annotations/utils/stringDef/UserManager.kt
================================================
package com.istudio.app.modules.module_demos.kotlin_annotations.utils.stringDef
import android.util.Log
class UserManager {
fun modifyUserStatus(@UserStatus.Status status: String) {
when(status){
UserStatus.ACTIVE -> {
Log.d("UserStatus","Logically Active")
}
UserStatus.IN_ACTIVE -> {
Log.d("UserStatus","Logically InActive")
}
UserStatus.BANNED -> {
Log.d("UserStatus","Logically Banned")
}
}
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/kotlin_annotations/utils/stringDef/UserStatus.kt
================================================
package com.istudio.app.modules.module_demos.kotlin_annotations.utils.stringDef
import androidx.annotation.StringDef
object UserStatus {
const val ACTIVE = "active"
const val IN_ACTIVE = "inactive"
const val BANNED = "banned"
@Retention(AnnotationRetention.SOURCE)
@StringDef(ACTIVE, IN_ACTIVE, BANNED)
annotation class Status
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/kotlin_annotations/utils/stringRes/HomeNavItem.kt
================================================
package com.istudio.app.modules.module_demos.kotlin_annotations.utils.stringRes
import androidx.annotation.StringRes
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.Create
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.outlined.Add
import androidx.compose.material.icons.outlined.Create
import androidx.compose.material.icons.outlined.MoreVert
import androidx.compose.ui.graphics.vector.ImageVector
import com.istudio.app.R
sealed class HomeNavItem(
val route: String,
val iconSelected: ImageVector,
val iconUnSelected: ImageVector,
@StringRes val title: Int
) {
// <--------- MyBooks Screen --------->
object MyBooks : HomeNavItem(
route = "myBooks",
title = R.string.app_books,
iconSelected = Icons.Filled.Add,
iconUnSelected = Icons.Outlined.Add,
)
// <--------- BookReviews Screen --------->
object BookReviews : HomeNavItem(
route = "bookReviews",
title = R.string.app_reviews,
iconSelected = Icons.Filled.Create,
iconUnSelected = Icons.Outlined.Create,
)
// <--------- ReadingList Screen --------->
object ReadingList : HomeNavItem(
route = "readingList",
title = R.string.app_reading_list,
iconSelected = Icons.Filled.MoreVert,
iconUnSelected = Icons.Outlined.MoreVert,
)
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/kotlin_annotations/utils/stringRes/init/JavaInstanceSr.java
================================================
package com.istudio.app.modules.module_demos.kotlin_annotations.utils.stringRes.init;
import com.istudio.app.modules.module_demos.kotlin_annotations.utils.stringRes.HomeNavItem;
public class JavaInstanceSr {
public void initilize() {
System.out.println(HomeNavItem.BookReviews.INSTANCE.getTitle());
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/kotlin_annotations/utils/stringRes/init/KotlinInstanceSr.kt
================================================
package com.istudio.app.modules.module_demos.kotlin_annotations.utils.stringRes.init
import com.istudio.app.modules.module_demos.kotlin_annotations.utils.stringRes.HomeNavItem
class KotlinInstanceSr {
fun initilize() {
println(HomeNavItem.BookReviews.title)
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/nested_vs_inner/ui/NestedVsInner.kt
================================================
package com.istudio.app.modules.module_demos.nested_vs_inner.ui
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.istudio.app.ui.composables.AppButton
@Composable
fun NestedVsInner(navController: NavHostController){
val viewModel: NestedVsInnerVm = hiltViewModel()
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Nested class Demo", onClick = {
viewModel.nestedClassDemo()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Inner class Demo", onClick = {
viewModel.innerClassDemo()
})
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/nested_vs_inner/ui/NestedVsInnerVm.kt
================================================
package com.istudio.app.modules.module_demos.nested_vs_inner.ui
import androidx.lifecycle.ViewModel
import com.istudio.app.modules.module_demos.nested_vs_inner.utils.OuterClass
import javax.inject.Inject
class NestedVsInnerVm @Inject constructor( ) : ViewModel() {
fun nestedClassDemo() {
val innerClassInstance = OuterClass.NestedClass()
println(innerClassInstance.nestedClassMember)
println(innerClassInstance.nestedClassFunction())
}
fun innerClassDemo() {
//Constructor of inner class InnerClass can be called only with receiver of containing class
//val innerClassInstance = OuterClass.InnerClass()
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/nested_vs_inner/utils/OuterClass.kt
================================================
package com.istudio.app.modules.module_demos.nested_vs_inner.utils
class OuterClass {
val outerClassMember = "outerClassMember"
fun outerClassFunction() { }
class NestedClass {
val nestedClassMember = "nestedClassMember"
fun nestedClassFunction() {
// This is not possible
// val nestedClassVariable = outerClassMember
// This is not possible
// outerClassFunction()
}
}
inner class InnerClass {
val innerClassMember = "innerClassMember"
fun innerClassFunction() {
// This is possible
val nestedClassVariable = outerClassMember
// This is possible
outerClassFunction()
}
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/sealed_class/ui/SealedClassDemo.kt
================================================
package com.istudio.app.modules.module_demos.sealed_class.ui
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.istudio.app.modules.module_demos.sealed_class.utils.payment.Payment
import com.istudio.app.ui.composables.AppButton
@Composable
fun SealedClassDemo(navController: NavHostController) {
val viewModel: SealedClassDemoVm = hiltViewModel()
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Create Sealed class Object", onClick = {
viewModel.createSealedClassObject()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Access public members of sealed class", onClick = {
viewModel.accessPublicMembers()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Access public function of sealed class", onClick = {
viewModel.accessPublicFunction()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Replicating Enum function using sealed class", onClick = {
viewModel.replicatingEnumFunction()
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Suggesting all possible options of state", onClick = {
viewModel.suggestAllPossibleOptions(
Payment.BankTransfer(amount = 10, orderId = 20)
)
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Using Abstract variable", onClick = {
viewModel.usingAbstractVariable()
})
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/sealed_class/ui/SealedClassDemoVm.kt
================================================
package com.istudio.app.modules.module_demos.sealed_class.ui
import androidx.lifecycle.ViewModel
import com.istudio.app.modules.module_demos.sealed_class.utils.Student.Student
import com.istudio.app.modules.module_demos.sealed_class.utils.animals.Tiger
import com.istudio.app.modules.module_demos.sealed_class.utils.payment.Payment
import com.istudio.app.modules.module_demos.sealed_class.utils.superHero.Hero
import javax.inject.Inject
class SealedClassDemoVm @Inject constructor( ) : ViewModel() {
fun createSealedClassObject() {
val tigerInstance = Tiger()
tigerInstance.printName()
}
fun accessPublicMembers() {
val tigerInstance = Tiger()
println(tigerInstance.publicCharacteristics)
}
fun accessPublicFunction() {
val tigerInstance = Tiger()
tigerInstance.publicCharacteristicsFunctionalities()
}
fun suggestAllPossibleOptions(payment: Payment) {
when (payment) {
is Payment.BankTransfer -> {
println("Bank Transfer")
}
is Payment.CardPayment -> {
println("Card Payment")
}
is Payment.CashPayment -> {
println("Cash Payment")
}
}
}
fun usingAbstractVariable() {
val instance = Hero("DC")
instance.printCompany()
}
fun replicatingEnumFunction() {
println(Student.Mahesh)
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/sealed_class/utils/Student/Student.kt
================================================
package com.istudio.app.modules.module_demos.sealed_class.utils.Student
sealed class Student {
object Mahesh
object Suresh
object Smitha
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/sealed_class/utils/animals/Animal.kt
================================================
package com.istudio.app.modules.module_demos.sealed_class.utils.animals
sealed class Animal {
// using companion object
companion object {
const val color : String = "Red"
const val age : Int = 50
}
// -----------> This is not possible
//const val height : Int = 50
// Private member variable
private val privateCharacteristics : String = "They are super powers"
// Public member variable
val publicCharacteristics : String = "They are alive"
// Public member function
fun publicCharacteristicsFunctionalities() {
println("We are printing public characteristics")
}
// Private data object
private data object Cat : Animal()
data class Dog(val name:String): Animal()
}
data object Camel : Animal()
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/sealed_class/utils/animals/Monkey.kt
================================================
package com.istudio.app.modules.module_demos.sealed_class.utils.animals
sealed class Monkey : Animal() {
init {
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/sealed_class/utils/animals/Tiger.kt
================================================
package com.istudio.app.modules.module_demos.sealed_class.utils.animals
import android.util.Log
class Tiger : Animal() {
fun printName() {
Log.d("DEMO","Tiger class")
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/sealed_class/utils/payment/Payment.kt
================================================
package com.istudio.app.modules.module_demos.sealed_class.utils.payment
sealed class Payment {
data class CashPayment(val amount: Int, val pointId: Int): Payment()
data class CardPayment(val amount: Int, val orderId: Int): Payment()
data class BankTransfer(val amount: Int, val orderId: Int): Payment()
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/sealed_class/utils/superHero/Hero.kt
================================================
package com.istudio.app.modules.module_demos.sealed_class.utils.superHero
class Hero(override val comicCompany: String) : SuperHero() {
fun printCompany(){
println(comicCompany)
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/sealed_class/utils/superHero/Payment.kt
================================================
package com.istudio.app.modules.module_demos.sealed_class.utils.superHero
sealed class SuperHero {
abstract val comicCompany : String
data class Superman(val superPower: String, override val comicCompany: String): SuperHero()
data class WonderWoman(val superPower: String, override val comicCompany: String): SuperHero()
data class Batman(val superPower: String, override val comicCompany: String): SuperHero()
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/type_alias/ui/TypeAlias.kt
================================================
package com.istudio.app.modules.module_demos.type_alias.ui
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.istudio.app.modules.module_demos.kotlin_annotations.ui.KotlinAnnotationsDemoVm
import com.istudio.app.ui.composables.AppButton
@Composable
fun TypeAlias(navController: NavHostController) {
val viewModel: TypeAliasVm = hiltViewModel()
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
AppButton(text = "Demo", onClick = {
viewModel.demo()
})
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/type_alias/ui/TypeAliasVm.kt
================================================
package com.istudio.app.modules.module_demos.type_alias.ui
import androidx.lifecycle.ViewModel
import com.istudio.app.modules.module_demos.type_alias.utils.AuthToken
import javax.inject.Inject
class TypeAliasVm @Inject constructor( ) : ViewModel() {
data class Student(val name : String, val age : Int, val authTolken : AuthToken)
data class Teacher(val name : String, val age : Int, val authTolken : AuthToken)
fun demo() {
val dataOne = Student(name = "Mahesh", age = 20 , authTolken = "282828fhisb")
val dataTwo = Teacher(name = "Suresh", age = 40 , authTolken = "282828fhisb")
println(dataOne.authTolken)
println(dataTwo.authTolken)
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_demos/type_alias/utils/TypeAliasReferences.kt
================================================
package com.istudio.app.modules.module_demos.type_alias.utils
typealias AuthToken = String
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_exercises/ExerciseSelection.kt
================================================
package com.istudio.app.modules.module_exercises
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.navigation.NavHostController
import com.istudio.app.modules.module_selection.ModuleDemo
import com.istudio.app.ui.composables.AppButton
@Composable
fun ExerciseSelection(navController: NavHostController){
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Exercise-1", onClick = {
navController.navigate(ModuleDemo.Exercise1.rout)
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Exercise-2", onClick = {
navController.navigate(ModuleDemo.Exercise2.rout)
})
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_exercises/exercise_1/Exercise1.kt
================================================
package com.istudio.app.modules.module_exercises.exercise_1
import android.util.Log
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.istudio.app.ui.composables.AppButton
import com.istudio.app.utils.endpoints.EndPointSimulation
import com.istudio.app.utils.log.ThreadInfoLogger.logThreadInfo
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun Exercise1(navController: NavHostController){
val viewModel: Exercise1vm = hiltViewModel()
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
var currentValue by remember { mutableStateOf("") }
var isActionButtonEnabled by remember { mutableStateOf(false) }
val keyboardController = LocalSoftwareKeyboardController.current
OutlinedTextField(
value = currentValue,
onValueChange = {
currentValue = it
// Enable it if there are data entered in the input field
if(!currentValue.isNullOrBlank()){ isActionButtonEnabled = true }
},
label = { Text(text = "Enter a value")},
keyboardOptions = KeyboardOptions.Default.copy(
imeAction = ImeAction.Done
),
keyboardActions = KeyboardActions(
onDone = { keyboardController?.hide() }
),
)
Spacer(modifier = Modifier.height(16.dp))
AppButton(
text = "ACTION",
isEnabled = isActionButtonEnabled,
onClick = {
logThreadInfo("button callback")
isActionButtonEnabled = false
CoroutineScope(Dispatchers.Default).launch {
// -------> Observe here since the long running operation is performed on separate task, UI is not blocked
val repo = EndPointSimulation.endPointCall("12")
Log.d("endpoint","Reputation:->$repo")
}
isActionButtonEnabled = true
}
)
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_exercises/exercise_1/Exercise1vm.kt
================================================
package com.istudio.app.modules.module_exercises.exercise_1
import androidx.lifecycle.ViewModel
import javax.inject.Inject
class Exercise1vm @Inject constructor( ) : ViewModel() {
fun demo() {
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_exercises/exercise_2/Exercise2.kt
================================================
package com.istudio.app.modules.module_exercises.exercise_2
import android.util.Log
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import com.istudio.app.ui.composables.AppButton
import com.istudio.app.utils.endpoints.EndPointSimulation
import com.istudio.app.utils.log.ThreadInfoLogger.logThreadInfo
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun Exercise2(navController: NavHostController){
val viewModel: Exercise2vm = hiltViewModel()
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
AppButton(text = "Blocking Type - Demo") {
viewModel.blockingTypeDemo()
}
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Suspending Type - Demo") {
viewModel.suspendingTypeDemo()
}
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_exercises/exercise_2/Exercise2vm.kt
================================================
package com.istudio.app.modules.module_exercises.exercise_2
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.joinAll
import kotlinx.coroutines.launch
import javax.inject.Inject
import kotlin.concurrent.thread
class Exercise2vm @Inject constructor( ) : ViewModel() {
fun blockingTypeDemo() {
val beforeThreadName = Thread.currentThread().name
println("Before calling threads, Execute in -> $beforeThreadName")
// Call thread 1
initiateNewThread(1)
// Call thread 2
initiateNewThread(2)
val threadNameLater = Thread.currentThread().name
Thread.sleep(600)
println("After calling threads, Execute in -> $threadNameLater")
}
private fun initiateNewThread(threadNo : Int) {
thread {
val threadName = Thread.currentThread().name
for (i in 1..4){
println("Task $threadNo with count$i is running on -> $threadName")
Thread.sleep(100)
}
}
}
fun suspendingTypeDemo() {
val beforeThreadName = Thread.currentThread().name
println("Before calling threads, Execute in -> $beforeThreadName")
CoroutineScope(Dispatchers.Main.immediate).launch {
joinAll(
// Call thread 1
launch { initiateNewCoroutine(1) },
// Call thread 2
launch { initiateNewCoroutine(2) }
)
}
val threadNameLater = Thread.currentThread().name
println("After calling threads, Execute in -> $threadNameLater")
}
private suspend fun initiateNewCoroutine(threadNo : Int) {
val threadName = Thread.currentThread().name
for (i in 1..4){
println("Task $threadNo with count$i is running on -> $threadName")
delay(100)
}
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_selection/ModuleDemo.kt
================================================
package com.istudio.app.modules.module_selection
sealed class ModuleDemo(val rout: String) {
data object DemoSelection : ModuleDemo("DemoSelection")
data object KotlinBasicsDemo : ModuleDemo("KotlinBasicsDemo")
data object SealedClassDemo : ModuleDemo("SealedClassDemo")
data object HigherOrderFunctions : ModuleDemo("HigherOrderFunctions")
data object AnnotationsInKotlin : ModuleDemo("AnnotationsInKotlin")
data object TypeAlias : ModuleDemo("TypeAlias")
data object ChannelsDemo : ModuleDemo("ChannelsDemo")
data object FlowsSelection : ModuleDemo("FlowsSelection")
data object FlowBasics : ModuleDemo("FlowBasics")
data object DisplayDataFromServer : ModuleDemo("DisplayDataFromServer")
data object TerminalOperators : ModuleDemo("TerminalOperators")
data object IntermediateOperators : ModuleDemo("IntermediateOperators")
data object NestedVsInner : ModuleDemo("NestedVsInner")
data object CoroutinesDemo : ModuleDemo("CoroutinesDemo")
data object Exercises : ModuleDemo("Exercises")
data object Exercise1 : ModuleDemo("Exercise1")
data object Exercise2 : ModuleDemo("Exercise2")
data object SimpleStructuredConcurrencyDemo : ModuleDemo("SimpleStructuredConcurrencyDemo")
data object DispatchersDemo : ModuleDemo("DispatchersDemo")
data object CoroutinesCancellationSelection : ModuleDemo("CoroutinesCancellationSelection")
data object RootChildrenCancelDemo : ModuleDemo("RootChildrenCancelDemo")
data object CoroutinesCancellationIsActiveDemo : ModuleDemo("CoroutinesCancellationIsActiveDemo")
data object EnsureActiveDemo : ModuleDemo("EnsureActiveDemo")
data object NonCancellableDemo : ModuleDemo("NonCancellableDemo")
data object SuspendAndLaunchDemo : ModuleDemo("SuspendAndLaunchDemo")
data object LaunchAndWithContextDemo : ModuleDemo("LaunchAndWithContextDemo")
data object JobDemoSelection : ModuleDemo("JobDemoSelection")
data object UsingJoinDemo : ModuleDemo("UsingJoinDemo")
data object UsingAsyncAwaitDemo : ModuleDemo("UsingAsyncAwaitDemo")
data object ExceptionHandlingSelectionDemo : ModuleDemo("ExceptionHandlingSelectionDemo")
data object UsingLaunchExceptionHandleDemo : ModuleDemo("UsingLaunchExceptionHandleDemo")
data object UsingAsyncExceptionHandleDemo : ModuleDemo("UsingAsyncExceptionHandleDemo")
data object ComposingAndFlatteningTheFlows : ModuleDemo("ComposingAndFlatteningTheFlows")
data object StateAndSharedFlowDemo : ModuleDemo("StateAndSharedFlowDemo")
data object MutableStateOfFlowDemo : ModuleDemo("MutableStateOfFlowDemo")
data object FlattenFlowsDemo : ModuleDemo("FlattenFlowsDemo")
data object CompareJoinAsyncDemo : ModuleDemo("CompareJoinAsyncDemo")
data object CollectAsStateWithLifeCycle : ModuleDemo("CollectAsStateWithLifeCycle")
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/modules/module_selection/ModuleSelectionScreen.kt
================================================
package com.istudio.app.modules.module_selection
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.navigation.NavHostController
import com.istudio.app.ui.composables.AppButton
@Composable
fun ModuleSelectionScreen(navController: NavHostController) {
Column(
modifier = Modifier.fillMaxSize().padding(10.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
) {
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Kotlin Basics", onClick = {
navController.navigate(ModuleDemo.KotlinBasicsDemo.rout)
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Sealed Class", onClick = {
navController.navigate(ModuleDemo.SealedClassDemo.rout)
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Annotations in kotlin", onClick = {
navController.navigate(ModuleDemo.AnnotationsInKotlin.rout)
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Type Alias", onClick = {
navController.navigate(ModuleDemo.TypeAlias.rout)
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Higher Order Functions", onClick = {
navController.navigate(ModuleDemo.HigherOrderFunctions.rout)
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "NestedVsInner", onClick = {
navController.navigate(ModuleDemo.NestedVsInner.rout)
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Channels", onClick = {
navController.navigate(ModuleDemo.ChannelsDemo.rout)
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Flows", onClick = {
navController.navigate(ModuleDemo.FlowsSelection.rout)
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Coroutines", onClick = {
navController.navigate(ModuleDemo.CoroutinesDemo.rout)
})
Spacer(modifier = Modifier.height(16.dp))
AppButton(text = "Exercises", onClick = {
navController.navigate(ModuleDemo.Exercises.rout)
})
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/ui/composables/Buttons.kt
================================================
package com.istudio.app.ui.composables
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@Composable
fun AppButton(
modifier: Modifier = Modifier,
text: String,
isEnabled : Boolean = true,
onClick: () -> Unit
) {
val gradientColor = listOf(Color(0xFFff00cc), Color(0xFF333399))
Button(
modifier = Modifier
.fillMaxWidth()
.padding(start = 32.dp, end = 32.dp),
onClick = onClick,
enabled = isEnabled,
contentPadding = PaddingValues(),
colors = ButtonDefaults.buttonColors(
containerColor = Color.Transparent
),
) {
Box(
modifier = Modifier
.fillMaxWidth()
.background(
brush = Brush.horizontalGradient(colors = gradientColor),
)
.padding(horizontal = 16.dp, vertical = 8.dp),
contentAlignment = Alignment.Center
) {
Text(
text = text,
fontSize = 20.sp,
color = Color.White,
textAlign = TextAlign.Center
)
}
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/ui/composables/Text.kt
================================================
package com.istudio.app.ui.composables
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
@Composable
fun AppText(
modifier: Modifier = Modifier,
text: String
) {
Text(text = text, textAlign = TextAlign.Center, modifier = Modifier.fillMaxWidth())
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/ui/theme/Color.kt
================================================
package com.istudio.app.ui.theme
import androidx.compose.ui.graphics.Color
val Purple80 = Color(0xFFD0BCFF)
val PurpleGrey80 = Color(0xFFCCC2DC)
val Pink80 = Color(0xFFEFB8C8)
val Purple40 = Color(0xFF6650a4)
val PurpleGrey40 = Color(0xFF625b71)
val Pink40 = Color(0xFF7D5260)
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/ui/theme/Shape.kt
================================================
package com.istudio.app.ui.theme
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Shapes
import androidx.compose.ui.unit.dp
val Shapes = Shapes(
small = RoundedCornerShape(4.dp),
medium = RoundedCornerShape(4.dp),
large = RoundedCornerShape(0.dp)
)
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/ui/theme/Theme.kt
================================================
package com.istudio.app.ui.theme
import android.app.Activity
import android.os.Build
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalView
import androidx.core.view.WindowCompat
private val DarkColorScheme = darkColorScheme(
primary = Purple80,
secondary = PurpleGrey80,
tertiary = Pink80
)
private val LightColorScheme = lightColorScheme(
primary = Purple40,
secondary = PurpleGrey40,
tertiary = Pink40
/* Other default colors to override
background = Color(0xFFFFFBFE),
surface = Color(0xFFFFFBFE),
onPrimary = Color.White,
onSecondary = Color.White,
onTertiary = Color.White,
onBackground = Color(0xFF1C1B1F),
onSurface = Color(0xFF1C1B1F),
*/
)
@Composable
fun KotlinConceptsTheme(
darkTheme: Boolean = isSystemInDarkTheme(),
// Dynamic color is available on Android 12+
dynamicColor: Boolean = true,
content: @Composable () -> Unit
) {
val colorScheme = when {
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
val context = LocalContext.current
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
}
darkTheme -> DarkColorScheme
else -> LightColorScheme
}
val view = LocalView.current
if (!view.isInEditMode) {
SideEffect {
val window = (view.context as Activity).window
window.statusBarColor = colorScheme.primary.toArgb()
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme
}
}
MaterialTheme(
colorScheme = colorScheme,
typography = Typography,
content = content
)
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/ui/theme/Type.kt
================================================
package com.istudio.app.ui.theme
import androidx.compose.material3.Typography
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.Font
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp
import com.istudio.app.R
// Set of Material typography styles to start with
val jostFontFamily = FontFamily(
Font(R.font.jost_book, FontWeight.Normal),
Font(R.font.jost_book, FontWeight.Light),
Font(R.font.jost_book, FontWeight.Medium),
Font(R.font.jost_medium, FontWeight.SemiBold),
Font(R.font.jost_medium, FontWeight.Bold),
)
// Set of Material typography styles to start with
val Typography = Typography(
displayLarge = TextStyle(
fontFamily = jostFontFamily,
fontWeight = FontWeight.Light,
fontSize = 57.sp,
lineHeight = 64.sp,
letterSpacing = 0.sp
),
displayMedium = TextStyle(
fontFamily = jostFontFamily,
fontWeight = FontWeight.Light,
fontSize = 45.sp,
lineHeight = 52.sp,
letterSpacing = 0.sp
),
displaySmall = TextStyle(
fontFamily = jostFontFamily,
fontWeight = FontWeight.Normal,
fontSize = 36.sp,
lineHeight = 44.sp,
letterSpacing = 0.sp
),
headlineLarge = TextStyle(
fontFamily = jostFontFamily,
fontWeight = FontWeight.SemiBold,
fontSize = 32.sp,
lineHeight = 40.sp,
letterSpacing = 0.sp
),
headlineMedium = TextStyle(
fontFamily = jostFontFamily,
fontWeight = FontWeight.SemiBold,
fontSize = 28.sp,
lineHeight = 36.sp,
letterSpacing = 0.sp
),
headlineSmall = TextStyle(
fontFamily = jostFontFamily,
fontWeight = FontWeight.SemiBold,
fontSize = 24.sp,
lineHeight = 32.sp,
letterSpacing = 0.sp
),
titleLarge = TextStyle(
fontFamily = jostFontFamily,
fontWeight = FontWeight.SemiBold,
fontSize = 22.sp,
lineHeight = 28.sp,
letterSpacing = 0.sp
),
titleMedium = TextStyle(
fontFamily = jostFontFamily,
fontWeight = FontWeight.SemiBold,
fontSize = 16.sp,
lineHeight = 24.sp,
letterSpacing = 0.15.sp
),
titleSmall = TextStyle(
fontFamily = jostFontFamily,
fontWeight = FontWeight.Bold,
fontSize = 14.sp,
lineHeight = 20.sp,
letterSpacing = 0.1.sp
),
bodyLarge = TextStyle(
fontFamily = jostFontFamily,
fontWeight = FontWeight.Normal,
fontSize = 16.sp,
lineHeight = 24.sp,
letterSpacing = 0.15.sp
),
bodyMedium = TextStyle(
fontFamily = jostFontFamily,
fontWeight = FontWeight.Medium,
fontSize = 14.sp,
lineHeight = 20.sp,
letterSpacing = 0.25.sp
),
bodySmall = TextStyle(
fontFamily = jostFontFamily,
fontWeight = FontWeight.Bold,
fontSize = 12.sp,
lineHeight = 16.sp,
letterSpacing = 0.4.sp
),
labelLarge = TextStyle(
fontFamily = jostFontFamily,
fontWeight = FontWeight.SemiBold,
fontSize = 14.sp,
lineHeight = 20.sp,
letterSpacing = 0.1.sp
),
labelMedium = TextStyle(
fontFamily = jostFontFamily,
fontWeight = FontWeight.SemiBold,
fontSize = 12.sp,
lineHeight = 16.sp,
letterSpacing = 0.5.sp
),
labelSmall = TextStyle(
fontFamily = jostFontFamily,
fontWeight = FontWeight.SemiBold,
fontSize = 11.sp,
lineHeight = 16.sp,
letterSpacing = 0.5.sp
)
)
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/utils/base/BaseViewModel.kt
================================================
package com.istudio.app.utils.base
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
open class BaseViewModel : ViewModel() {
fun uiState(): LiveData = uiState
protected val uiState: MutableLiveData = MutableLiveData()
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/utils/endpoints/EndPointSimulation.kt
================================================
package com.istudio.app.utils.endpoints
import com.istudio.app.utils.log.ThreadInfoLogger
import kotlin.random.Random
object EndPointSimulation {
fun endPointCall(userId: String): Int {
ThreadInfoLogger.logThreadInfo("EndPointSimulation#endPointCall(): called")
Thread.sleep(10000)
ThreadInfoLogger.logThreadInfo("EndPointSimulation#endPointCall(): return data")
return Random.nextInt(0, 100)
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/utils/extensions/Activity.kt
================================================
package com.istudio.app.utils.extensions
import android.content.Context
import android.content.Intent
import android.os.Bundle
/** ************************* Launching activity ************************* **/
/** SAMPLE ->
openActivity(MyActivity::class.java) {
putString("string.key", "string.value")
putInt("string.key", 43)
...
}
*/
fun Context.openActivity(it: Class, extras: Bundle.() -> Unit = {}) {
val intent = Intent(this, it)
intent.putExtras(Bundle().apply(extras))
startActivity(intent)
}
/** ************************* Launching activity ************************* **/
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/utils/extensions/Coroutine.kt
================================================
package com.istudio.app.utils.extensions
import kotlinx.coroutines.CoroutineName
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
fun CoroutineScope.printCoroutineScopeInfo() {
println("<--------------------------------------------->")
println("Scope: $this")
println("Name: ${this.coroutineContext[CoroutineName]?.name}")
println("Context: ${this.coroutineContext}")
println("Job: ${this.coroutineContext[Job]}")
println("<--------------------------------------------->")
}
================================================
FILE: application/KotlinConcepts/app/src/main/java/com/istudio/app/utils/log/ThreadInfoLogger.kt
================================================
package com.istudio.app.utils.log
import android.util.Log
object ThreadInfoLogger {
private const val TAG = "ThreadInfoLogger"
fun logThreadInfo(message: String) {
Log.i(TAG, "$message; thread name: ${Thread.currentThread().name}; thread ID: ${Thread.currentThread().id}")
}
}
================================================
FILE: application/KotlinConcepts/app/src/main/res/drawable/ic_launcher_background.xml
================================================
================================================
FILE: application/KotlinConcepts/app/src/main/res/drawable/ic_launcher_foreground.xml
================================================
================================================
FILE: application/KotlinConcepts/app/src/main/res/values/colors.xml
================================================
#FFBB86FC
#FF6200EE
#FF3700B3
#FF03DAC5
#FF018786
#FF000000
#FFFFFFFF
================================================
FILE: application/KotlinConcepts/app/src/main/res/values/strings.xml
================================================
KotlinConcepts
Books
Reviews
ReadingList
================================================
FILE: application/KotlinConcepts/app/src/main/res/values/themes.xml
================================================
================================================
FILE: application/KotlinConcepts/app/src/main/res/xml/backup_rules.xml
================================================
================================================
FILE: application/KotlinConcepts/app/src/main/res/xml/data_extraction_rules.xml
================================================
================================================
FILE: application/KotlinConcepts/app/src/test/java/com/istudio/app/ExampleUnitTest.kt
================================================
package com.istudio.app
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}
================================================
FILE: application/KotlinConcepts/build.gradle.kts
================================================
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id("com.android.application") version "8.5.2" apply false
id("org.jetbrains.kotlin.android") version "1.9.0" apply false
id("com.google.dagger.hilt.android") version "2.44" apply false
id("org.jetbrains.kotlin.jvm") version "1.9.24" apply false
}
================================================
FILE: application/KotlinConcepts/gradle/wrapper/gradle-wrapper.properties
================================================
#Thu Dec 21 10:35:24 IST 2023
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
================================================
FILE: application/KotlinConcepts/gradle.properties
================================================
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true
================================================
FILE: application/KotlinConcepts/gradlew
================================================
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"
================================================
FILE: application/KotlinConcepts/gradlew.bat
================================================
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
================================================
FILE: application/KotlinConcepts/settings.gradle.kts
================================================
pluginManagement {
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
}
}
rootProject.name = "KotlinAlchemy"
include(":app")
================================================
FILE: application/Sample-Coroutines/.idea/.name
================================================
My Application
================================================
FILE: application/Sample-Coroutines/.idea/compiler.xml
================================================
================================================
FILE: application/Sample-Coroutines/.idea/deploymentTargetDropDown.xml
================================================
================================================
FILE: application/Sample-Coroutines/.idea/deploymentTargetSelector.xml
================================================
================================================
FILE: application/Sample-Coroutines/.idea/gradle.xml
================================================
================================================
FILE: application/Sample-Coroutines/.idea/kotlinc.xml
================================================
================================================
FILE: application/Sample-Coroutines/.idea/material_theme_project_new.xml
================================================
================================================
FILE: application/Sample-Coroutines/.idea/migrations.xml
================================================
================================================
FILE: application/Sample-Coroutines/.idea/misc.xml
================================================
================================================
FILE: application/Sample-Coroutines/.idea/modules.xml
================================================
================================================
FILE: application/Sample-Coroutines/.idea/other.xml
================================================
================================================
FILE: application/Sample-Coroutines/.idea/workspace.xml
================================================
1703428587072
1703428587072
================================================
FILE: application/Sample-Coroutines/README.md
================================================
# DroidCoroutinesUsecases

* **`Check wiki tab above to access the documentation and some use cases`**
* **`This repository demonstrates how we can use coroutines in android development`**
================================================
FILE: application/Sample-Coroutines/app/.gitignore
================================================
/build
================================================
FILE: application/Sample-Coroutines/app/build.gradle
================================================
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
apply plugin: 'dagger.hilt.android.plugin'
apply plugin: 'kotlin-kapt'
android {
compileSdkVersion 31
buildToolsVersion "29.0.3"
defaultConfig {
applicationId "com.demo.code"
minSdkVersion 21
targetSdkVersion 31
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
viewBinding {
enabled = true
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8.toString()
}
}
dependencies {
def lifecycle_version = "2.3.1"
def coroutines_version = "1.5.0"
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.4.21"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.core:core-ktx:1.6.0'
implementation "androidx.activity:activity-ktx:1.3.1"
implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
implementation 'androidx.recyclerview:recyclerview:1.2.1'
implementation 'androidx.cardview:cardview:1.0.0'
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.7.1'
implementation 'com.google.code.gson:gson:2.8.6'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
implementation 'io.reactivex.rxjava2:rxjava:2.2.19'
implementation 'io.reactivex.rxjava2:rxkotlin:2.4.0'
implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version"
def work_manager_version = "2.6.0"
implementation "androidx.work:work-runtime:$work_manager_version"
implementation "androidx.work:work-runtime-ktx:$work_manager_version"
implementation 'com.jakewharton.timber:timber:4.7.1'
def room_version = "2.3.0"
implementation "androidx.room:room-runtime:$room_version"
implementation "androidx.room:room-ktx:$room_version"
kapt "androidx.room:room-compiler:$room_version"
testImplementation 'junit:junit:4.13.2'
testImplementation 'androidx.arch.core:core-testing:2.1.0'
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version"
testImplementation 'com.squareup.retrofit2:retrofit-mock:2.7.1'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation "com.google.dagger:hilt-android:2.38.1"
kapt "com.google.dagger:hilt-compiler:2.38.1"
}
================================================
FILE: application/Sample-Coroutines/app/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
================================================
FILE: application/Sample-Coroutines/app/src/androidTest/java/com/demo/code/ExampleInstrumentedTest.kt
================================================
package com.demo.code
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.lukaslechner.coroutineusecasesonandroid", appContext.packageName)
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/AndroidManifest.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/CoroutineUsecasesOnAndroidApplication.kt
================================================
package com.demo.code
import android.app.Application
import com.demo.code.usecases.coroutines.usecase14.AndroidVersionDatabase
import com.demo.code.usecases.coroutines.usecase14.AndroidVersionRepository
import dagger.hilt.android.HiltAndroidApp
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.SupervisorJob
import timber.log.Timber
@HiltAndroidApp
class CoroutineUsecasesOnAndroidApplication : Application() {
private val applicationScope = CoroutineScope(SupervisorJob())
val androidVersionRepository by lazy {
val database = AndroidVersionDatabase.getInstance(applicationContext).androidVersionDao()
AndroidVersionRepository(
database,
applicationScope
)
}
override fun onCreate() {
super.onCreate()
Timber.plant(Timber.DebugTree())
// Enable Debugging for Kotlin Coroutines in debug builds
// Prints Coroutine name when logging Thread.currentThread().name
System.setProperty("kotlinx.coroutines.debug", if (BuildConfig.DEBUG) "on" else "off")
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/activities/JobsActivity.kt
================================================
package com.demo.code.activities
import android.os.Bundle
import com.demo.code.base.BaseActivity
import com.demo.code.databinding.ActivityJobsBinding
import kotlinx.coroutines.*
@DelicateCoroutinesApi
class JobsActivity : BaseActivity() {
override fun getToolbarTitle() = "Jobs in Coroutine"
private lateinit var binding: ActivityJobsBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityJobsBinding.inflate(layoutInflater)
setContentView(binding.root)
hideUpButton()
setOnClickListeners()
}
private fun setOnClickListeners() {
binding.apply {
retryDemoId.setOnClickListener {
retryDemo()
}
simpleDemoOneId.setOnClickListener {
simpleJobOneDemo()
}
simpleDemoTwoId.setOnClickListener {
simpleJobTwoDemo()
}
}
}
private fun simpleJobTwoDemo() {
val rootJob = GlobalScope.launch(start = CoroutineStart.DEFAULT){
val parentJob = launch {
delay(10)
println("Parent job started")
delay(10)
}
val childOneJob = launch() {
delay(10)
println("Child one job started")
delay(10)
}
val childTwoJob = launch() {
delay(10)
println("Child two job started")
delay(10)
}
if(parentJob.children.iterator().hasNext()){
val childCnt = parentJob.children
println("Parent has $childCnt children")
}else{
println("Parent has no children")
}
Thread.sleep(1000)
}
/**
* OUTPUT:->
* Parent has kotlin.sequences.SequencesKt__SequenceBuilderKt$sequence$$inlined$Sequence$1@85caa11 children
* Parent job started
* Child two job started
* Child one job started
*/
}
private fun simpleJobOneDemo() {
/**
* This since executed by Lazy, It will start only when invoked
*/
val job1 = GlobalScope.launch(start=CoroutineStart.LAZY) {
delay(200)
println("Two")
delay(200)
}
GlobalScope.launch {
delay(200)
println("One")
// Job is invoked here so it is executed here
job1.join()
println("Three")
}
/**
* 2021-10-09 12:08:38.108 18586-18711/com.demo.code I/System.out: One
* 2021-10-09 12:08:38.311 18586-18711/com.demo.code I/System.out: Two
* 2021-10-09 12:08:38.519 18586-18711/com.demo.code I/System.out: Three
*/
}
private fun retryDemo(){
GlobalScope.launch {
repeat(3){
delay(200)
println("Execution happened")
}
}
/** Output:
* Execution happened
* Execution happened
* Execution happened
*/
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/activities/MainActivity.kt
================================================
package com.demo.code.activities
import android.os.Bundle
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import com.demo.code.R
import com.demo.code.base.*
import com.demo.code.databinding.ActivityMainBinding
class MainActivity : BaseActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
hideUpButton()
initRecyclerView()
}
private val onUseCaseCategoryClickListener: (UseCaseCategory) -> Unit =
{ clickedUseCaseCategory ->
val intent = UseCaseActivity.newIntent(applicationContext, clickedUseCaseCategory)
startActivity(intent)
}
private fun initRecyclerView() {
binding.recyclerView.apply {
adapter =
UseCaseCategoryAdapter(
useCaseCategories,
onUseCaseCategoryClickListener
)
hasFixedSize()
layoutManager = LinearLayoutManager(this@MainActivity)
addItemDecoration(initItemDecoration())
}
}
private fun initItemDecoration(): DividerItemDecoration {
val itemDecorator =
DividerItemDecoration(applicationContext, DividerItemDecoration.VERTICAL)
itemDecorator.setDrawable(
ContextCompat.getDrawable(
applicationContext,
R.drawable.recyclerview_divider
)!!
)
return itemDecorator
}
override fun getToolbarTitle() = "Coroutine Usecases on Android"
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/activities/SelectionActivity.kt
================================================
package com.demo.code.activities
import android.content.Intent
import android.os.Bundle
import com.demo.code.base.BaseActivity
import com.demo.code.databinding.ActivitySelectionBinding
import com.demo.code.modules.observabletypes.ObservableTypesActivity
class SelectionActivity : BaseActivity() {
private lateinit var binding: ActivitySelectionBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivitySelectionBinding.inflate(layoutInflater)
setContentView(binding.root)
hideUpButton()
setOnClickListeners()
}
private fun setOnClickListeners() {
binding.apply {
btnUseCasesId.setOnClickListener {
startActivity(Intent(this@SelectionActivity, MainActivity::class.java))
}
jobsId.setOnClickListener {
startActivity(Intent(this@SelectionActivity, JobsActivity::class.java))
}
suspendingFunctionsId.setOnClickListener {
startActivity(Intent(this@SelectionActivity, SuspendingFuncActivity::class.java))
}
typesOfObservablesId.setOnClickListener {
startActivity(Intent(this@SelectionActivity, ObservableTypesActivity::class.java))
}
}
}
override fun getToolbarTitle() = "Selection Screen"
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/activities/SuspendingFuncActivity.kt
================================================
package com.demo.code.activities
import android.os.Bundle
import androidx.lifecycle.lifecycleScope
import com.demo.code.base.BaseActivity
import com.demo.code.databinding.ActivitySuspendingFuncBinding
import com.demo.code.modules.legacycode.LegacyCallbackSampleOne
import com.demo.code.modules.legacycode.LegacyCallbackSampleTwo
import com.demo.code.modules.legacycode.User
import kotlinx.coroutines.launch
import kotlin.concurrent.thread
import kotlin.coroutines.suspendCoroutine
class SuspendingFuncActivity : BaseActivity() {
override fun getToolbarTitle() = "Suspending Functions"
private lateinit var binding: ActivitySuspendingFuncBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivitySuspendingFuncBinding.inflate(layoutInflater)
setContentView(binding.root)
hideUpButton()
setOnClickListeners()
}
private fun setOnClickListeners() {
binding.apply {
btnLaunchId.setOnClickListener {
simpleDemo()
}
}
}
private fun simpleDemo() {
lifecycleScope.launch {
LegacyCallbackSampleTwo(this.coroutineContext).initiateDemo()
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/base/BaseActivity.kt
================================================
package com.demo.code.base
import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import com.demo.code.R
import com.demo.code.utils.setGone
abstract class BaseActivity : AppCompatActivity() {
abstract fun getToolbarTitle(): String
override fun onStart() {
super.onStart()
setToolbarTitle(getToolbarTitle())
getUpButton().setOnClickListener {
finish()
}
}
private fun getUpButton(): ImageView = findViewById(R.id.btnToolbarBack)
private fun getToolbar(): TextView = findViewById(R.id.toolbarTitle)
fun hideUpButton() {
getUpButton().setGone()
}
private fun setToolbarTitle(toolbarTitle: String) {
getToolbar().text = toolbarTitle
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/base/BaseViewModel.kt
================================================
package com.demo.code.base
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
open class BaseViewModel : ViewModel() {
fun uiState(): LiveData = uiState
protected val uiState: MutableLiveData = MutableLiveData()
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/base/UseCase.kt
================================================
package com.demo.code.base
import android.os.Parcelable
import androidx.appcompat.app.AppCompatActivity
import com.demo.code.usecases.channels.usecase1.ChannelUseCase1Activity
import com.demo.code.usecases.coroutines.usecase1.PerformSingleNetworkRequestActivity
import com.demo.code.usecases.coroutines.usecase10.CalculationInBackgroundActivity
import com.demo.code.usecases.coroutines.usecase11.CooperativeCancellationActivity
import com.demo.code.usecases.coroutines.usecase12.CalculationInSeveralCoroutinesActivity
import com.demo.code.usecases.coroutines.usecase13.ExceptionHandlingActivity
import com.demo.code.usecases.coroutines.usecase14.ContinueCoroutineWhenUserLeavesScreenActivity
import com.demo.code.usecases.coroutines.usecase15.WorkManagerActivity
import com.demo.code.usecases.coroutines.usecase16.PerformanceAnalysisActivity
import com.demo.code.usecases.coroutines.usecase17.PerformCalculationOnMainThreadActivity
import com.demo.code.usecases.coroutines.usecase2.Perform2SequentialNetworkRequestsActivity
import com.demo.code.usecases.coroutines.usecase2.callbacks.SequentialNetworkRequestsCallbacksActivity
import com.demo.code.usecases.coroutines.usecase2.rx.SequentialNetworkRequestsRxActivity
import com.demo.code.usecases.coroutines.usecase3.PerformNetworkRequestsConcurrentlyActivity
import com.demo.code.usecases.coroutines.usecase4.VariableAmountOfNetworkRequestsActivity
import com.demo.code.usecases.coroutines.usecase5.NetworkRequestWithTimeoutActivity
import com.demo.code.usecases.coroutines.usecase6.RetryNetworkRequestActivity
import com.demo.code.usecases.coroutines.usecase7.TimeoutAndRetryActivity
import com.demo.code.usecases.coroutines.usecase7.callbacks.TimeoutAndRetryCallbackActivity
import com.demo.code.usecases.coroutines.usecase7.rx.TimeoutAndRetryRxActivity
import com.demo.code.usecases.coroutines.usecase8.RoomAndCoroutinesActivity
import com.demo.code.usecases.coroutines.usecase9.DebuggingCoroutinesActivity
import com.demo.code.usecases.flow.usecase1.FlowUseCase1Activity
import kotlinx.android.parcel.Parcelize
@Parcelize
data class UseCase(
val description: String,
val targetActivity: Class
) : Parcelable
@Parcelize
data class UseCaseCategory(val categoryName: String, val useCases: List) : Parcelable
const val useCase1Description = "#1 Perform single network request"
const val useCase2Description = "#2 Perform two sequential network requests"
const val useCase2UsingCallbacksDescription = "#2 using Callbacks"
const val useCase2UsingRxDescription = "#2 using RxJava"
const val useCase3Description = "#3 Perform several network requests concurrently"
const val useCase4Description = "#4 Perform variable amount of network requests"
const val useCase5Description = "#5 Network request with TimeOut"
const val useCase6Description = "#6 Retry Network request"
const val useCase7Description = "#7 Network requests with timeout and retry"
const val useCase7UsingCallbacksDescription = "#7 Using callbacks"
const val useCase7UsingRxDescription = "#7 Using RxJava"
const val useCase8Description = "#8 Room and Coroutines"
const val useCase9Description = "#9 Debugging Coroutines"
const val useCase10Description = "#10 Offload expensive calculation to background thread"
const val useCase11Description = "#11 Cooperative Cancellation"
const val useCase12Description = "#12 Offload expensive calculation to several coroutines"
const val useCase13Description = "#13 Exception Handling"
const val useCase14Description = "#14 Continue Coroutine when User leaves screen"
const val useCase15Description = "#15 Using WorkManager with Coroutines"
const val useCase16Description =
"#16 Performance Analysis of dispatchers, number of coroutines and yielding"
const val useCase17Description =
"#17 Perform heavy calculation on Main Thread without freezing the UI"
private val coroutinesUseCases =
UseCaseCategory(
"Coroutine Use Cases", listOf(
UseCase(
useCase1Description,
PerformSingleNetworkRequestActivity::class.java
),
UseCase(
useCase2Description,
Perform2SequentialNetworkRequestsActivity::class.java
),
UseCase(
useCase2UsingCallbacksDescription,
SequentialNetworkRequestsCallbacksActivity::class.java
), UseCase(
useCase2UsingRxDescription,
SequentialNetworkRequestsRxActivity::class.java
),
UseCase(
useCase3Description,
PerformNetworkRequestsConcurrentlyActivity::class.java
),
UseCase(
useCase4Description,
VariableAmountOfNetworkRequestsActivity::class.java
),
UseCase(
useCase5Description,
NetworkRequestWithTimeoutActivity::class.java
),
UseCase(
useCase6Description,
RetryNetworkRequestActivity::class.java
),
UseCase(
useCase7Description,
TimeoutAndRetryActivity::class.java
),
UseCase(
useCase7UsingCallbacksDescription,
TimeoutAndRetryCallbackActivity::class.java
), UseCase(
useCase7UsingRxDescription,
TimeoutAndRetryRxActivity::class.java
),
UseCase(
useCase8Description,
RoomAndCoroutinesActivity::class.java
),
UseCase(
useCase9Description,
DebuggingCoroutinesActivity::class.java
),
UseCase(
useCase10Description,
CalculationInBackgroundActivity::class.java
),
UseCase(
useCase11Description,
CooperativeCancellationActivity::class.java
),
UseCase(
useCase12Description,
CalculationInSeveralCoroutinesActivity::class.java
),
UseCase(
useCase13Description,
ExceptionHandlingActivity::class.java
),
UseCase(
useCase14Description,
ContinueCoroutineWhenUserLeavesScreenActivity::class.java
),
UseCase(
useCase15Description,
WorkManagerActivity::class.java
),
UseCase(
useCase16Description,
PerformanceAnalysisActivity::class.java
),
UseCase(
useCase17Description,
PerformCalculationOnMainThreadActivity::class.java
)
)
)
private val channelsUseCases =
UseCaseCategory(
"Channels Use Cases",
listOf(
UseCase(
"Channels Use Case 1",
ChannelUseCase1Activity::class.java
)
)
)
private val flowUseCases =
UseCaseCategory(
"Flow Use Cases",
listOf(
UseCase(
"Flow Use Case 1",
FlowUseCase1Activity::class.java
)
)
)
val useCaseCategories = listOf(
coroutinesUseCases /*,
channelsUseCases,
flowUseCases */
)
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/base/UseCaseActivity.kt
================================================
package com.demo.code.base
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import com.demo.code.R
import com.demo.code.databinding.ActivityUsecasesBinding
class UseCaseActivity : BaseActivity() {
private val useCaseCategory by lazy {
intent.getParcelableExtra(
EXTRA_USE_CASE_CATEGORY
)!!
}
private lateinit var binding: ActivityUsecasesBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityUsecasesBinding.inflate(layoutInflater)
setContentView(binding.root)
initRecyclerView()
}
private val onUseCaseClickListener: (UseCase) -> Unit = { clickedUseCase ->
startActivity(Intent(applicationContext, clickedUseCase.targetActivity))
}
private fun initRecyclerView() {
binding.recyclerView.apply {
adapter =
UseCaseAdapter(
useCaseCategory,
onUseCaseClickListener
)
hasFixedSize()
layoutManager = LinearLayoutManager(this@UseCaseActivity)
addItemDecoration(initItemDecoration())
}
}
private fun initItemDecoration(): DividerItemDecoration {
val itemDecorator =
DividerItemDecoration(applicationContext, DividerItemDecoration.VERTICAL)
itemDecorator.setDrawable(
ContextCompat.getDrawable(
applicationContext,
R.drawable.recyclerview_divider
)!!
)
return itemDecorator
}
override fun getToolbarTitle() = useCaseCategory.categoryName
companion object {
private const val EXTRA_USE_CASE_CATEGORY = "EXTRA_USE_CASES"
fun newIntent(context: Context, useCaseCategory: UseCaseCategory) =
Intent(context, UseCaseActivity::class.java).apply {
putExtra(EXTRA_USE_CASE_CATEGORY, useCaseCategory)
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/base/UseCaseAdapter.kt
================================================
package com.demo.code.base
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.demo.code.R
class UseCaseAdapter(
private val useCaseCategory: UseCaseCategory,
private val onUseCaseClick: (UseCase) -> Unit
) : RecyclerView.Adapter() {
class ViewHolder(val textView: TextView) : RecyclerView.ViewHolder(textView)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val textView = LayoutInflater.from(parent.context)
.inflate(R.layout.recyclerview_item, parent, false) as TextView
return ViewHolder(
textView
)
}
override fun getItemCount() = useCaseCategory.useCases.size
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.textView.text = useCaseCategory.useCases[position].description
holder.textView.setOnClickListener {
onUseCaseClick(useCaseCategory.useCases[position])
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/base/UseCaseCategoryAdapter.kt
================================================
package com.demo.code.base
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.demo.code.R
class UseCaseCategoryAdapter(
private val useCaseCategories: List,
private val onUseCaseCategoryClick: (UseCaseCategory) -> Unit
) : RecyclerView.Adapter() {
class ViewHolder(val textView: TextView) : RecyclerView.ViewHolder(textView)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val textView = LayoutInflater.from(parent.context)
.inflate(R.layout.recyclerview_item, parent, false) as TextView
return ViewHolder(
textView
)
}
override fun getItemCount() = useCaseCategories.size
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.textView.text = useCaseCategories[position].categoryName
holder.textView.setOnClickListener {
onUseCaseCategoryClick(useCaseCategories[position])
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/mock/MockAnalyticsApi.kt
================================================
package com.demo.code.mock
import com.demo.code.utils.MockNetworkInterceptor
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.GET
interface MockAnalyticsApi {
@GET("analytics/workmanager-screen-opened")
suspend fun trackScreenOpened(): Boolean
}
fun createMockAnalyticsApi(interceptor: MockNetworkInterceptor): MockAnalyticsApi {
val okHttpClient = OkHttpClient.Builder()
.addInterceptor(interceptor)
.build()
val retrofit = Retrofit.Builder()
.baseUrl("http://localhost/")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()
return retrofit.create(MockAnalyticsApi::class.java)
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/mock/MockApi.kt
================================================
package com.demo.code.mock
import com.demo.code.utils.MockNetworkInterceptor
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.GET
import retrofit2.http.Path
interface MockApi {
@GET("recent-android-versions")
suspend fun getRecentAndroidVersions(): List
@GET("android-version-features/{apiLevel}")
suspend fun getAndroidVersionFeatures(@Path("apiLevel") apiLevel: Int): VersionFeatures
}
fun createMockApi(interceptor: MockNetworkInterceptor): MockApi {
val okHttpClient = OkHttpClient.Builder()
.addInterceptor(interceptor)
.build()
val retrofit = Retrofit.Builder()
.baseUrl("http://localhost/")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()
return retrofit.create(MockApi::class.java)
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/mock/MockData.kt
================================================
package com.demo.code.mock
data class AndroidVersion(val apiLevel: Int, val name: String)
data class VersionFeatures(val androidVersion: AndroidVersion, val features: List)
val mockAndroidVersionOreo = AndroidVersion(27, "Oreo")
val mockAndroidVersionPie = AndroidVersion(28, "Pie")
val mockAndroidVersionAndroid10 = AndroidVersion(29, "Android 10")
val mockAndroidVersions = listOf(
mockAndroidVersionOreo, mockAndroidVersionPie, mockAndroidVersionAndroid10
)
val featuresOfOreo = listOf(
"Neural networks API.",
"Shared memory API.",
"WallpaperColors API.",
"Bluetooth battery level for connected devices, accessible in Quick Settings.",
"Android Oreo Go Edition, a lightweight distribution of Android that runs better than normal Android on devices with less than 1 GB of RAM.",
"Autofill framework updates.",
"Programmatic Safe Browsing actions.",
"Navigation buttons dim when not in use.",
"Visual changes to 'Power Off' and 'Restart', including a new screen and floating toolbar.",
"Toast messages are now white with the same existing transparency.",
"Automatic light and dark themes.",
"New Easter egg in the form of an official Oreo cookie picture."
)
val featuresOfPie = listOf(
"New user interface for the quick settings menu.",
"The clock has moved to the left of the notification bar.",
"The \"dock\" now has a semi-transparent background.",
"Battery Saver no longer shows an orange overlay on the notification and status bars.",
"A \"screenshot\" button has been added to the power options.",
"A new \"Lockdown\" mode which disables biometric authentication once activated.",
"Rounded corners across the UI.",
"New transitions for switching between apps, or activities within apps.",
"Richer messaging notifications, where a full conversation can be seen within a notification, full-scale images, and smart replies akin to Google's new app, Reply.",
"Support for display cutouts.",
"Redesigned volume slider.",
"Battery percentage now shown in Always-On Display.",
"Lock screen security changes include the possible return of an improved NFC Unlock.",
"Experimental features (which are currently hidden within a menu called Feature Flags) such as a redesigned About Phone page in settings, and automatic Bluetooth enabling while driving.",
"DNS over TLS.",
"A new optional gesture-based system interface, allowing users to navigate the OS using swipes more often than the traditional UI.",
"Redesigned multitask app switcher with the Google search bar and app drawer built-in.",
"Android Dashboard, which tells the user how much time they are spending on their device and in apps, and allows the user to set time limits on apps.",
"\"Shush\", an enhanced version of Do Not Disturb mode activated by placing the phone face down, which mutes standard notifications.",
"\"Adaptive Battery\" prediction, which makes use of Doze to hibernate user apps the OS determines the user will not use.",
"Auto-Brightness feature modifies screen brightness based on user habits.",
"Wind Down option lets Android users set a specific bedtime that enables Do Not Disturb and turns the entire phone's interface gray to discourage further use at night.",
"Vulkan 1.1 support."
)
val featuresOfAndroid10 = listOf(
"New permissions to access location in background and to access photo, video and audio files",
"Background apps can no longer jump into the foreground",
"Limited access to non-resettable device identifiers",
"Sharing shortcuts, which allow sharing content with a contact directly",
"Floating settings panel, that allows changing system settings directly from apps",
"Dynamic depth format for photos, which allow changing background blur after taking a photo",
"Support for the AV1 video codec, the HDR10+ video format and the Opus audio codec",
"Support for aptX Adaptive, LHDC, LLAC, CELT and AAC LATM codecs[244",
"A native MIDI API, allowing interaction with music controllers",
"Better support for biometric authentication in apps",
"Support for the WPA3 Wi-Fi security protocol",
"Support for foldable phones",
"Support for Notification Bubbles",
"New system-wide dark theme/mode",
"Project Mainline, allows core OS components to be updated via the Google Play Store, without requiring a complete system update"
)
val mockVersionFeaturesOreo = VersionFeatures(
mockAndroidVersionOreo,
featuresOfOreo
)
val mockVersionFeaturesPie = VersionFeatures(
mockAndroidVersionPie,
featuresOfPie
)
val mockVersionFeaturesAndroid10 = VersionFeatures(
mockAndroidVersionAndroid10,
featuresOfAndroid10
)
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/modules/legacycode/LegacyCallbackSampleOne.kt
================================================
package com.demo.code.modules.legacycode
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import kotlin.concurrent.thread
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.suspendCoroutine
class LegacyCallbackSampleOne(
override val coroutineContext: CoroutineContext
) : CoroutineScope{
fun initiateDemo() {
launch {
getUser("111")
}
}
private suspend fun getUser(id: String): User = suspendCoroutine {
getUserFromNetworkCallback("101") { user, error ->
user?.run { println(this.userName) }
error?.run { println(this.message) }
}
}
private fun getUserFromNetworkCallback(
userId: String,
onUserResponse: (User?, Throwable?) -> Unit) {
thread {
try {
Thread.sleep(1000) // ---> Simulating the network delay
val user = User(userId, "Test User")
onUserResponse(user, null)
} catch (error: Throwable) {
onUserResponse(null, error)
}
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/modules/legacycode/LegacyCallbackSampleTwo.kt
================================================
package com.demo.code.modules.legacycode
import android.os.AsyncTask
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import java.io.IOException
import java.net.MalformedURLException
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
class LegacyCallbackSampleTwo(
override val coroutineContext: CoroutineContext
) : CoroutineScope {
fun initiateDemo() {
launch {
val user = getUser("111")
println(user.userName)
}
}
private suspend fun getUser(id: String): User = suspendCoroutine {
try {
val result = MyTask().execute(id).get()
it.resume(result)
} catch (e: Exception) {
e.printStackTrace()
println(e.message)
}
}
class MyTask : AsyncTask() {
protected override fun doInBackground(vararg userId: String?): User? {
try {
return User(userId.toString(), "Async User")
} catch (e: MalformedURLException) {
e.printStackTrace()
} catch (e: IOException) {
e.printStackTrace()
}
return null
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/modules/legacycode/User.kt
================================================
package com.demo.code.modules.legacycode
data class User(val userId: String, val userName:String)
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/modules/observabletypes/ObservableTypesActivity.kt
================================================
package com.demo.code.modules.observabletypes
import android.os.Bundle
import androidx.activity.viewModels
import androidx.lifecycle.Observer
import androidx.lifecycle.lifecycleScope
import com.demo.code.base.BaseActivity
import com.demo.code.databinding.ActivityObservableTypesBinding
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.collectLatest
@AndroidEntryPoint
class ObservableTypesActivity : BaseActivity() {
override fun getToolbarTitle() = "Observable Types"
private lateinit var binding: ActivityObservableTypesBinding
private val viewModel: ObservableTypesViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityObservableTypesBinding.inflate(layoutInflater)
setContentView(binding.root)
hideUpButton()
setOnClickListeners()
subscribeData()
}
private fun setOnClickListeners() {
binding.apply {
liveDataId.setOnClickListener {
viewModel.liveDataDemo()
}
stateFlowId.setOnClickListener {
viewModel.stateFlowDemo()
}
flowId.setOnClickListener {
flowDemo()
}
sharedFlowId.setOnClickListener {
sharedFlowDemo()
}
}
}
private fun sharedFlowDemo() {
viewModel.sharedFlowDemo()
}
private fun flowDemo() {
lifecycleScope.launchWhenStarted {
viewModel.flowDemo().collectLatest {
binding.outputTextId.text = it
}
}
}
private fun subscribeData() {
viewModel.liveData.observe(this, {
binding.outputTextId.text = it
})
lifecycleScope.launchWhenCreated {
viewModel.stateFlow.collectLatest {
binding.outputTextId.text = it
}
}
lifecycleScope.launchWhenStarted {
viewModel.sharedFlow.collect {
binding.outputTextId.text = it
}
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/modules/observabletypes/ObservableTypesViewModel.kt
================================================
package com.demo.code.modules.observabletypes
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
class ObservableTypesViewModel : ViewModel() {
private val _liveData = MutableLiveData("Default")
val liveData : LiveData = _liveData
private val _stateFlow = MutableStateFlow("Default")
val stateFlow = _stateFlow.asStateFlow()
private val _sharedFlow = MutableSharedFlow()
val sharedFlow = _sharedFlow.asSharedFlow()
fun liveDataDemo() {
_liveData.value = "Live Data"
}
fun stateFlowDemo() {
_stateFlow.value = "State Flow"
}
fun flowDemo() : Flow{
return flow {
emit("Flow")
}
}
fun sharedFlowDemo() {
viewModelScope.launch {
_sharedFlow.emit("Shared Flow")
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/modules/placeholder
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/playground/cancellation/1_cancellation.kt
================================================
package com.demo.code.playground.cancellation
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
fun main() = runBlocking {
val job = launch {
repeat(10) { index ->
println("operation number $index")
try {
delay(100)
} catch (exception: CancellationException) {
println("CancellationException was thrown")
throw CancellationException()
}
}
}
delay(250)
println("Cancelling Coroutine")
job.cancel()
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/playground/cancellation/2_cooperative_cancellation.kt
================================================
package com.demo.code.playground.cancellation
import kotlinx.coroutines.*
fun main() = runBlocking {
val job = launch(Dispatchers.Default) {
repeat(10) { index ->
if (isActive) {
println("operation number $index")
Thread.sleep(100)
} else {
// perform some cleanup on cancellation
withContext(NonCancellable) {
delay(100)
println("Clean up done!")
}
throw CancellationException()
}
}
}
delay(250)
println("Cancelling Coroutine")
job.cancel()
val globalCoroutineJob = GlobalScope.launch {
repeat(10) {
println("$it")
delay(100)
}
}
delay(250)
globalCoroutineJob.cancel()
delay(1000)
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/playground/coroutine_scope.kt
================================================
package com.demo.code.playground
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
fun main() = runBlocking { // this: CoroutineScope
launch {
delay(200L)
println("Task from runBlocking")
}
coroutineScope { // Creates a new coroutine scope
launch {
delay(900L)
println("Task from nested launch")
}
delay(100L)
println("Task from coroutine scope") // This line will be printed before nested launch
}
println("Coroutine scope is over") // This line is not printed until nested launch completes
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/playground/coroutinebuilders/1_launch.kt
================================================
package com.demo.code.playground.coroutinebuilders
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
fun main() = runBlocking {
val job = launch(start = CoroutineStart.LAZY) {
networkRequest()
println("result received")
}
delay(200)
job.start()
println("end of runBlocking")
}
suspend fun networkRequest(): String {
delay(500)
return "Result"
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/playground/coroutinebuilders/2_async.kt
================================================
package com.demo.code.playground.coroutinebuilders
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
fun main() = runBlocking {
val startTime = System.currentTimeMillis()
val deferred1 = async {
val result1 = networkCall(1).also {
println("result received: $it after ${elapsedMillis(startTime)}ms")
}
result1
}
val deferred2 = async {
val result2 = networkCall(2)
println("result received: $result2 after ${elapsedMillis(startTime)}ms")
result2
}
val resultList = listOf(deferred1.await(), deferred2.await())
println("Result list: $resultList after ${elapsedMillis(startTime)}ms")
}
suspend fun networkCall(number: Int): String {
delay(500)
return "Result $number"
}
fun elapsedMillis(startTime: Long) = System.currentTimeMillis() - startTime
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/playground/exceptionhandling/1_try_catch.kt
================================================
package com.demo.code.playground.exceptionhandling
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
fun main() {
val scope = CoroutineScope(Job())
try {
scope.launch {
functionThatThrowsIt()
}
} catch (e: Exception) {
println("Caught: $e")
}
Thread.sleep(100)
}
fun functionThatThrowsIt() {
throw RuntimeException()
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/playground/exceptionhandling/2_coroutine_exception_handler.kt
================================================
package com.demo.code.playground.exceptionhandling
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
fun main() {
val exceptionHandler = CoroutineExceptionHandler { context, exception ->
println("Caught $exception in CoroutineExceptionHandler")
}
val scope = CoroutineScope(Job())
scope.launch {
launch(exceptionHandler) {
functionThatThrowsIt()
}
}
Thread.sleep(100)
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/playground/exceptionhandling/3_try_catch_vs_exception_handler.kt
================================================
package com.demo.code.playground.exceptionhandling
import kotlinx.coroutines.*
fun main() {
val exceptionHandler = CoroutineExceptionHandler { coroutineContext, throwable ->
println("Caught exception: $throwable")
}
val scope = CoroutineScope(Job())
scope.launch(exceptionHandler) {
launch {
println("Starting coroutine 1")
delay(100)
throw RuntimeException()
}
launch {
println("Starting coroutine 2")
delay(3000)
println("Coroutine 2 completed")
}
}
Thread.sleep(5000)
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/playground/exceptionhandling/4_launch_and_async.kt
================================================
package com.demo.code.playground.exceptionhandling
import kotlinx.coroutines.*
fun main() {
val exceptionHandler = CoroutineExceptionHandler { context, exception ->
println("Caught $exception in CoroutineExceptionHandler")
}
val scope = CoroutineScope(Job() + exceptionHandler)
scope.async {
val deferred = async {
delay(200)
throw RuntimeException()
}
}
Thread.sleep(1000)
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/playground/exceptionhandling/5_exception_handling_specifics_coroutineScope.kt
================================================
package com.demo.code.playground.exceptionhandling
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
fun main() = runBlocking() {
try {
doSomeThingSuspend()
} catch (e: Exception) {
println("Caught $e")
}
}
private suspend fun doSomeThingSuspend() {
coroutineScope {
launch {
throw RuntimeException()
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/playground/exceptionhandling/6_exception_handling_specifics_supervisorScope.kt
================================================
package com.demo.code.playground.exceptionhandling
import kotlinx.coroutines.*
fun main() {
val ceh = CoroutineExceptionHandler { coroutineContext, throwable ->
println("Caught $throwable in CoroutineExceptionHandler")
}
val scope = CoroutineScope(Job())
scope.launch(ceh) {
try {
supervisorScope {
launch {
println("CEH: ${coroutineContext[CoroutineExceptionHandler]}")
throw RuntimeException()
}
}
} catch (e: Exception) {
println("Caught $e")
}
}
Thread.sleep(100)
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/playground/fundamentals/10_how_delay_works.kt
================================================
package com.demo.code.playground.fundamentals
import android.os.Handler
import android.os.Looper
import kotlinx.coroutines.async
import kotlinx.coroutines.joinAll
import kotlinx.coroutines.runBlocking
fun main() = runBlocking {
println("main starts")
joinAll(
async { delayDemonstration(1, 500) },
async { delayDemonstration(2, 300) }
)
println("main ends")
}
suspend fun delayDemonstration(number: Int, delay: Long) {
println("Coroutine $number starts work")
// delay(delay)
Handler(Looper.getMainLooper())
.postDelayed({
println("Coroutine $number has finished")
}, 500)
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/playground/fundamentals/1_routines.kt
================================================
package com.demo.code.playground.fundamentals
fun main() {
println("main starts")
routine(1, 500)
routine(2, 300)
println("main ends")
}
fun routine(number: Int, delay: Long) {
println("Routine $number starts work")
Thread.sleep(delay)
println("Routine $number has finished")
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/playground/fundamentals/2_coroutines.kt
================================================
package com.demo.code.playground.fundamentals
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.joinAll
import kotlinx.coroutines.runBlocking
fun main() = runBlocking {
println("main starts")
joinAll(
async { coroutine(1, 500) },
async { coroutine(2, 300) }
)
println("main ends")
}
suspend fun coroutine(number: Int, delay: Long) {
println("Coroutine $number starts work")
delay(delay)
println("Coroutine $number has finished")
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/playground/fundamentals/3_routines_threads.kt
================================================
package com.demo.code.playground.fundamentals
import kotlin.concurrent.thread
fun main() {
println("main starts")
threadRoutine(1, 500)
threadRoutine(2, 300)
Thread.sleep(1000)
println("main ends")
}
fun threadRoutine(number: Int, delay: Long) {
thread {
println("Routine $number starts work")
Thread.sleep(delay)
println("Routine $number has finished")
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/playground/fundamentals/4_coroutines_with_thread_info.kt
================================================
package com.demo.code.playground.fundamentals
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.joinAll
import kotlinx.coroutines.runBlocking
fun main() = runBlocking {
println("main starts")
joinAll(
async { threadInfoCoroutine(1, 500) },
async { threadInfoCoroutine(2, 300) }
)
println("main ends")
}
suspend fun threadInfoCoroutine(number: Int, delay: Long) {
println("Coroutine $number starts work on ${Thread.currentThread().name}")
delay(delay)
println("Coroutine $number has finished on ${Thread.currentThread().name}")
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/playground/fundamentals/5_starting_lots_of_coroutines.kt
================================================
package com.demo.code.playground.fundamentals
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
fun main() = runBlocking {
repeat(1_000_000) {
launch {
delay(5000)
print(".")
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/playground/fundamentals/7_starting_lots_of_threads.kt
================================================
package com.demo.code.playground.fundamentals
import kotlin.concurrent.thread
fun main() {
repeat(1_000_000) {
thread {
Thread.sleep(5000)
print(".")
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/playground/fundamentals/8_suspending_coroutines.kt
================================================
package com.demo.code.playground.fundamentals
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.joinAll
import kotlinx.coroutines.runBlocking
fun main() = runBlocking {
println("main starts")
joinAll(
async { suspendingCoroutine(1, 500) },
async { suspendingCoroutine(2, 300) },
async {
repeat(5) {
println("other tasks is working on ${Thread.currentThread().name}")
delay(100)
}
}
)
println("main ends")
}
suspend fun suspendingCoroutine(number: Int, delay: Long) {
println("Coroutine $number starts work on ${Thread.currentThread().name}")
delay(delay)
println("Coroutine $number has finished on ${Thread.currentThread().name}")
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/playground/fundamentals/9_coroutine_in_different_threads.kt
================================================
package com.demo.code.playground.fundamentals
import kotlinx.coroutines.*
fun main() = runBlocking {
println("main starts")
joinAll(
async { threadSwitchingCoroutine(1, 500) },
async { threadSwitchingCoroutine(2, 300) }
)
println("main ends")
}
suspend fun threadSwitchingCoroutine(number: Int, delay: Long) {
println("Coroutine $number starts work on ${Thread.currentThread().name}")
delay(delay)
withContext(Dispatchers.Default) {
println("Coroutine $number has finished on ${Thread.currentThread().name}")
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/playground/structuredconcurrency/1_coroutines_need_to_be_started_in_scope.kt
================================================
package com.demo.code.playground.structuredconcurrency
import kotlinx.coroutines.*
val scope = CoroutineScope(Dispatchers.Default)
fun main() = runBlocking {
val job = scope.launch {
delay(100)
println("Coroutine completed")
}
job.invokeOnCompletion { throwable ->
if (throwable is CancellationException) {
println("Coroutine was cancelled")
}
}
delay(50)
onDestroy()
}
fun onDestroy() {
println("life-time of scope ends")
scope.cancel()
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/playground/structuredconcurrency/2_job_hierarchy.kt
================================================
package com.demo.code.playground.structuredconcurrency
import kotlinx.coroutines.*
fun main() {
val scopeJob = Job()
val scope = CoroutineScope(Dispatchers.Default + scopeJob)
val passedJob = Job()
val coroutineJob = scope.launch(passedJob) {
println("Starting coroutine")
delay(1000)
}
println("passedJob and coroutineJob are references to the same job object: ${passedJob === coroutineJob}")
println("Is coroutineJob a child of scopeJob? =>${scopeJob.children.contains(coroutineJob)}")
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/playground/structuredconcurrency/3_parents_wait_for_children.kt
================================================
package com.demo.code.playground.structuredconcurrency
import kotlinx.coroutines.*
fun main() = runBlocking {
val scope = CoroutineScope(Dispatchers.Default)
val parentCoroutineJob = scope.launch {
launch {
delay(1000)
println("Child Coroutine 1 has completed!")
}
launch {
delay(1000)
println("Child Coroutine 2 has completed!")
}
}
parentCoroutineJob.join()
println("Parent Coroutine has completed!")
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/playground/structuredconcurrency/4_cancelling_parents_and_children.kt
================================================
package com.demo.code.playground.structuredconcurrency
import kotlinx.coroutines.*
fun main() = runBlocking {
val scope = CoroutineScope(Dispatchers.Default)
scope.coroutineContext[Job]!!.invokeOnCompletion { throwable ->
if (throwable is CancellationException) {
println("Parent job was cancelled")
}
}
val childCoroutine1Job = scope.launch {
delay(1000)
println("Coroutine 1 completed")
}
childCoroutine1Job.invokeOnCompletion { throwable ->
if (throwable is CancellationException) {
println("Coroutine 1 was cancelled!")
}
}
scope.launch {
delay(1000)
println("Coroutine 2 completed")
}.invokeOnCompletion { throwable ->
if (throwable is CancellationException) {
println("Coroutine 2 was cancelled!")
}
}
delay(200)
childCoroutine1Job.cancelAndJoin()
// scope.coroutineContext[Job]!!.cancelAndJoin()
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/playground/structuredconcurrency/5_exception_propagation.kt
================================================
package com.demo.code.playground.structuredconcurrency
import kotlinx.coroutines.*
fun main() {
val exceptionHandler = CoroutineExceptionHandler { context, exception ->
println("Caught exception $exception")
}
val scope = CoroutineScope(SupervisorJob() + exceptionHandler)
scope.launch {
println("Coroutine 1 starts")
delay(50)
println("Coroutine 1 fails")
throw RuntimeException()
}
scope.launch {
println("Coroutine 2 starts")
delay(500)
println("Coroutine 2 completed")
}.invokeOnCompletion { throwable ->
if (throwable is CancellationException) {
println("Coroutine 2 got cancelled!")
}
}
Thread.sleep(1000)
println("Scope got cancelled: ${!scope.isActive}")
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/playground/structuredconcurrency/6_globalscope.kt
================================================
package com.demo.code.playground.structuredconcurrency
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
fun main() {
println("Job of GlobalScope: ${GlobalScope.coroutineContext[Job]}")
GlobalScope.launch {
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/playground/structuredconcurrency/7_scoping_functions.kt
================================================
package com.demo.code.playground.structuredconcurrency
import kotlinx.coroutines.*
fun main() {
val scope = CoroutineScope(Job())
scope.launch {
doSomeTasks()
launch {
println("Starting Task 3")
delay(300)
println("Task 3 completed")
}
}
Thread.sleep(1000)
}
suspend fun doSomeTasks() = coroutineScope {
launch {
println("Starting Task 1")
delay(100)
println("Task 1 completed")
}
launch {
println("Starting Task 2")
delay(200)
println("Task 2 completed")
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/channels/usecase1/ChannelUseCase1Activity.kt
================================================
package com.demo.code.usecases.channels.usecase1
import android.os.Bundle
import com.demo.code.base.BaseActivity
import com.demo.code.databinding.ActivityChannelsUsecase1Binding
class ChannelUseCase1Activity : BaseActivity() {
private val binding by lazy { ActivityChannelsUsecase1Binding.inflate(layoutInflater) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
}
override fun getToolbarTitle() = "Channel Use Case 1"
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase1/MockApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase1
import com.google.gson.Gson
import com.demo.code.mock.createMockApi
import com.demo.code.mock.mockAndroidVersions
import com.demo.code.utils.MockNetworkInterceptor
fun mockApi() =
createMockApi(
MockNetworkInterceptor()
.mock(
"http://localhost/recent-android-versions",
Gson().toJson(mockAndroidVersions),
200,
1500
)
)
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase1/PerformSingleNetworkRequestActivity.kt
================================================
package com.demo.code.usecases.coroutines.usecase1
import android.os.Bundle
import androidx.activity.viewModels
import androidx.lifecycle.Observer
import com.demo.code.base.BaseActivity
import com.demo.code.base.useCase1Description
import com.demo.code.databinding.ActivityPerformsinglenetworkrequestBinding
import com.demo.code.utils.fromHtml
import com.demo.code.utils.setGone
import com.demo.code.utils.setVisible
import com.demo.code.utils.toast
class PerformSingleNetworkRequestActivity : BaseActivity() {
override fun getToolbarTitle() = useCase1Description
private val binding by lazy { ActivityPerformsinglenetworkrequestBinding.inflate(layoutInflater) }
private val viewModel: PerformSingleNetworkRequestViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
viewModel.uiState().observe(this, Observer { uiState ->
if (uiState != null) {
render(uiState)
}
})
binding.btnPerformSingleNetworkRequest.setOnClickListener {
viewModel.performSingleNetworkRequest()
}
}
private fun render(uiState: UiState) {
when (uiState) {
is UiState.Loading -> {
onLoad()
}
is UiState.Success -> {
onSuccess(uiState)
}
is UiState.Error -> {
onError(uiState)
}
}
}
private fun onLoad() = with(binding) {
progressBar.setVisible()
textViewResult.text = ""
btnPerformSingleNetworkRequest.isEnabled = false
}
private fun onSuccess(uiState: UiState.Success) = with(binding) {
progressBar.setGone()
btnPerformSingleNetworkRequest.isEnabled = true
val readableVersions = uiState.recentVersions.map { "API ${it.apiLevel}: ${it.name}" }
textViewResult.text = fromHtml(
"Recent Android Versions ${readableVersions.joinToString(separator = " ")}"
)
}
private fun onError(uiState: UiState.Error) = with(binding) {
progressBar.setGone()
btnPerformSingleNetworkRequest.isEnabled = true
toast(uiState.message)
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase1/PerformSingleNetworkRequestViewModel.kt
================================================
package com.demo.code.usecases.coroutines.usecase1
import androidx.lifecycle.viewModelScope
import com.demo.code.base.BaseViewModel
import com.demo.code.mock.MockApi
import kotlinx.coroutines.launch
import timber.log.Timber
class PerformSingleNetworkRequestViewModel(
private val mockApi: MockApi = mockApi()
) : BaseViewModel() {
fun performSingleNetworkRequest() {
uiState.value = UiState.Loading
viewModelScope.launch {
try {
val recentAndroidVersions = mockApi.getRecentAndroidVersions()
uiState.value = UiState.Success(recentAndroidVersions)
} catch (exception: Exception) {
Timber.e(exception)
uiState.value = UiState.Error("Network Request failed!")
}
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase1/UiState.kt
================================================
package com.demo.code.usecases.coroutines.usecase1
import com.demo.code.mock.AndroidVersion
sealed class UiState {
object Loading : UiState()
data class Success(val recentVersions: List) : UiState()
data class Error(val message: String) : UiState()
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase10/CalculationInBackgroundActivity.kt
================================================
package com.demo.code.usecases.coroutines.usecase10
import android.os.Bundle
import androidx.activity.viewModels
import androidx.lifecycle.Observer
import com.demo.code.R
import com.demo.code.base.BaseActivity
import com.demo.code.base.useCase10Description
import com.demo.code.databinding.ActivityCalculationinbackgroundBinding
import com.demo.code.utils.hideKeyboard
import com.demo.code.utils.setGone
import com.demo.code.utils.setVisible
import com.demo.code.utils.toast
class CalculationInBackgroundActivity : BaseActivity() {
override fun getToolbarTitle() = useCase10Description
private val binding by lazy { ActivityCalculationinbackgroundBinding.inflate(layoutInflater) }
private val viewModel: CalculationInBackgroundViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
viewModel.uiState().observe(this, Observer { uiState ->
if (uiState != null) {
render(uiState)
}
})
binding.btnCalculate.setOnClickListener {
val factorialOf = binding.editTextFactorialOf.text.toString().toIntOrNull()
if (factorialOf != null) {
viewModel.performCalculation(factorialOf)
}
}
}
private fun render(uiState: UiState) {
when (uiState) {
is UiState.Loading -> {
onLoad()
}
is UiState.Success -> {
onSuccess(uiState)
}
is UiState.Error -> {
onError(uiState)
}
}
}
private fun onLoad() = with(binding) {
progressBar.setVisible()
textViewResult.text = ""
textViewCalculationDuration.text = ""
textViewStringConversionDuration.text = ""
btnCalculate.isEnabled = false
textViewResult.hideKeyboard()
}
private fun onSuccess(uiState: UiState.Success) = with(binding) {
textViewCalculationDuration.text =
getString(R.string.duration_calculation, uiState.computationDuration)
textViewStringConversionDuration.text =
getString(R.string.duration_stringconversion, uiState.stringConversionDuration)
progressBar.setGone()
btnCalculate.isEnabled = true
textViewResult.text = if (uiState.result.length <= 150) {
uiState.result
} else {
"${uiState.result.substring(0, 147)}..."
}
}
private fun onError(uiState: UiState.Error) = with(binding) {
progressBar.setGone()
btnCalculate.isEnabled = true
toast(uiState.message)
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase10/CalculationInBackgroundViewModel.kt
================================================
package com.demo.code.usecases.coroutines.usecase10
import androidx.lifecycle.viewModelScope
import com.demo.code.base.BaseViewModel
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.math.BigInteger
import kotlin.system.measureTimeMillis
class CalculationInBackgroundViewModel(
private val defaultDispatcher: CoroutineDispatcher = Dispatchers.Default
) : BaseViewModel() {
fun performCalculation(factorialOf: Int) {
uiState.value = UiState.Loading
viewModelScope.launch {
try {
var result: BigInteger = BigInteger.ZERO
val computationDuration = measureTimeMillis {
result = calculateFactorialOf(factorialOf)
}
var resultString = ""
val stringConversionDuration = measureTimeMillis {
resultString = convertToString(result)
}
uiState.value =
UiState.Success(resultString, computationDuration, stringConversionDuration)
} catch (exception: Exception) {
UiState.Error("Error while calculating result")
}
}
}
// factorial of n (n!) = 1 * 2 * 3 * 4 * ... * n
private suspend fun calculateFactorialOf(number: Int): BigInteger =
withContext(defaultDispatcher) {
var factorial = BigInteger.ONE
for (i in 1..number) {
factorial = factorial.multiply(BigInteger.valueOf(i.toLong()))
}
factorial
}
private suspend fun convertToString(number: BigInteger): String =
withContext(defaultDispatcher) {
number.toString()
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase10/UiState.kt
================================================
package com.demo.code.usecases.coroutines.usecase10
sealed class UiState {
object Loading : UiState()
data class Success(
val result: String,
val computationDuration: Long,
val stringConversionDuration: Long
) : UiState()
data class Error(val message: String) : UiState()
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase11/CooperativeCancellationActivity.kt
================================================
package com.demo.code.usecases.coroutines.usecase11
import android.os.Bundle
import androidx.activity.viewModels
import androidx.lifecycle.Observer
import com.demo.code.R
import com.demo.code.base.BaseActivity
import com.demo.code.base.useCase11Description
import com.demo.code.databinding.ActivityCooperativecancellationBinding
import com.demo.code.utils.hideKeyboard
import com.demo.code.utils.setGone
import com.demo.code.utils.setVisible
import com.demo.code.utils.toast
class CooperativeCancellationActivity : BaseActivity() {
override fun getToolbarTitle() = useCase11Description
private val binding by lazy { ActivityCooperativecancellationBinding.inflate(layoutInflater) }
private val viewModel: CooperativeCancellationViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
viewModel.uiState().observe(this, Observer { uiState ->
if (uiState != null) {
render(uiState)
}
})
binding.btnCalculate.setOnClickListener {
val factorialOf = binding.editTextFactorialOf.text.toString().toIntOrNull()
if (factorialOf != null) {
viewModel.performCalculation(factorialOf)
}
}
binding.btnCancel.setOnClickListener {
viewModel.cancelCalculation()
}
}
private fun render(uiState: UiState) {
when (uiState) {
is UiState.Loading -> {
onLoad()
}
is UiState.Success -> {
onSuccess(uiState)
}
is UiState.Error -> {
onError(uiState)
}
}
}
private fun onLoad() = with(binding) {
progressBar.setVisible()
textViewResult.text = ""
textViewCalculationDuration.text = ""
textViewStringConversionDuration.text = ""
btnCalculate.isEnabled = false
btnCancel.isEnabled = true
textViewResult.hideKeyboard()
}
private fun onSuccess(uiState: UiState.Success) = with(binding) {
textViewCalculationDuration.text =
getString(R.string.duration_calculation, uiState.computationDuration)
textViewStringConversionDuration.text =
getString(R.string.duration_stringconversion, uiState.stringConversionDuration)
binding.progressBar.setGone()
btnCalculate.isEnabled = true
btnCancel.isEnabled = false
textViewResult.text = if (uiState.result.length <= 150) {
uiState.result
} else {
"${uiState.result.substring(0, 147)}..."
}
}
private fun onError(uiState: UiState.Error) = with(binding) {
progressBar.setGone()
btnCalculate.isEnabled = true
btnCancel.isEnabled = false
toast(uiState.message)
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase11/CooperativeCancellationViewModel.kt
================================================
package com.demo.code.usecases.coroutines.usecase11
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.*
import java.math.BigInteger
import kotlin.system.measureTimeMillis
class CooperativeCancellationViewModel(
private val defaultDispatcher: CoroutineDispatcher = Dispatchers.Default
) : ViewModel() {
private var calculationJob: Job? = null
fun performCalculation(factorialOf: Int) {
uiState.value = UiState.Loading
calculationJob = viewModelScope.launch {
try {
var result: BigInteger = BigInteger.ZERO
val computationDuration = measureTimeMillis {
result = calculateFactorialOf(factorialOf)
}
var resultString = ""
val stringConversionDuration = measureTimeMillis {
resultString = convertToString(result)
}
uiState.value =
UiState.Success(resultString, computationDuration, stringConversionDuration)
} catch (exception: Exception) {
uiState.value = if (exception is CancellationException) {
UiState.Error("Calculation was cancelled")
} else {
UiState.Error("Error while calculating result")
}
}
}
}
// factorial of n (n!) = 1 * 2 * 3 * 4 * ... * n
private suspend fun calculateFactorialOf(number: Int): BigInteger =
withContext(defaultDispatcher) {
var factorial = BigInteger.ONE
for (i in 1..number) {
// yield enables cooperative cancellations
// alternatives:
// - ensureActive()
// - isActive() - possible to do clean up tasks with
yield()
factorial = factorial.multiply(BigInteger.valueOf(i.toLong()))
}
factorial
}
private suspend fun convertToString(number: BigInteger): String =
withContext(defaultDispatcher) {
number.toString()
}
fun uiState(): LiveData = uiState
fun cancelCalculation() {
calculationJob?.cancel()
}
private val uiState: MutableLiveData = MutableLiveData()
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase11/UiState.kt
================================================
package com.demo.code.usecases.coroutines.usecase11
sealed class UiState {
object Loading : UiState()
data class Success(
val result: String,
val computationDuration: Long,
val stringConversionDuration: Long
) : UiState()
data class Error(val message: String) : UiState()
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase12/CalculationInSeveralCoroutinesActivity.kt
================================================
package com.demo.code.usecases.coroutines.usecase12
import android.os.Bundle
import androidx.activity.viewModels
import androidx.lifecycle.Observer
import com.demo.code.R
import com.demo.code.base.BaseActivity
import com.demo.code.base.useCase12Description
import com.demo.code.databinding.ActivityCalculationinmultiplebackgroundthreadsBinding
import com.demo.code.utils.hideKeyboard
import com.demo.code.utils.setGone
import com.demo.code.utils.setVisible
import com.demo.code.utils.toast
class CalculationInSeveralCoroutinesActivity : BaseActivity() {
override fun getToolbarTitle() = useCase12Description
private val binding by lazy {
ActivityCalculationinmultiplebackgroundthreadsBinding.inflate(
layoutInflater
)
}
private val viewModel: CalculationInSeveralCoroutinesViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
viewModel.uiState()
.observe(this, Observer { uiState ->
if (uiState != null) {
render(uiState)
}
})
binding.btnCalculate.setOnClickListener {
val factorialOf = binding.editTextFactorialOf.text.toString().toIntOrNull()
val numberOfThreads = binding.editTextNumberOfThreads.text.toString().toIntOrNull()
if (factorialOf != null && numberOfThreads != null) {
viewModel.performCalculation(
factorialOf,
numberOfThreads
)
}
}
}
private fun render(uiState: UiState) {
when (uiState) {
is UiState.Loading -> {
onLoad()
}
is UiState.Success -> {
onSuccess(uiState)
}
is UiState.Error -> {
onError(uiState)
}
}
}
private fun onLoad() = with(binding) {
progressBar.setVisible()
textViewResult.text = ""
textViewDuration.text = ""
textViewStringConversionDuration.text = ""
btnCalculate.isEnabled = false
textViewResult.hideKeyboard()
}
private fun onSuccess(uiState: UiState.Success) = with(binding) {
textViewDuration.text =
getString(R.string.duration_calculation, uiState.computationDuration)
textViewStringConversionDuration.text =
getString(R.string.duration_stringconversion, uiState.stringConversionDuration)
progressBar.setGone()
btnCalculate.isEnabled = true
textViewResult.text = if (uiState.result.length <= 150) {
uiState.result
} else {
"${uiState.result.substring(0, 147)}..."
}
}
private fun onError(uiState: UiState.Error) = with(binding) {
progressBar.setGone()
btnCalculate.isEnabled = true
toast(uiState.message)
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase12/CalculationInSeveralCoroutinesViewModel.kt
================================================
package com.demo.code.usecases.coroutines.usecase12
import androidx.lifecycle.viewModelScope
import com.demo.code.base.BaseViewModel
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.math.BigInteger
import kotlin.system.measureTimeMillis
class CalculationInSeveralCoroutinesViewModel(
private val factorialCalculator: FactorialCalculator = FactorialCalculator(),
private val defaultDispatcher: CoroutineDispatcher = Dispatchers.Default
) : BaseViewModel() {
fun performCalculation(
factorialOf: Int,
numberOfCoroutines: Int
) {
uiState.value = UiState.Loading
viewModelScope.launch {
var factorialResult = BigInteger.ZERO
val computationDuration = measureTimeMillis {
factorialResult =
factorialCalculator.calculateFactorial(
factorialOf,
numberOfCoroutines
)
}
var resultString = ""
val stringConversionDuration = measureTimeMillis {
resultString = convertToString(factorialResult)
}
uiState.value =
UiState.Success(resultString, computationDuration, stringConversionDuration)
}
}
private suspend fun convertToString(
number: BigInteger
): String =
withContext(defaultDispatcher) {
number.toString()
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase12/FactorialCalculator.kt
================================================
package com.demo.code.usecases.coroutines.usecase12
import com.demo.code.utils.addCoroutineDebugInfo
import kotlinx.coroutines.*
import timber.log.Timber
import java.math.BigInteger
class FactorialCalculator(
private val defaultDispatcher: CoroutineDispatcher = Dispatchers.Default
) {
suspend fun calculateFactorial(
factorialOf: Int,
numberOfCoroutines: Int
): BigInteger {
return withContext(defaultDispatcher) {
val subRanges = createSubRangeList(factorialOf, numberOfCoroutines)
subRanges.map { subRange ->
async {
calculateFactorialOfSubRange(subRange)
}
}.awaitAll()
.fold(BigInteger.ONE, { acc, element ->
ensureActive()
acc.multiply(element)
})
}
}
suspend fun calculateFactorialOfSubRange(
subRange: SubRange
): BigInteger {
return withContext(defaultDispatcher) {
Timber.d(addCoroutineDebugInfo("Calculate factorial of $subRange"))
var factorial = BigInteger.ONE
for (i in subRange.start..subRange.end) {
ensureActive()
factorial = factorial.multiply(BigInteger.valueOf(i.toLong()))
}
factorial
}
}
fun createSubRangeList(
factorialOf: Int,
numberOfSubRanges: Int
): List {
val quotient = factorialOf.div(numberOfSubRanges)
val rangesList = mutableListOf()
var curStartIndex = 1
repeat(numberOfSubRanges - 1) {
rangesList.add(
SubRange(
curStartIndex,
curStartIndex + (quotient - 1)
)
)
curStartIndex += quotient
}
rangesList.add(SubRange(curStartIndex, factorialOf))
return rangesList
}
}
data class SubRange(val start: Int, val end: Int)
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase12/UiState.kt
================================================
package com.demo.code.usecases.coroutines.usecase12
sealed class UiState {
object Loading : UiState()
data class Success(
val result: String,
val computationDuration: Long,
val stringConversionDuration: Long
) : UiState()
data class Error(val message: String) : UiState()
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase13/ExceptionHandlingActivity.kt
================================================
package com.demo.code.usecases.coroutines.usecase13
import android.os.Bundle
import androidx.activity.viewModels
import androidx.lifecycle.Observer
import com.demo.code.R
import com.demo.code.base.BaseActivity
import com.demo.code.base.useCase13Description
import com.demo.code.databinding.ActivityExceptionhandlingBinding
import com.demo.code.utils.fromHtml
import com.demo.code.utils.setGone
import com.demo.code.utils.setVisible
import com.demo.code.utils.toast
class ExceptionHandlingActivity : BaseActivity() {
private val binding by lazy {
ActivityExceptionhandlingBinding.inflate(
layoutInflater
)
}
private val viewModel: ExceptionHandlingViewModel by viewModels()
override fun getToolbarTitle() = useCase13Description
private var operationStartTime = 0L
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
viewModel.uiState().observe(this, Observer { uiState ->
if (uiState != null) {
render(uiState)
}
})
binding.btnExceptionTryCatch.setOnClickListener {
viewModel.handleExceptionWithTryCatch()
}
binding.btnCoroutineExceptionHandler.setOnClickListener {
viewModel.handleWithCoroutineExceptionHandler()
}
binding.btnShowResultsEvenIfChildCoroutineFailsTryCatch.setOnClickListener {
viewModel.showResultsEvenIfChildCoroutineFails()
}
}
private fun render(uiState: UiState) {
when (uiState) {
is UiState.Loading -> {
onLoad()
}
is UiState.Success -> {
onSuccess(uiState)
}
is UiState.Error -> {
onError(uiState)
}
}
}
private fun onLoad() = with(binding) {
operationStartTime = System.currentTimeMillis()
progressBar.setVisible()
textViewDuration.text = ""
textViewResult.text = ""
disableButtons()
}
private fun onSuccess(uiState: UiState.Success) = with(binding) {
enableButtons()
progressBar.setGone()
val duration = System.currentTimeMillis() - operationStartTime
textViewDuration.text = getString(R.string.duration, duration)
val versionFeatures = uiState.versionFeatures
val versionFeaturesString = versionFeatures.joinToString(separator = " ") {
"New Features of ${it.androidVersion.name} ${it.features.joinToString(
prefix = "- ",
separator = " - "
)}"
}
textViewResult.text = fromHtml(versionFeaturesString)
}
private fun onError(uiState: UiState.Error) = with(binding) {
progressBar.setGone()
textViewDuration.setGone()
toast(uiState.message)
enableButtons()
}
private fun enableButtons() = with(binding) {
btnExceptionTryCatch.isEnabled = true
btnCoroutineExceptionHandler.isEnabled = true
btnShowResultsEvenIfChildCoroutineFailsTryCatch.isEnabled = true
}
private fun disableButtons() = with(binding) {
btnExceptionTryCatch.isEnabled = false
btnCoroutineExceptionHandler.isEnabled = false
btnShowResultsEvenIfChildCoroutineFailsTryCatch.isEnabled = false
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase13/ExceptionHandlingViewModel.kt
================================================
package com.demo.code.usecases.coroutines.usecase13
import androidx.lifecycle.viewModelScope
import com.demo.code.base.BaseViewModel
import com.demo.code.mock.MockApi
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import timber.log.Timber
class ExceptionHandlingViewModel(
private val api: MockApi = mockApi()
) : BaseViewModel() {
fun handleExceptionWithTryCatch() {
uiState.value = UiState.Loading
viewModelScope.launch {
try {
api.getAndroidVersionFeatures(27)
} catch (exception: Exception) {
uiState.value = UiState.Error("Network Request failed: $exception")
}
}
}
fun handleWithCoroutineExceptionHandler() {
val exceptionHandler = CoroutineExceptionHandler { _, exception ->
uiState.value = UiState.Error("Network Request failed!! $exception")
}
uiState.value = UiState.Loading
viewModelScope.launch(exceptionHandler) {
api.getAndroidVersionFeatures(27)
}
}
fun showResultsEvenIfChildCoroutineFails() {
uiState.value = UiState.Loading
viewModelScope.launch {
//supervisorScope {
val oreoFeaturesDeferred = async { api.getAndroidVersionFeatures(27) }
val pieFeaturesDeferred = async { api.getAndroidVersionFeatures(28) }
val android10FeaturesDeferred = async { api.getAndroidVersionFeatures(29) }
val versionFeatures = listOf(
oreoFeaturesDeferred,
pieFeaturesDeferred,
android10FeaturesDeferred
).mapNotNull {
try {
it.await()
} catch (exception: Exception) {
// We have to re-throw cancellation exceptions so that
// our Coroutine gets cancelled immediately.
// Otherwise, the CancellationException is ignored
// and the Coroutine keeps running until it reaches the next
// suspension point.
if (exception is CancellationException) {
throw exception
}
Timber.e("Error loading feature data!")
null
}
}
uiState.value = UiState.Success(versionFeatures)
//}
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase13/MockApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase13
import com.google.gson.Gson
import com.demo.code.mock.*
import com.demo.code.utils.MockNetworkInterceptor
fun mockApi() = createMockApi(
MockNetworkInterceptor()
.mock(
"http://localhost/recent-android-versions",
Gson().toJson(mockAndroidVersions),
200,
1000
)
.mock(
"http://localhost/android-version-features/27",
Gson().toJson(mockVersionFeaturesOreo),
MockNetworkInterceptor.INTERNAL_SERVER_ERROR_HTTP_CODE,
100
)
.mock(
"http://localhost/android-version-features/28",
Gson().toJson(mockVersionFeaturesPie),
200,
1000
)
.mock(
"http://localhost/android-version-features/29",
Gson().toJson(mockVersionFeaturesAndroid10),
200,
1000
)
)
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase13/UiState.kt
================================================
package com.demo.code.usecases.coroutines.usecase13
import com.demo.code.mock.VersionFeatures
sealed class UiState {
object Loading : UiState()
data class Success(
val versionFeatures: List
) : UiState()
data class Error(val message: String) : UiState()
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase14/AndroidVersionDao.kt
================================================
package com.demo.code.usecases.coroutines.usecase14
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
@Dao
interface AndroidVersionDao {
@Query("SELECT * FROM androidversions")
suspend fun getAndroidVersions(): List
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(androidVersionEntity: AndroidVersionEntity)
@Query("DELETE FROM androidversions")
suspend fun clear()
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase14/AndroidVersionDatabase.kt
================================================
package com.demo.code.usecases.coroutines.usecase14
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
@Database(entities = [AndroidVersionEntity::class], version = 1, exportSchema = false)
abstract class AndroidVersionDatabase : RoomDatabase() {
abstract fun androidVersionDao(): AndroidVersionDao
companion object {
private var INSTANCE: AndroidVersionDatabase? = null
fun getInstance(context: Context): AndroidVersionDatabase {
if (INSTANCE == null) {
synchronized(AndroidVersionDatabase::class) {
INSTANCE = buildRoomDb(context)
}
}
return INSTANCE!!
}
private fun buildRoomDb(context: Context) =
Room.databaseBuilder(
context.applicationContext,
AndroidVersionDatabase::class.java,
"androidversions_usecase12.db"
).build()
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase14/AndroidVersionEntity.kt
================================================
package com.demo.code.usecases.coroutines.usecase14
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.demo.code.mock.AndroidVersion
@Entity(tableName = "androidversions")
data class AndroidVersionEntity(@PrimaryKey val apiLevel: Int, val name: String)
fun AndroidVersionEntity.mapToUiModel() = AndroidVersion(this.apiLevel, this.name)
fun List.mapToUiModelList() = map {
it.mapToUiModel()
}
fun AndroidVersion.mapToEntity() = AndroidVersionEntity(this.apiLevel, this.name)
fun List.mapToEntityList() = map {
it.mapToEntity()
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase14/AndroidVersionRepository.kt
================================================
package com.demo.code.usecases.coroutines.usecase14
import com.demo.code.mock.AndroidVersion
import com.demo.code.mock.MockApi
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import timber.log.Timber
class AndroidVersionRepository(
private var database: AndroidVersionDao,
private val scope: CoroutineScope,
private val api: MockApi = mockApi()
) {
suspend fun getLocalAndroidVersions(): List {
return database.getAndroidVersions().mapToUiModelList()
}
suspend fun loadAndStoreRemoteAndroidVersions(): List {
return scope.async {
val recentVersions = api.getRecentAndroidVersions()
Timber.d("Recent Android versions loaded")
for (recentVersion in recentVersions) {
Timber.d("Insert $recentVersion to database")
database.insert(recentVersion.mapToEntity())
}
recentVersions
}.await()
}
fun clearDatabase() {
scope.launch {
database.clear()
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase14/ContinueCoroutineWhenUserLeavesScreenActivity.kt
================================================
package com.demo.code.usecases.coroutines.usecase14
import android.os.Bundle
import androidx.activity.viewModels
import androidx.lifecycle.Observer
import com.demo.code.CoroutineUsecasesOnAndroidApplication
import com.demo.code.R
import com.demo.code.base.BaseActivity
import com.demo.code.base.useCase14Description
import com.demo.code.databinding.ActivityQueryfromroomdatabaseBinding
import com.demo.code.utils.fromHtml
import com.demo.code.utils.setGone
import com.demo.code.utils.setVisible
import com.demo.code.utils.toast
class ContinueCoroutineWhenUserLeavesScreenActivity : BaseActivity() {
override fun getToolbarTitle() = useCase14Description
private val binding by lazy { ActivityQueryfromroomdatabaseBinding.inflate(layoutInflater) }
private val viewModel: ContinueCoroutineWhenUserLeavesScreenViewModel by viewModels {
ViewModelFactory((application as CoroutineUsecasesOnAndroidApplication).androidVersionRepository)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
viewModel.uiState().observe(this, Observer { uiState ->
if (uiState != null) {
render(uiState)
}
})
binding.btnLoadData.setOnClickListener {
viewModel.loadData()
}
binding.btnClearDatabase.setOnClickListener {
viewModel.clearDatabase()
}
}
private fun render(uiState: UiState) {
when (uiState) {
is UiState.Loading -> {
onLoad(uiState)
}
is UiState.Success -> {
onSuccess(uiState)
}
is UiState.Error -> {
onError(uiState)
}
}
}
private fun onLoad(loadingState: UiState.Loading) = with(binding) {
when (loadingState) {
UiState.Loading.LoadFromDb -> {
progressBarLoadFromDb.setVisible()
textViewLoadFromDatabase.setVisible()
imageViewDatabaseLoadSuccessOrError.setGone()
}
UiState.Loading.LoadFromNetwork -> {
progressBarLoadFromNetwork.setVisible()
textViewLoadFromNetwork.setVisible()
imageViewNetworkLoadSuccessOrError.setGone()
}
}
}
private fun onSuccess(uiState: UiState.Success) = with(binding) {
when (uiState.dataSource) {
DataSource.Network -> {
progressBarLoadFromNetwork.setGone()
imageViewNetworkLoadSuccessOrError.setImageDrawable(getDrawable(R.drawable.ic_check_green_24dp))
imageViewNetworkLoadSuccessOrError.setVisible()
}
DataSource.Database -> {
progressBarLoadFromDb.setGone()
imageViewDatabaseLoadSuccessOrError.setImageDrawable(getDrawable(R.drawable.ic_check_green_24dp))
imageViewDatabaseLoadSuccessOrError.setVisible()
}
}
val readableVersions = uiState.recentVersions.map { "API ${it.apiLevel}: ${it.name}" }
textViewResult.text = fromHtml(
"Recent Android Versions [from ${uiState.dataSource.name}] ${readableVersions.joinToString(
separator = " "
)}"
)
}
private fun onError(uiState: UiState.Error) = with(binding) {
when (uiState.dataSource) {
is DataSource.Network -> {
progressBarLoadFromNetwork.setGone()
imageViewNetworkLoadSuccessOrError.setImageDrawable(getDrawable(R.drawable.ic_clear_red_24dp))
imageViewNetworkLoadSuccessOrError.setVisible()
}
is DataSource.Database -> {
progressBarLoadFromDb.setGone()
imageViewDatabaseLoadSuccessOrError.setImageDrawable(getDrawable(R.drawable.ic_clear_red_24dp))
imageViewDatabaseLoadSuccessOrError.setVisible()
}
}
toast(uiState.message)
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase14/ContinueCoroutineWhenUserLeavesScreenViewModel.kt
================================================
package com.demo.code.usecases.coroutines.usecase14
import androidx.lifecycle.viewModelScope
import com.demo.code.base.BaseViewModel
import kotlinx.coroutines.launch
class ContinueCoroutineWhenUserLeavesScreenViewModel(
private var repository: AndroidVersionRepository
) : BaseViewModel() {
// more information in this blogpost about "Coroutines & Patterns for work that shouldn't
// be cancelled" =>
// https://medium.com/androiddevelopers/coroutines-patterns-for-work-that-shouldnt-be-cancelled-e26c40f142ad
fun loadData() {
uiState.value = UiState.Loading.LoadFromDb
viewModelScope.launch {
val localVersions = repository.getLocalAndroidVersions()
if (localVersions.isNotEmpty()) {
uiState.value =
UiState.Success(DataSource.Database, localVersions)
} else {
uiState.value =
UiState.Error(DataSource.Database, "Database empty!")
}
uiState.value = UiState.Loading.LoadFromNetwork
try {
uiState.value = UiState.Success(
DataSource.Network,
repository.loadAndStoreRemoteAndroidVersions()
)
} catch (exception: Exception) {
uiState.value = UiState.Error(DataSource.Network, "Network Request failed")
}
}
}
fun clearDatabase() {
repository.clearDatabase()
}
}
sealed class DataSource(val name: String) {
object Database : DataSource("Database")
object Network : DataSource("Network")
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase14/MockApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase14
import com.google.gson.Gson
import com.demo.code.mock.createMockApi
import com.demo.code.mock.mockAndroidVersions
import com.demo.code.utils.MockNetworkInterceptor
fun mockApi() =
createMockApi(
MockNetworkInterceptor()
.mock(
"http://localhost/recent-android-versions",
Gson().toJson(mockAndroidVersions),
200,
5000
)
)
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase14/UiState.kt
================================================
package com.demo.code.usecases.coroutines.usecase14
import com.demo.code.mock.AndroidVersion
sealed class UiState {
sealed class Loading : UiState() {
object LoadFromDb : Loading()
object LoadFromNetwork : Loading()
}
data class Success(val dataSource: DataSource, val recentVersions: List) :
UiState()
data class Error(val dataSource: DataSource, val message: String) : UiState()
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase14/ViewModelFactory.kt
================================================
package com.demo.code.usecases.coroutines.usecase14
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
class ViewModelFactory(private val repository: AndroidVersionRepository?) :
ViewModelProvider.Factory {
override fun create(modelClass: Class): T {
return modelClass.getConstructor(AndroidVersionRepository::class.java)
.newInstance(repository)
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase15/AnalyticsWorker.kt
================================================
package com.demo.code.usecases.coroutines.usecase15
import android.content.Context
import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import com.demo.code.mock.createMockAnalyticsApi
import com.demo.code.utils.MockNetworkInterceptor
import timber.log.Timber
class AnalyticsWorker(appContext: Context, workerParameters: WorkerParameters) :
CoroutineWorker(appContext, workerParameters) {
private val analyticsApi = createMockAnalyticsApi()
override suspend fun doWork(): Result {
return try {
analyticsApi.trackScreenOpened()
Timber.d("Successfully tracked screen open event!")
Result.success()
} catch (exception: Exception) {
Timber.e("Tracking screen open event failed!")
Result.failure()
}
}
companion object {
fun createMockAnalyticsApi() = createMockAnalyticsApi(
MockNetworkInterceptor()
.mock(
"http://localhost/analytics/workmanager-screen-opened",
"true",
200,
1500
)
)
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase15/ViewModelFactory.kt
================================================
package com.demo.code.usecases.coroutines.usecase15
import android.content.Context
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
class ViewModelFactory(private val context: Context) :
ViewModelProvider.Factory {
override fun create(modelClass: Class): T {
return modelClass.getConstructor(Context::class.java)
.newInstance(context.applicationContext)
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase15/WorkManagerActivity.kt
================================================
package com.demo.code.usecases.coroutines.usecase15
import android.os.Bundle
import androidx.activity.viewModels
import com.demo.code.base.BaseActivity
import com.demo.code.base.useCase15Description
import com.demo.code.databinding.ActivityWorkmangerBinding
class WorkManagerActivity : BaseActivity() {
override fun getToolbarTitle() = useCase15Description
private val binding by lazy { ActivityWorkmangerBinding.inflate(layoutInflater) }
private val viewModel: WorkManagerViewModel by viewModels {
ViewModelFactory(this)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
viewModel.performAnalyticsRequest()
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase15/WorkManagerViewModel.kt
================================================
package com.demo.code.usecases.coroutines.usecase15
import android.content.Context
import androidx.lifecycle.ViewModel
import androidx.work.Constraints
import androidx.work.NetworkType
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import java.util.concurrent.TimeUnit
class WorkManagerViewModel(private val context: Context) : ViewModel() {
fun performAnalyticsRequest() {
val constraints =
Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build()
val request = OneTimeWorkRequestBuilder()
.setConstraints(constraints)
// Set a delay to not slow down other UI related requests that should run fast
.setInitialDelay(10, TimeUnit.SECONDS)
.addTag("analyitcs-work-request")
.build()
WorkManager.getInstance(context).enqueue(request)
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase16/FactorialCalculator.kt
================================================
package com.demo.code.usecases.coroutines.usecase16
import com.demo.code.utils.addCoroutineDebugInfo
import kotlinx.coroutines.*
import timber.log.Timber
import java.math.BigInteger
class FactorialCalculator {
suspend fun calculateFactorial(
factorialOf: Int,
numberOfThreads: Int,
dispatcher: CoroutineDispatcher,
yieldDuringCalculation: Boolean
): BigInteger {
val subRanges = createSubRangeList(factorialOf, numberOfThreads, dispatcher)
return withContext(dispatcher) {
subRanges.map { subRange ->
async {
calculateFactorialOfSubRange(subRange, yieldDuringCalculation)
}
}.awaitAll()
.fold(BigInteger.ONE, { acc, element ->
if (yieldDuringCalculation) {
yield()
}
acc.multiply(element)
})
}
}
private suspend fun calculateFactorialOfSubRange(
subRange: SubRange,
yieldDuringCalculation: Boolean
): BigInteger {
Timber.d(addCoroutineDebugInfo("Calculate factorial of $subRange"))
var factorial = BigInteger.ONE
for (i in subRange.start..subRange.end) {
if (yieldDuringCalculation) {
yield()
}
factorial = factorial.multiply(BigInteger.valueOf(i.toLong()))
}
return factorial
}
private suspend fun createSubRangeList(
factorialOf: Int,
numberOfSubRanges: Int,
dispatcher: CoroutineDispatcher
): List =
withContext(dispatcher) {
val quotient = factorialOf.div(numberOfSubRanges)
val rangesList = mutableListOf()
var curStartIndex = 1
repeat(numberOfSubRanges - 1) {
rangesList.add(
SubRange(
curStartIndex,
curStartIndex + (quotient - 1)
)
)
curStartIndex += quotient
}
rangesList.add(SubRange(curStartIndex, factorialOf))
rangesList
}
}
data class SubRange(val start: Int, val end: Int)
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase16/PerformanceAnalysisActivity.kt
================================================
package com.demo.code.usecases.coroutines.usecase16
import android.os.Bundle
import android.view.View
import android.widget.AdapterView
import android.widget.ArrayAdapter
import androidx.activity.viewModels
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager
import com.demo.code.R
import com.demo.code.base.BaseActivity
import com.demo.code.base.useCase16Description
import com.demo.code.databinding.ActivityPerformanceanalysisBinding
import com.demo.code.utils.setGone
import com.demo.code.utils.setVisible
import com.demo.code.utils.toast
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
class PerformanceAnalysisActivity : BaseActivity() {
override fun getToolbarTitle() = useCase16Description
private val binding by lazy {
ActivityPerformanceanalysisBinding.inflate(
layoutInflater
)
}
private val viewModel: PerformanceAnalysisViewModel by viewModels()
private lateinit var selectedDispatcher: CoroutineDispatcher
private val resultAdapter = ResultAdapter()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
val numberOfCores = Runtime.getRuntime().availableProcessors()
binding.textViewNumberOfCores.text = getString(R.string.device_cores, numberOfCores)
viewModel.uiState()
.observe(this@PerformanceAnalysisActivity, Observer { uiState ->
if (uiState != null) {
render(uiState)
}
})
binding.btnCalculate.setOnClickListener {
val factorialOf = binding.editTextFactorialOf.text.toString().toIntOrNull()
val numberOfThreads = binding.editTextNumberOfThreads.text.toString().toIntOrNull()
if (factorialOf != null && numberOfThreads != null) {
viewModel.performCalculation(
factorialOf,
numberOfThreads,
selectedDispatcher,
binding.switchYield.isChecked
)
}
}
ArrayAdapter.createFromResource(
this@PerformanceAnalysisActivity,
R.array.dispatchers,
android.R.layout.simple_spinner_item
).also { adapter ->
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
binding.spinnerDispatcher.adapter = adapter
}
binding.spinnerDispatcher.onItemSelectedListener =
object : AdapterView.OnItemSelectedListener {
override fun onNothingSelected(parent: AdapterView<*>?) {}
override fun onItemSelected(
parent: AdapterView<*>?,
view: View?,
position: Int,
id: Long
) {
when (parent?.getItemAtPosition(position)) {
"Default" -> selectedDispatcher = Dispatchers.Default
"IO" -> selectedDispatcher = Dispatchers.IO
"Main" -> selectedDispatcher = Dispatchers.Main
"Unconfined" -> selectedDispatcher = Dispatchers.Unconfined
}
}
}
initRecyclerView()
}
private fun initRecyclerView() {
binding.recyclerViewResults.apply {
adapter = resultAdapter
hasFixedSize()
layoutManager = LinearLayoutManager(this@PerformanceAnalysisActivity)
}
}
private fun render(uiState: UiState) {
when (uiState) {
is UiState.Loading -> {
onLoad()
}
is UiState.Success -> {
onSuccess(uiState)
}
is UiState.Error -> {
onError(uiState)
}
}
}
private fun onLoad() = with(binding) {
progressBar.setVisible()
btnCalculate.isEnabled = false
}
private fun onSuccess(uiState: UiState.Success) = with(binding) {
progressBar.setGone()
btnCalculate.isEnabled = true
resultAdapter.addResult(uiState)
}
private fun onError(uiState: UiState.Error) = with(binding) {
progressBar.setGone()
btnCalculate.isEnabled = true
toast(uiState.message)
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase16/PerformanceAnalysisViewModel.kt
================================================
package com.demo.code.usecases.coroutines.usecase16
import androidx.lifecycle.viewModelScope
import com.demo.code.base.BaseViewModel
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.math.BigInteger
import kotlin.system.measureTimeMillis
class PerformanceAnalysisViewModel(
private val factorialCalculator: FactorialCalculator = FactorialCalculator()
) : BaseViewModel() {
fun performCalculation(
factorialOf: Int,
numberOfCoroutines: Int,
dispatcher: CoroutineDispatcher,
yieldDuringCalculation: Boolean = true
) {
uiState.value = UiState.Loading
viewModelScope.launch {
var factorialResult = BigInteger.ZERO
val computationDuration = measureTimeMillis {
factorialResult =
factorialCalculator.calculateFactorial(
factorialOf,
numberOfCoroutines,
dispatcher,
yieldDuringCalculation
)
}
var resultString = ""
val stringConversionDuration = measureTimeMillis {
resultString = convertToString(factorialResult, dispatcher)
}
uiState.value =
UiState.Success(
resultString,
computationDuration,
stringConversionDuration,
factorialOf.toString(),
numberOfCoroutines.toString(),
dispatcher.toString(),
yieldDuringCalculation
)
}
}
private suspend fun convertToString(
number: BigInteger,
dispatcher: CoroutineDispatcher
): String =
withContext(dispatcher) {
number.toString()
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase16/ResultAdapter.kt
================================================
package com.demo.code.usecases.coroutines.usecase16
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.demo.code.R
import com.demo.code.databinding.RecyclerviewItemCalculationResultBinding
import kotlinx.android.synthetic.main.recyclerview_item_calculation_result.view.*
class ResultAdapter(
private val results: MutableList = mutableListOf()
) : RecyclerView.Adapter() {
class ViewHolder(
val layout: LinearLayout,
val factorialOf: TextView,
val numberOfCoroutines: TextView,
val dispatcher: TextView,
val yielding: TextView,
val calculationDuration: TextView,
val stringConversionDuration: TextView,
val computationResult: TextView
) :
RecyclerView.ViewHolder(layout)
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val layoutInflater = LayoutInflater.from(parent.context)
val binding =
RecyclerviewItemCalculationResultBinding.inflate(layoutInflater, parent, false)
val layout = binding.root.linearLayout as LinearLayout
return ViewHolder(
layout,
binding.textViewResultFactorialOf,
binding.textViewResultNumberCoroutines,
binding.textViewResultDispatcher,
binding.textViewResultYield,
binding.textViewDuration,
binding.textViewStringConversionDuration,
binding.textViewResult
)
}
fun addResult(state: UiState.Success) {
results.add(0, state)
notifyDataSetChanged()
}
override fun getItemCount() = results.size
override fun onBindViewHolder(holder: ViewHolder, position: Int) = with(holder) {
val result = results[position]
val context = layout.context
factorialOf.text = "Calculated factorial of ${result.factorialOf}"
numberOfCoroutines.text = "Coroutines: ${result.numberOfCoroutines}"
dispatcher.text = "Dispatcher: ${result.dispatcherName}"
yielding.text = "yield(): ${result.yieldDuringCalculation}"
calculationDuration.text =
context.getString(R.string.duration_calculation, result.computationDuration)
stringConversionDuration.text =
context.getString(R.string.duration_stringconversion, result.stringConversionDuration)
computationResult.text = if (result.result.length <= 150) {
"Result: ${result.result}"
} else {
"Result: ${result.result.substring(0, 147)}..."
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase16/UiState.kt
================================================
package com.demo.code.usecases.coroutines.usecase16
sealed class UiState {
object Loading : UiState()
data class Success(
val result: String,
val computationDuration: Long,
val stringConversionDuration: Long,
val factorialOf: String,
val numberOfCoroutines: String,
val dispatcherName: String,
val yieldDuringCalculation: Boolean
) : UiState()
data class Error(val message: String) : UiState()
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase17/PerformCalculationOnMainThreadActivity.kt
================================================
package com.demo.code.usecases.coroutines.usecase17
import android.os.Bundle
import androidx.activity.viewModels
import androidx.lifecycle.Observer
import com.demo.code.base.BaseActivity
import com.demo.code.base.useCase17Description
import com.demo.code.databinding.ActivityCalculateonmainBinding
import com.demo.code.utils.setGone
import com.demo.code.utils.setVisible
import com.demo.code.utils.toast
class PerformCalculationOnMainThreadActivity : BaseActivity() {
override fun getToolbarTitle() = useCase17Description
private val binding by lazy { ActivityCalculateonmainBinding.inflate(layoutInflater) }
private val viewModel: PerformCalculationOnMainThreadViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
viewModel.uiState().observe(this, Observer { uiState ->
if (uiState != null) {
render(uiState)
}
})
binding.btnCalculateOnMain.setOnClickListener {
val factorialOf = binding.editTextFactorialOf.text.toString().toIntOrNull()
if (factorialOf != null) {
viewModel.performCalculationOnMainThread(factorialOf)
}
}
binding.btnCalculateOnMainUsingYield.setOnClickListener {
val factorialOf = binding.editTextFactorialOf.text.toString().toIntOrNull()
if (factorialOf != null) {
viewModel.performCalculationOnMainThreadUsingYield(factorialOf)
}
}
binding.btnCalculateWithDefaultDispatcher.setOnClickListener {
val factorialOf = binding.editTextFactorialOf.text.toString().toIntOrNull()
if (factorialOf != null) {
viewModel.performCalculationWithDefaultDispatcher(factorialOf)
}
}
}
private fun render(uiState: UiState) {
when (uiState) {
is UiState.Loading -> {
onLoad()
}
is UiState.Success -> {
onSuccess(uiState)
}
is UiState.Error -> {
onError(uiState)
}
}
}
private fun onLoad() = with(binding) {
progressBar.setVisible()
textViewCalculationDuration.text = ""
btnCalculateOnMain.isEnabled = false
btnCalculateOnMainUsingYield.isEnabled = false
btnCalculateWithDefaultDispatcher.isEnabled = false
}
private fun onSuccess(uiState: UiState.Success) = with(binding) {
progressBar.setGone()
btnCalculateOnMain.isEnabled = true
btnCalculateOnMainUsingYield.isEnabled = true
btnCalculateWithDefaultDispatcher.isEnabled = true
textViewCalculationDuration.text =
"${uiState.thread}: Calculation took ${uiState.duration}ms"
}
private fun onError(uiState: UiState.Error) = with(binding) {
progressBar.setGone()
btnCalculateOnMain.isEnabled = true
btnCalculateOnMainUsingYield.isEnabled = true
btnCalculateWithDefaultDispatcher.isEnabled = true
toast(uiState.message)
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase17/PerformCalculationOnMainThreadViewModel.kt
================================================
package com.demo.code.usecases.coroutines.usecase17
import androidx.lifecycle.viewModelScope
import com.demo.code.base.BaseViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.coroutines.yield
import java.math.BigInteger
import kotlin.system.measureTimeMillis
class PerformCalculationOnMainThreadViewModel : BaseViewModel() {
fun performCalculationOnMainThread(factorialOf: Int) {
uiState.value = UiState.Loading
val duration = measureTimeMillis {
calculateFactorialInMainThread(factorialOf)
}
uiState.value = UiState.Success("Main thread", duration)
}
fun performCalculationOnMainThreadUsingYield(factorialOf: Int) {
uiState.value = UiState.Loading
viewModelScope.launch {
val duration = measureTimeMillis {
calculateFactorialInMainThreadUsingYield(factorialOf)
}
uiState.value = UiState.Success("Main thread using yield()", duration)
}
}
fun performCalculationWithDefaultDispatcher(factorialOf: Int) {
uiState.value = UiState.Loading
viewModelScope.launch {
val duration = measureTimeMillis {
calculateFactorialOnDefaultDispatcher(factorialOf)
}
uiState.value = UiState.Success("Default Dispatcher", duration)
}
}
private fun calculateFactorialInMainThread(number: Int): BigInteger {
var factorial = BigInteger.ONE
for (i in 1..number) {
factorial = factorial.multiply(BigInteger.valueOf(i.toLong()))
}
return factorial
}
private suspend fun calculateFactorialInMainThreadUsingYield(number: Int): BigInteger {
var factorial = BigInteger.ONE
for (i in 1..number) {
yield()
factorial = factorial.multiply(BigInteger.valueOf(i.toLong()))
}
return factorial
}
private suspend fun calculateFactorialOnDefaultDispatcher(number: Int): BigInteger =
withContext(Dispatchers.Default) {
var factorial = BigInteger.ONE
for (i in 1..number) {
factorial = factorial.multiply(BigInteger.valueOf(i.toLong()))
}
factorial
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase17/UiState.kt
================================================
package com.demo.code.usecases.coroutines.usecase17
sealed class UiState {
object Loading : UiState()
data class Success(val thread: String, val duration: Long) : UiState()
data class Error(val message: String) : UiState()
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase2/MockApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase2
import com.google.gson.Gson
import com.demo.code.mock.createMockApi
import com.demo.code.mock.mockAndroidVersions
import com.demo.code.mock.mockVersionFeaturesAndroid10
import com.demo.code.utils.MockNetworkInterceptor
fun mockApi() = createMockApi(
MockNetworkInterceptor()
.mock(
"http://localhost/recent-android-versions",
Gson().toJson(mockAndroidVersions),
200,
1500
)
.mock(
"http://localhost/android-version-features/29",
Gson().toJson(mockVersionFeaturesAndroid10),
200,
1500
)
)
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase2/Perform2SequentialNetworkRequestsActivity.kt
================================================
package com.demo.code.usecases.coroutines.usecase2
import android.os.Bundle
import androidx.activity.viewModels
import androidx.lifecycle.Observer
import com.demo.code.base.BaseActivity
import com.demo.code.base.useCase2Description
import com.demo.code.databinding.ActivityPerform2sequentialnetworkrequestsBinding
import com.demo.code.utils.fromHtml
import com.demo.code.utils.setGone
import com.demo.code.utils.setVisible
import com.demo.code.utils.toast
class Perform2SequentialNetworkRequestsActivity : BaseActivity() {
private val binding by lazy {
ActivityPerform2sequentialnetworkrequestsBinding.inflate(
layoutInflater
)
}
private val viewModel: Perform2SequentialNetworkRequestsViewModel by viewModels()
override fun getToolbarTitle() = useCase2Description
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
viewModel.uiState().observe(this, Observer { uiState ->
if (uiState != null) {
render(uiState)
}
})
binding.btnRequestsSequentially.setOnClickListener {
viewModel.perform2SequentialNetworkRequest()
}
}
private fun render(uiState: UiState) {
when (uiState) {
is UiState.Loading -> {
onLoad()
}
is UiState.Success -> {
onSuccess(uiState)
}
is UiState.Error -> {
onError(uiState)
}
}
}
private fun onLoad() = with(binding) {
progressBar.setVisible()
textViewResult.text = ""
}
private fun onSuccess(uiState: UiState.Success) = with(binding) {
progressBar.setGone()
textViewResult.text = fromHtml(
"Features of most recent Android Version \" ${uiState.versionFeatures.androidVersion.name} \" " +
uiState.versionFeatures.features.joinToString(
prefix = "- ",
separator = " - "
)
)
}
private fun onError(uiState: UiState.Error) = with(binding) {
progressBar.setGone()
btnRequestsSequentially.isEnabled = true
toast(uiState.message)
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase2/Perform2SequentialNetworkRequestsViewModel.kt
================================================
package com.demo.code.usecases.coroutines.usecase2
import androidx.lifecycle.viewModelScope
import com.demo.code.base.BaseViewModel
import com.demo.code.mock.MockApi
import kotlinx.coroutines.launch
class Perform2SequentialNetworkRequestsViewModel(
private val mockApi: MockApi = mockApi()
) : BaseViewModel() {
fun perform2SequentialNetworkRequest() {
uiState.value = UiState.Loading
viewModelScope.launch {
try {
val recentVersions = mockApi.getRecentAndroidVersions()
val mostRecentVersion = recentVersions.last()
val featuresOfMostRecentVersion =
mockApi.getAndroidVersionFeatures(mostRecentVersion.apiLevel)
uiState.value = UiState.Success(featuresOfMostRecentVersion)
} catch (exception: Exception) {
uiState.value = UiState.Error("Network Request failed")
}
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase2/UiState.kt
================================================
package com.demo.code.usecases.coroutines.usecase2
import com.demo.code.mock.VersionFeatures
sealed class UiState {
object Loading : UiState()
data class Success(
val versionFeatures: VersionFeatures
) : UiState()
data class Error(val message: String) : UiState()
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase2/callbacks/MockApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase2.callbacks
import com.google.gson.Gson
import com.demo.code.mock.AndroidVersion
import com.demo.code.mock.VersionFeatures
import com.demo.code.mock.mockAndroidVersions
import com.demo.code.mock.mockVersionFeaturesAndroid10
import com.demo.code.utils.MockNetworkInterceptor
import okhttp3.OkHttpClient
import retrofit2.Call
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.GET
import retrofit2.http.Path
fun mockApi(): CallbackMockApi = createMockApi(
MockNetworkInterceptor()
.mock(
"http://localhost/recent-android-versions",
Gson().toJson(mockAndroidVersions),
200,
1500
)
.mock(
"http://localhost/android-version-features/29",
Gson().toJson(mockVersionFeaturesAndroid10),
200,
1500
)
)
interface CallbackMockApi {
@GET("recent-android-versions")
fun getRecentAndroidVersions(): Call>
@GET("android-version-features/{apiLevel}")
fun getAndroidVersionFeatures(@Path("apiLevel") apiLevel: Int): Call
}
fun createMockApi(interceptor: MockNetworkInterceptor): CallbackMockApi {
val okHttpClient = OkHttpClient.Builder()
.addInterceptor(interceptor)
.build()
val retrofit = Retrofit.Builder()
.baseUrl("http://localhost/")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()
return retrofit.create(CallbackMockApi::class.java)
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase2/callbacks/SequentialNetworkRequestsCallbacksActivity.kt
================================================
package com.demo.code.usecases.coroutines.usecase2.callbacks
import android.os.Bundle
import androidx.activity.viewModels
import androidx.lifecycle.Observer
import com.demo.code.base.BaseActivity
import com.demo.code.base.useCase2Description
import com.demo.code.databinding.ActivityPerform2sequentialnetworkrequestsBinding
import com.demo.code.utils.fromHtml
import com.demo.code.utils.setGone
import com.demo.code.utils.setVisible
import com.demo.code.utils.toast
class SequentialNetworkRequestsCallbacksActivity : BaseActivity() {
private val binding by lazy {
ActivityPerform2sequentialnetworkrequestsBinding.inflate(
layoutInflater
)
}
private val viewModel: SequentialNetworkRequestsCallbacksViewModel by viewModels()
override fun getToolbarTitle() = useCase2Description
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
viewModel.uiState().observe(this, Observer { uiState ->
if (uiState != null) {
render(uiState)
}
})
binding.btnRequestsSequentially.setOnClickListener {
viewModel.perform2SequentialNetworkRequest()
}
}
private fun render(uiState: UiState) {
when (uiState) {
is UiState.Loading -> {
onLoad()
}
is UiState.Success -> {
onSuccess(uiState)
}
is UiState.Error -> {
onError(uiState)
}
}
}
private fun onLoad() = with(binding) {
progressBar.setVisible()
textViewResult.text = ""
}
private fun onSuccess(uiState: UiState.Success) = with(binding) {
progressBar.setGone()
textViewResult.text = fromHtml(
"Features of most recent Android Version \" ${uiState.versionFeatures.androidVersion.name} \" " +
uiState.versionFeatures.features.joinToString(
prefix = "- ",
separator = " - "
)
)
}
private fun onError(uiState: UiState.Error) = with(binding) {
progressBar.setGone()
btnRequestsSequentially.isEnabled = true
toast(uiState.message)
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase2/callbacks/SequentialNetworkRequestsCallbacksViewModel.kt
================================================
package com.demo.code.usecases.coroutines.usecase2.callbacks
import com.demo.code.base.BaseViewModel
import com.demo.code.mock.AndroidVersion
import com.demo.code.mock.VersionFeatures
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
class SequentialNetworkRequestsCallbacksViewModel(
private val mockApi: CallbackMockApi = mockApi()
) : BaseViewModel() {
private var getAndroidVersionsCall: Call>? = null
private var getAndroidFeaturesCall: Call? = null
fun perform2SequentialNetworkRequest() {
uiState.value = UiState.Loading
getAndroidVersionsCall = mockApi.getRecentAndroidVersions()
getAndroidVersionsCall!!.enqueue(object : Callback> {
override fun onFailure(call: Call>, t: Throwable) {
uiState.value = UiState.Error("Network Request failed")
}
override fun onResponse(
call: Call>,
response: Response>
) {
if (response.isSuccessful) {
val mostRecentVersion = response.body()!!.last()
getAndroidFeaturesCall =
mockApi.getAndroidVersionFeatures(mostRecentVersion.apiLevel)
getAndroidFeaturesCall!!.enqueue(object : Callback {
override fun onFailure(call: Call, t: Throwable) {
uiState.value = UiState.Error("Network Request failed")
}
override fun onResponse(
call: Call,
response: Response
) {
if (response.isSuccessful) {
val featuresOfMostRecentVersion = response.body()!!
uiState.value = UiState.Success(featuresOfMostRecentVersion)
} else {
uiState.value = UiState.Error("Network Request failed")
}
}
})
} else {
uiState.value = UiState.Error("Network Request failed")
}
}
})
}
override fun onCleared() {
super.onCleared()
getAndroidVersionsCall?.cancel()
getAndroidFeaturesCall?.cancel()
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase2/callbacks/UiState.kt
================================================
package com.demo.code.usecases.coroutines.usecase2.callbacks
import com.demo.code.mock.VersionFeatures
sealed class UiState {
object Loading : UiState()
data class Success(
val versionFeatures: VersionFeatures
) : UiState()
data class Error(val message: String) : UiState()
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase2/rx/MockApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase2.rx
import com.google.gson.Gson
import com.demo.code.mock.AndroidVersion
import com.demo.code.mock.VersionFeatures
import com.demo.code.mock.mockAndroidVersions
import com.demo.code.mock.mockVersionFeaturesAndroid10
import com.demo.code.utils.MockNetworkInterceptor
import io.reactivex.Single
import io.reactivex.schedulers.Schedulers
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.GET
import retrofit2.http.Path
fun mockApi(): RxMockApi = createMockApi(
MockNetworkInterceptor()
.mock(
"http://localhost/recent-android-versions",
Gson().toJson(mockAndroidVersions),
200,
1500
)
.mock(
"http://localhost/android-version-features/29",
Gson().toJson(mockVersionFeaturesAndroid10),
200,
1500
)
)
interface RxMockApi {
@GET("recent-android-versions")
fun getRecentAndroidVersions(): Single>
@GET("android-version-features/{apiLevel}")
fun getAndroidVersionFeatures(@Path("apiLevel") apiLevel: Int): Single
}
fun createMockApi(interceptor: MockNetworkInterceptor): RxMockApi {
val okHttpClient = OkHttpClient.Builder()
.addInterceptor(interceptor)
.build()
val retrofit = Retrofit.Builder()
.baseUrl("http://localhost/")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
.build()
return retrofit.create(RxMockApi::class.java)
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase2/rx/SequentialNetworkRequestsRxActivity.kt
================================================
package com.demo.code.usecases.coroutines.usecase2.rx
import android.os.Bundle
import androidx.activity.viewModels
import androidx.lifecycle.Observer
import com.demo.code.base.BaseActivity
import com.demo.code.base.useCase2UsingRxDescription
import com.demo.code.databinding.ActivityPerform2sequentialnetworkrequestsBinding
import com.demo.code.utils.fromHtml
import com.demo.code.utils.setGone
import com.demo.code.utils.setVisible
import com.demo.code.utils.toast
class SequentialNetworkRequestsRxActivity : BaseActivity() {
private val binding by lazy {
ActivityPerform2sequentialnetworkrequestsBinding.inflate(
layoutInflater
)
}
private val viewModel: SequentialNetworkRequestsRxViewModel by viewModels()
override fun getToolbarTitle() = useCase2UsingRxDescription
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
viewModel.uiState().observe(this, Observer { uiState ->
if (uiState != null) {
render(uiState)
}
})
binding.btnRequestsSequentially.setOnClickListener {
viewModel.perform2SequentialNetworkRequest()
}
}
private fun render(uiState: UiState) {
when (uiState) {
is UiState.Loading -> {
onLoad()
}
is UiState.Success -> {
onSuccess(uiState)
}
is UiState.Error -> {
onError(uiState)
}
}
}
private fun onLoad() = with(binding) {
progressBar.setVisible()
textViewResult.text = ""
}
private fun onSuccess(uiState: UiState.Success) = with(binding) {
progressBar.setGone()
textViewResult.text = fromHtml(
"Features of most recent Android Version \" ${uiState.versionFeatures.androidVersion.name} \" " +
uiState.versionFeatures.features.joinToString(
prefix = "- ",
separator = " - "
)
)
}
private fun onError(uiState: UiState.Error) = with(binding) {
progressBar.setGone()
btnRequestsSequentially.isEnabled = true
toast(uiState.message)
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase2/rx/SequentialNetworkRequestsRxViewModel.kt
================================================
package com.demo.code.usecases.coroutines.usecase2.rx
import com.demo.code.base.BaseViewModel
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.addTo
import io.reactivex.rxkotlin.subscribeBy
import io.reactivex.schedulers.Schedulers
class SequentialNetworkRequestsRxViewModel(
private val mockApi: RxMockApi = mockApi()
) : BaseViewModel() {
private val disposables = CompositeDisposable()
fun perform2SequentialNetworkRequest() {
uiState.value = UiState.Loading
mockApi.getRecentAndroidVersions()
.flatMap { androidVersions ->
val recentVersion = androidVersions.last()
mockApi.getAndroidVersionFeatures(recentVersion.apiLevel)
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeBy(
onSuccess = { featureVersions ->
uiState.value = UiState.Success(featureVersions)
},
onError = {
uiState.value = UiState.Error("Network Request failed.")
}
)
.addTo(disposables)
}
override fun onCleared() {
super.onCleared()
disposables.clear()
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase2/rx/UiState.kt
================================================
package com.demo.code.usecases.coroutines.usecase2.rx
import com.demo.code.mock.VersionFeatures
sealed class UiState {
object Loading : UiState()
data class Success(
val versionFeatures: VersionFeatures
) : UiState()
data class Error(val message: String) : UiState()
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase3/MockApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase3
import com.google.gson.Gson
import com.demo.code.mock.createMockApi
import com.demo.code.mock.mockVersionFeaturesAndroid10
import com.demo.code.mock.mockVersionFeaturesOreo
import com.demo.code.mock.mockVersionFeaturesPie
import com.demo.code.utils.MockNetworkInterceptor
fun mockApi() = createMockApi(
MockNetworkInterceptor()
.mock(
"http://localhost/android-version-features/27",
Gson().toJson(mockVersionFeaturesOreo),
200,
1000
)
.mock(
"http://localhost/android-version-features/28",
Gson().toJson(mockVersionFeaturesPie),
200,
1000
)
.mock(
"http://localhost/android-version-features/29",
Gson().toJson(mockVersionFeaturesAndroid10),
200,
1000
)
)
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase3/PerformNetworkRequestsConcurrentlyActivity.kt
================================================
package com.demo.code.usecases.coroutines.usecase3
import android.os.Bundle
import androidx.activity.viewModels
import androidx.lifecycle.Observer
import com.demo.code.R
import com.demo.code.base.BaseActivity
import com.demo.code.base.useCase3Description
import com.demo.code.databinding.ActivityPerformnetworkrequestsconcurrentlyBinding
import com.demo.code.utils.fromHtml
import com.demo.code.utils.setGone
import com.demo.code.utils.setVisible
import com.demo.code.utils.toast
class PerformNetworkRequestsConcurrentlyActivity : BaseActivity() {
private val binding by lazy {
ActivityPerformnetworkrequestsconcurrentlyBinding.inflate(
layoutInflater
)
}
private val viewModel: PerformNetworkRequestsConcurrentlyViewModel by viewModels()
override fun getToolbarTitle() = useCase3Description
private var operationStartTime = 0L
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
viewModel.uiState().observe(this, Observer { uiState ->
if (uiState != null) {
render(uiState)
}
})
binding.btnRequestsSequentially.setOnClickListener {
viewModel.performNetworkRequestsSequentially()
}
binding.btnRequestsConcurrently.setOnClickListener {
viewModel.performNetworkRequestsConcurrently()
}
}
private fun render(uiState: UiState) {
when (uiState) {
is UiState.Loading -> {
onLoad()
}
is UiState.Success -> {
onSuccess(uiState)
}
is UiState.Error -> {
onError(uiState)
}
}
}
private fun onLoad() = with(binding) {
operationStartTime = System.currentTimeMillis()
progressBar.setVisible()
textViewDuration.text = ""
textViewResult.text = ""
disableButtons()
}
private fun onSuccess(uiState: UiState.Success) = with(binding) {
enableButtons()
progressBar.setGone()
val duration = System.currentTimeMillis() - operationStartTime
textViewDuration.text = getString(R.string.duration, duration)
val versionFeatures = uiState.versionFeatures
val versionFeaturesString = versionFeatures.joinToString(separator = " ") {
"New Features of ${it.androidVersion.name} ${it.features.joinToString(
prefix = "- ",
separator = " - "
)}"
}
textViewResult.text = fromHtml(versionFeaturesString)
}
private fun onError(uiState: UiState.Error) {
binding.progressBar.setGone()
binding.textViewDuration.setGone()
toast(uiState.message)
enableButtons()
}
private fun enableButtons() {
binding.btnRequestsSequentially.isEnabled = true
binding.btnRequestsConcurrently.isEnabled = true
}
private fun disableButtons() {
binding.btnRequestsSequentially.isEnabled = false
binding.btnRequestsConcurrently.isEnabled = false
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase3/PerformNetworkRequestsConcurrentlyViewModel.kt
================================================
package com.demo.code.usecases.coroutines.usecase3
import androidx.lifecycle.viewModelScope
import com.demo.code.base.BaseViewModel
import com.demo.code.mock.MockApi
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.launch
class PerformNetworkRequestsConcurrentlyViewModel(
private val mockApi: MockApi = mockApi()
) : BaseViewModel() {
fun performNetworkRequestsSequentially() {
uiState.value = UiState.Loading
viewModelScope.launch {
try {
val oreoFeatures = mockApi.getAndroidVersionFeatures(27)
val pieFeatures = mockApi.getAndroidVersionFeatures(28)
val android10Features = mockApi.getAndroidVersionFeatures(29)
val versionFeatures = listOf(oreoFeatures, pieFeatures, android10Features)
uiState.value = UiState.Success(versionFeatures)
} catch (exception: Exception) {
uiState.value = UiState.Error("Network Request failed")
}
}
}
fun performNetworkRequestsConcurrently() {
uiState.value = UiState.Loading
val oreoFeaturesDeferred = viewModelScope.async { mockApi.getAndroidVersionFeatures(27) }
val pieFeaturesDeferred = viewModelScope.async { mockApi.getAndroidVersionFeatures(28) }
val android10FeaturesDeferred =
viewModelScope.async { mockApi.getAndroidVersionFeatures(29) }
viewModelScope.launch {
try {
val versionFeatures =
awaitAll(oreoFeaturesDeferred, pieFeaturesDeferred, android10FeaturesDeferred)
uiState.value = UiState.Success(versionFeatures)
} catch (exception: Exception) {
uiState.value = UiState.Error("Network Request failed")
}
}
/*
Alternatively:
viewModelScope.launch {
try {
// we need to wrap this code with a coroutineScope block
// otherwise the app would crash on unsuccessful network requests
coroutineScope {
val oreoFeaturesDeferred = async { mockApi.getAndroidVersionFeatures(27) }
val pieFeaturesDeferred = async { mockApi.getAndroidVersionFeatures(28) }
val android10FeaturesDeferred = async { mockApi.getAndroidVersionFeatures(29) }
val oreoFeatures = oreoFeaturesDeferred.await()
val pieFeatures = pieFeaturesDeferred.await()
val android10Features = android10FeaturesDeferred.await()
val versionFeatures = listOf(oreoFeatures, pieFeatures, android10Features)
// other alternative: (but slightly different behavior when a deferred fails, see docs)
// val versionFeatures = awaitAll(oreoFeaturesDeferred, pieFeaturesDeferred, android10FeaturesDeferred)
uiState.value = UiState.Success(versionFeatures)
}
} catch (exception: Exception) {
uiState.value = UiState.Error("Network Request failed")
}
}*/
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase3/UiState.kt
================================================
package com.demo.code.usecases.coroutines.usecase3
import com.demo.code.mock.VersionFeatures
sealed class UiState {
object Loading : UiState()
data class Success(
val versionFeatures: List
) : UiState()
data class Error(val message: String) : UiState()
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase4/MockApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase4
import com.google.gson.Gson
import com.demo.code.mock.*
import com.demo.code.utils.MockNetworkInterceptor
fun mockApi() = createMockApi(
MockNetworkInterceptor()
.mock(
"http://localhost/recent-android-versions",
Gson().toJson(mockAndroidVersions),
200,
1000
)
.mock(
"http://localhost/android-version-features/27",
Gson().toJson(mockVersionFeaturesOreo),
200,
1000
)
.mock(
"http://localhost/android-version-features/28",
Gson().toJson(mockVersionFeaturesPie),
200,
1000
)
.mock(
"http://localhost/android-version-features/29",
Gson().toJson(mockVersionFeaturesAndroid10),
200,
1000
)
)
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase4/UiState.kt
================================================
package com.demo.code.usecases.coroutines.usecase4
import com.demo.code.mock.VersionFeatures
sealed class UiState {
object Loading : UiState()
data class Success(
val versionFeatures: List
) : UiState()
data class Error(val message: String) : UiState()
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase4/VariableAmountOfNetworkRequestsActivity.kt
================================================
package com.demo.code.usecases.coroutines.usecase4
import android.os.Bundle
import androidx.activity.viewModels
import androidx.lifecycle.Observer
import com.demo.code.R
import com.demo.code.base.BaseActivity
import com.demo.code.base.useCase4Description
import com.demo.code.databinding.ActivityPerformvariableamountofnetworkrequestsconcurrentlyBinding
import com.demo.code.utils.fromHtml
import com.demo.code.utils.setGone
import com.demo.code.utils.setVisible
import com.demo.code.utils.toast
class VariableAmountOfNetworkRequestsActivity : BaseActivity() {
private val binding by lazy {
ActivityPerformvariableamountofnetworkrequestsconcurrentlyBinding.inflate(
layoutInflater
)
}
private val viewModel: VariableAmountOfNetworkRequestsViewModel by viewModels()
override fun getToolbarTitle() = useCase4Description
private var operationStartTime = 0L
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
viewModel.uiState().observe(this, Observer { uiState ->
if (uiState != null) {
render(uiState)
}
})
binding.btnRequestsSequentially.setOnClickListener {
viewModel.performNetworkRequestsSequentially()
}
binding.btnRequestsConcurrently.setOnClickListener {
viewModel.performNetworkRequestsConcurrently()
}
}
private fun render(uiState: UiState) {
when (uiState) {
is UiState.Loading -> {
onLoad()
}
is UiState.Success -> {
onSuccess(uiState)
}
is UiState.Error -> {
onError(uiState)
}
}
}
private fun onLoad() = with(binding) {
operationStartTime = System.currentTimeMillis()
progressBar.setVisible()
textViewResult.text = ""
textViewDuration.text = ""
disableButtons()
}
private fun onSuccess(uiState: UiState.Success) = with(binding) {
enableButtons()
progressBar.setGone()
val duration = System.currentTimeMillis() - operationStartTime
textViewDuration.text = getString(R.string.duration, duration)
val versionFeatures = uiState.versionFeatures
val versionFeaturesString = versionFeatures.map {
"New Features of ${it.androidVersion.name} ${it.features.joinToString(
prefix = "- ",
separator = " - "
)}"
}.joinToString(separator = " ")
textViewResult.text = fromHtml(versionFeaturesString)
}
private fun onError(uiState: UiState.Error) = with(binding) {
progressBar.setGone()
toast(uiState.message)
enableButtons()
}
private fun enableButtons() = with(binding) {
btnRequestsSequentially.isEnabled = true
btnRequestsConcurrently.isEnabled = true
}
private fun disableButtons() = with(binding) {
btnRequestsSequentially.isEnabled = false
btnRequestsConcurrently.isEnabled = false
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase4/VariableAmountOfNetworkRequestsViewModel.kt
================================================
package com.demo.code.usecases.coroutines.usecase4
import androidx.lifecycle.viewModelScope
import com.demo.code.base.BaseViewModel
import com.demo.code.mock.MockApi
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.launch
class VariableAmountOfNetworkRequestsViewModel(
private val mockApi: MockApi = mockApi()
) : BaseViewModel() {
fun performNetworkRequestsSequentially() {
uiState.value = UiState.Loading
viewModelScope.launch {
try {
val recentVersions = mockApi.getRecentAndroidVersions()
val versionFeatures = recentVersions.map { androidVersion ->
mockApi.getAndroidVersionFeatures(androidVersion.apiLevel)
}
uiState.value = UiState.Success(versionFeatures)
} catch (exception: Exception) {
uiState.value = UiState.Error("Network Request failed")
}
}
}
fun performNetworkRequestsConcurrently() {
uiState.value = UiState.Loading
viewModelScope.launch {
try {
val recentVersions = mockApi.getRecentAndroidVersions()
val versionFeatures = recentVersions
.map { androidVersion ->
async { mockApi.getAndroidVersionFeatures(androidVersion.apiLevel) }
}.awaitAll()
uiState.value = UiState.Success(versionFeatures)
} catch (exception: Exception) {
uiState.value = UiState.Error("Network Request failed")
}
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase5/MockApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase5
import com.google.gson.Gson
import com.demo.code.mock.createMockApi
import com.demo.code.mock.mockAndroidVersions
import com.demo.code.utils.MockNetworkInterceptor
fun mockApi() = createMockApi(
MockNetworkInterceptor()
.mock(
"http://localhost/recent-android-versions",
Gson().toJson(mockAndroidVersions),
200,
1000
)
)
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase5/NetworkRequestWithTimeoutActivity.kt
================================================
package com.demo.code.usecases.coroutines.usecase5
import android.os.Bundle
import androidx.activity.viewModels
import androidx.lifecycle.Observer
import com.demo.code.base.BaseActivity
import com.demo.code.base.useCase5Description
import com.demo.code.databinding.ActivityNetworkrequestwithtimeoutBinding
import com.demo.code.utils.fromHtml
import com.demo.code.utils.setGone
import com.demo.code.utils.setVisible
import com.demo.code.utils.toast
class NetworkRequestWithTimeoutActivity : BaseActivity() {
override fun getToolbarTitle() = useCase5Description
private val binding by lazy { ActivityNetworkrequestwithtimeoutBinding.inflate(layoutInflater) }
private val viewModel: NetworkRequestWithTimeoutViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
viewModel.uiState().observe(this, Observer { uiState ->
if (uiState != null) {
render(uiState)
}
})
binding.btnPerformSingleNetworkRequest.setOnClickListener {
val timeOut = binding.editTextTimeOut.text.toString().toLongOrNull()
if (timeOut != null) {
viewModel.performNetworkRequest(timeOut)
}
}
}
private fun render(uiState: UiState) {
when (uiState) {
is UiState.Loading -> {
onLoad()
}
is UiState.Success -> {
onSuccess(uiState)
}
is UiState.Error -> {
onError(uiState)
}
}
}
private fun onLoad() = with(binding) {
progressBar.setVisible()
textViewResult.text = ""
btnPerformSingleNetworkRequest.isEnabled = false
}
private fun onSuccess(uiState: UiState.Success) = with(binding) {
progressBar.setGone()
btnPerformSingleNetworkRequest.isEnabled = true
val readableVersions = uiState.recentVersions.map { "API ${it.apiLevel}: ${it.name}" }
textViewResult.text = fromHtml(
"Recent Android Versions ${readableVersions.joinToString(separator = " ")}"
)
}
private fun onError(uiState: UiState.Error) = with(binding) {
progressBar.setGone()
btnPerformSingleNetworkRequest.isEnabled = true
toast(uiState.message)
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase5/NetworkRequestWithTimeoutViewModel.kt
================================================
package com.demo.code.usecases.coroutines.usecase5
import androidx.lifecycle.viewModelScope
import com.demo.code.base.BaseViewModel
import com.demo.code.mock.MockApi
import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.launch
import kotlinx.coroutines.withTimeout
import kotlinx.coroutines.withTimeoutOrNull
class NetworkRequestWithTimeoutViewModel(
private val api: MockApi = mockApi()
) : BaseViewModel() {
fun performNetworkRequest(timeout: Long) {
uiState.value = UiState.Loading
// usingWithTimeout(timeout)
usingWithTimeoutOrNull(timeout)
}
private fun usingWithTimeout(timeout: Long) {
viewModelScope.launch {
try {
val recentVersions = withTimeout(timeout) {
api.getRecentAndroidVersions()
}
uiState.value = UiState.Success(recentVersions)
} catch (timeoutCancellationException: TimeoutCancellationException) {
uiState.value = UiState.Error("Network Request timed out!")
} catch (exception: Exception) {
uiState.value = UiState.Error("Network Request failed!")
}
}
}
private fun usingWithTimeoutOrNull(timeout: Long) {
viewModelScope.launch {
try {
val recentVersions = withTimeoutOrNull(timeout) {
api.getRecentAndroidVersions()
}
if (recentVersions != null) {
uiState.value = UiState.Success(recentVersions)
} else {
uiState.value = UiState.Error("Network Request timed out!")
}
} catch (exception: Exception) {
uiState.value = UiState.Error("Network Request failed!")
}
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase5/UiState.kt
================================================
package com.demo.code.usecases.coroutines.usecase5
import com.demo.code.mock.AndroidVersion
sealed class UiState {
object Loading : UiState()
data class Success(val recentVersions: List) : UiState()
data class Error(val message: String) : UiState()
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase6/MockApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase6
import com.google.gson.Gson
import com.demo.code.mock.createMockApi
import com.demo.code.mock.mockAndroidVersions
import com.demo.code.utils.MockNetworkInterceptor
fun mockApi() = createMockApi(
MockNetworkInterceptor()
.mock(
"http://localhost/recent-android-versions",
"something went wrong on server side",
500,
1000,
persist = false
).mock(
"http://localhost/recent-android-versions",
"something went wrong on server side",
500,
1000,
persist = false
).mock(
"http://localhost/recent-android-versions",
Gson().toJson(mockAndroidVersions),
200,
1000
)
)
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase6/RetryNetworkRequestActivity.kt
================================================
package com.demo.code.usecases.coroutines.usecase6
import android.os.Bundle
import androidx.activity.viewModels
import androidx.lifecycle.Observer
import com.demo.code.base.BaseActivity
import com.demo.code.base.useCase6Description
import com.demo.code.databinding.ActivityRetrynetworkrequestBinding
import com.demo.code.utils.fromHtml
import com.demo.code.utils.setGone
import com.demo.code.utils.setVisible
import com.demo.code.utils.toast
class RetryNetworkRequestActivity : BaseActivity() {
override fun getToolbarTitle() = useCase6Description
private val binding by lazy { ActivityRetrynetworkrequestBinding.inflate(layoutInflater) }
private val viewModel: RetryNetworkRequestViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
viewModel.uiState().observe(this, Observer { uiState ->
if (uiState != null) {
render(uiState)
}
})
binding.btnPerformSingleNetworkRequest.setOnClickListener {
viewModel.performNetworkRequest()
}
}
private fun render(uiState: UiState) {
when (uiState) {
is UiState.Loading -> {
onLoad()
}
is UiState.Success -> {
onSuccess(uiState)
}
is UiState.Error -> {
onError(uiState)
}
}
}
private fun onLoad() = with(binding) {
progressBar.setVisible()
textViewResult.text = ""
btnPerformSingleNetworkRequest.isEnabled = false
}
private fun onSuccess(uiState: UiState.Success) = with(binding) {
progressBar.setGone()
btnPerformSingleNetworkRequest.isEnabled = true
val readableVersions = uiState.recentVersions.map { "API ${it.apiLevel}: ${it.name}" }
textViewResult.text = fromHtml(
"Recent Android Versions ${readableVersions.joinToString(separator = " ")}"
)
}
private fun onError(uiState: UiState.Error) = with(binding) {
progressBar.setGone()
btnPerformSingleNetworkRequest.isEnabled = true
toast(uiState.message)
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase6/RetryNetworkRequestViewModel.kt
================================================
package com.demo.code.usecases.coroutines.usecase6
import androidx.lifecycle.viewModelScope
import com.demo.code.base.BaseViewModel
import com.demo.code.mock.MockApi
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import timber.log.Timber
class RetryNetworkRequestViewModel(
private val api: MockApi = mockApi()
) : BaseViewModel() {
fun performNetworkRequest() {
uiState.value = UiState.Loading
viewModelScope.launch {
val numberOfRetries = 2
try {
retry(times = numberOfRetries) {
val recentVersions = api.getRecentAndroidVersions()
uiState.value = UiState.Success(recentVersions)
}
} catch (e: Exception) {
uiState.value = UiState.Error("Network Request failed")
}
}
}
// retry with exponential backoff
// inspired by https://stackoverflow.com/questions/46872242/how-to-exponential-backoff-retry-on-kotlin-coroutines
private suspend fun retry(
times: Int,
initialDelayMillis: Long = 100,
maxDelayMillis: Long = 1000,
factor: Double = 2.0,
block: suspend () -> T
): T {
var currentDelay = initialDelayMillis
repeat(times) {
try {
return block()
} catch (exception: Exception) {
Timber.e(exception)
}
delay(currentDelay)
currentDelay = (currentDelay * factor).toLong().coerceAtMost(maxDelayMillis)
}
return block() // last attempt
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase6/UiState.kt
================================================
package com.demo.code.usecases.coroutines.usecase6
import com.demo.code.mock.AndroidVersion
sealed class UiState {
object Loading : UiState()
data class Success(val recentVersions: List) : UiState()
data class Error(val message: String) : UiState()
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase7/MockApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase7
import com.google.gson.Gson
import com.demo.code.mock.createMockApi
import com.demo.code.mock.mockVersionFeaturesOreo
import com.demo.code.mock.mockVersionFeaturesPie
import com.demo.code.utils.MockNetworkInterceptor
fun mockApi() = createMockApi(
MockNetworkInterceptor()
// timeout on first request for oreo features
.mock(
"http://localhost/android-version-features/27",
Gson().toJson(mockVersionFeaturesOreo),
200,
1050,
persist = false
)
// network error on second request
.mock(
"http://localhost/android-version-features/27",
"Something went wrong on servers side",
500,
100,
persist = false
)
// 3rd request is successful and within timeout
.mock(
"http://localhost/android-version-features/27",
Gson().toJson(mockVersionFeaturesOreo),
200,
100
)
// timeout on first request for pie features
.mock(
"http://localhost/android-version-features/28",
Gson().toJson(mockVersionFeaturesPie),
200,
1050,
persist = false
)
// network error on second request
.mock(
"http://localhost/android-version-features/28",
"Something went wrong on servers side",
500,
100,
persist = false
)
// 3rd request is successful and within timeout
.mock(
"http://localhost/android-version-features/28",
Gson().toJson(mockVersionFeaturesPie),
200,
100
)
)
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase7/TimeoutAndRetryActivity.kt
================================================
package com.demo.code.usecases.coroutines.usecase7
import android.os.Bundle
import androidx.activity.viewModels
import androidx.lifecycle.Observer
import com.demo.code.base.BaseActivity
import com.demo.code.base.useCase7Description
import com.demo.code.databinding.ActivityRetrynetworkrequestBinding
import com.demo.code.utils.fromHtml
import com.demo.code.utils.setGone
import com.demo.code.utils.setVisible
import com.demo.code.utils.toast
class TimeoutAndRetryActivity : BaseActivity() {
override fun getToolbarTitle() = useCase7Description
private val binding by lazy { ActivityRetrynetworkrequestBinding.inflate(layoutInflater) }
private val viewModel: TimeoutAndRetryViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
viewModel.uiState().observe(this, Observer { uiState ->
if (uiState != null) {
render(uiState)
}
})
binding.btnPerformSingleNetworkRequest.setOnClickListener {
viewModel.performNetworkRequest()
}
}
private fun render(uiState: UiState) {
when (uiState) {
is UiState.Loading -> {
onLoad()
}
is UiState.Success -> {
onSuccess(uiState)
}
is UiState.Error -> {
onError(uiState)
}
}
}
private fun onLoad() = with(binding) {
progressBar.setVisible()
textViewResult.text = ""
btnPerformSingleNetworkRequest.isEnabled = false
}
private fun onSuccess(uiState: UiState.Success) = with(binding) {
progressBar.setGone()
btnPerformSingleNetworkRequest.isEnabled = true
val versionFeatures = uiState.versionFeatures
val versionFeaturesString = versionFeatures.map {
"New Features of ${it.androidVersion.name} ${it.features.joinToString(
prefix = "- ",
separator = " - "
)}"
}.joinToString(separator = " ")
textViewResult.text = fromHtml(versionFeaturesString)
}
private fun onError(uiState: UiState.Error) = with(binding) {
progressBar.setGone()
btnPerformSingleNetworkRequest.isEnabled = true
toast(uiState.message)
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase7/TimeoutAndRetryViewModel.kt
================================================
package com.demo.code.usecases.coroutines.usecase7
import androidx.lifecycle.viewModelScope
import com.demo.code.base.BaseViewModel
import com.demo.code.mock.MockApi
import kotlinx.coroutines.*
import timber.log.Timber
class TimeoutAndRetryViewModel(
private val api: MockApi = mockApi()
) : BaseViewModel() {
fun performNetworkRequest() {
uiState.value = UiState.Loading
val numberOfRetries = 2
val timeout = 1000L
val oreoVersionsDeferred = viewModelScope.async {
retryWithTimeout(numberOfRetries, timeout) {
api.getAndroidVersionFeatures(27)
}
}
val pieVersionsDeferred = viewModelScope.async {
retryWithTimeout(numberOfRetries, timeout) {
api.getAndroidVersionFeatures(28)
}
}
viewModelScope.launch {
try {
val versionFeatures = listOf(
oreoVersionsDeferred,
pieVersionsDeferred
).awaitAll()
uiState.value = UiState.Success(versionFeatures)
} catch (e: Exception) {
Timber.e(e)
uiState.value = UiState.Error("Network Request failed")
}
}
}
private suspend fun retryWithTimeout(
numberOfRetries: Int,
timeout: Long,
block: suspend () -> T
) = retry(numberOfRetries) {
withTimeout(timeout) {
block()
}
}
private suspend fun retry(
numberOfRetries: Int,
delayBetweenRetries: Long = 100,
block: suspend () -> T
): T {
repeat(numberOfRetries) {
try {
return block()
} catch (exception: Exception) {
Timber.e(exception)
}
delay(delayBetweenRetries)
}
return block() // last attempt
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase7/UiState.kt
================================================
package com.demo.code.usecases.coroutines.usecase7
import com.demo.code.mock.VersionFeatures
sealed class UiState {
object Loading : UiState()
data class Success(val versionFeatures: List) : UiState()
data class Error(val message: String) : UiState()
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase7/callbacks/MockApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase7.callbacks
import com.google.gson.Gson
import com.demo.code.mock.AndroidVersion
import com.demo.code.mock.VersionFeatures
import com.demo.code.mock.mockVersionFeaturesOreo
import com.demo.code.mock.mockVersionFeaturesPie
import com.demo.code.utils.MockNetworkInterceptor
import okhttp3.OkHttpClient
import retrofit2.Call
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.GET
import retrofit2.http.Path
fun mockApi(): CallbackMockApi = createMockApi(
MockNetworkInterceptor()
// timeout on first request for oreo features
.mock(
"http://localhost/android-version-features/27",
Gson().toJson(mockVersionFeaturesOreo),
200,
1200,
persist = false
)
// network error on second request
.mock(
"http://localhost/android-version-features/27",
"Something went wrong on servers side",
500,
300,
persist = false
)
// 3rd request is successful and within timeout
.mock(
"http://localhost/android-version-features/27",
Gson().toJson(mockVersionFeaturesOreo),
200,
100
)
// timeout on first request for pie features
.mock(
"http://localhost/android-version-features/28",
Gson().toJson(mockVersionFeaturesPie),
200,
1200,
persist = false
)
// network error on second request
.mock(
"http://localhost/android-version-features/28",
"Something went wrong on servers side",
500,
200,
persist = false
)
// 3rd request is successful and within timeout
.mock(
"http://localhost/android-version-features/28",
Gson().toJson(mockVersionFeaturesPie),
200,
100
)
)
interface CallbackMockApi {
@GET("recent-android-versions")
fun getRecentAndroidVersions(): Call>
@GET("android-version-features/{apiLevel}")
fun getAndroidVersionFeatures(@Path("apiLevel") apiLevel: Int): Call
}
fun createMockApi(interceptor: MockNetworkInterceptor): CallbackMockApi {
val okHttpClient = OkHttpClient.Builder()
.addInterceptor(interceptor)
.build()
val retrofit = Retrofit.Builder()
.baseUrl("http://localhost/")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.build()
return retrofit.create(CallbackMockApi::class.java)
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase7/callbacks/TimeoutAndRetryCallbackActivity.kt
================================================
package com.demo.code.usecases.coroutines.usecase7.callbacks
import android.os.Bundle
import androidx.activity.viewModels
import androidx.lifecycle.Observer
import com.demo.code.base.BaseActivity
import com.demo.code.base.useCase7UsingCallbacksDescription
import com.demo.code.databinding.ActivityRetrynetworkrequestBinding
import com.demo.code.utils.fromHtml
import com.demo.code.utils.setGone
import com.demo.code.utils.setVisible
import com.demo.code.utils.toast
class TimeoutAndRetryCallbackActivity : BaseActivity() {
override fun getToolbarTitle() = useCase7UsingCallbacksDescription
private val binding by lazy { ActivityRetrynetworkrequestBinding.inflate(layoutInflater) }
private val viewModel: TimeoutAndRetryCallbackViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
viewModel.uiState().observe(this, Observer { uiState ->
if (uiState != null) {
render(uiState)
}
})
binding.btnPerformSingleNetworkRequest.setOnClickListener {
viewModel.performNetworkRequest()
}
}
private fun render(uiState: UiState) {
when (uiState) {
is UiState.Loading -> {
onLoad()
}
is UiState.Success -> {
onSuccess(uiState)
}
is UiState.Error -> {
onError(uiState)
}
}
}
private fun onLoad() = with(binding) {
progressBar.setVisible()
textViewResult.text = ""
btnPerformSingleNetworkRequest.isEnabled = false
}
private fun onSuccess(uiState: UiState.Success) = with(binding) {
progressBar.setGone()
btnPerformSingleNetworkRequest.isEnabled = true
val versionFeatures = uiState.versionFeatures
val versionFeaturesString = versionFeatures.map {
"New Features of ${it.androidVersion.name} ${it.features.joinToString(
prefix = "- ",
separator = " - "
)}"
}.joinToString(separator = " ")
textViewResult.text = fromHtml(versionFeaturesString)
}
private fun onError(uiState: UiState.Error) = with(binding) {
progressBar.setGone()
btnPerformSingleNetworkRequest.isEnabled = true
toast(uiState.message)
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase7/callbacks/TimeoutAndRetryCallbackViewModel.kt
================================================
package com.demo.code.usecases.coroutines.usecase7.callbacks
import android.os.Handler
import android.os.Looper
import com.demo.code.base.BaseViewModel
import com.demo.code.mock.VersionFeatures
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import timber.log.Timber
class TimeoutAndRetryCallbackViewModel(api: CallbackMockApi = mockApi()) :
BaseViewModel() {
private val totalAttempts = 3
private var oreoFeaturesRequestAttemptNumber = 0
private var pieFeaturesRequestAttemptNumber = 0
private val shouldRetryOreoFeaturesRequest: Boolean
get() = oreoFeaturesRequestAttemptNumber < totalAttempts
private val shouldRetryPieFeaturesRequest: Boolean
get() = pieFeaturesRequestAttemptNumber < totalAttempts
private val timeout = 1000L
private val oreoFeaturesTimeoutHandler = Handler(Looper.getMainLooper())
private val pieFeaturesTimeoutHandler = Handler(Looper.getMainLooper())
private var oreoFeaturesCall = api.getAndroidVersionFeatures(27)
private var pieFeaturesCall = api.getAndroidVersionFeatures(28)
private var oreoFeaturesResult: VersionFeatures? = null
private var pieFeaturesResult: VersionFeatures? = null
private val oreoFeaturesReceived: Boolean
get() = oreoFeaturesResult != null
private val pieFeaturesReceived: Boolean
get() = pieFeaturesResult != null
fun performNetworkRequest() {
uiState.value = UiState.Loading
getOreoFeatures()
getPieFeatures()
}
private fun getOreoFeatures() {
oreoFeaturesRequestAttemptNumber++
Timber.d("Start get oreo features request")
oreoFeaturesCall = oreoFeaturesCall.clone()
oreoFeaturesCall.enqueue(object : Callback {
override fun onFailure(call: Call, t: Throwable) {
Timber.e("Get oreo features onFailure() entered: $t")
stopOreoFeaturesTimeoutHandler()
postErrorOrRetryGetOreoFeatures()
}
override fun onResponse(
call: Call,
response: Response
) {
stopOreoFeaturesTimeoutHandler()
if (!response.isSuccessful) {
Timber.e("Get oreo features request was unsuccessful")
postErrorOrRetryGetOreoFeatures()
return
} else {
Timber.d("successful oreo response received.")
}
oreoFeaturesResult = response.body()
maybeNotifyView()
}
})
setOreoFeaturesTimeout()
}
private fun setOreoFeaturesTimeout() {
val retryRunnable = Runnable {
Timber.e("Timeout for getting oreo features")
if (!oreoFeaturesReceived) {
oreoFeaturesCall.cancel()
}
}
Timber.d("start oreo Features Timeout Handler")
oreoFeaturesTimeoutHandler.postDelayed(retryRunnable, timeout)
}
private fun postErrorOrRetryGetOreoFeatures() {
if (shouldRetryOreoFeaturesRequest) {
getOreoFeatures()
} else {
uiState.value = UiState.Error("Network Request failed.")
cancelNetworkRequests()
}
}
private fun getPieFeatures() {
pieFeaturesRequestAttemptNumber++
Timber.d("Start get pie features request")
pieFeaturesCall = pieFeaturesCall.clone()
pieFeaturesCall.enqueue(object : Callback {
override fun onFailure(call: Call, t: Throwable) {
Timber.e("Get pie features onFailure() entered: $t")
stopPieFeaturesTimeoutHandler()
postErrorOrRetryGetPieFeatures()
}
override fun onResponse(
call: Call,
response: Response
) {
stopPieFeaturesTimeoutHandler()
if (!response.isSuccessful) {
Timber.e("Get pie features request was unsuccessful")
postErrorOrRetryGetPieFeatures()
return
} else {
Timber.d("successful pie response received.")
}
pieFeaturesResult = response.body()
maybeNotifyView()
}
})
setPieFeaturesTimeout()
}
private fun stopPieFeaturesTimeoutHandler() {
Timber.d("stopping pie Features Timeout Handler")
pieFeaturesTimeoutHandler.removeCallbacksAndMessages(null)
}
private fun setPieFeaturesTimeout() {
val retryRunnable = Runnable {
Timber.e("Timeout for getting pie features")
if (!pieFeaturesReceived) {
pieFeaturesCall.cancel()
}
}
Timber.d("start pie Features Timeout Handler")
pieFeaturesTimeoutHandler.postDelayed(retryRunnable, timeout)
}
private fun postErrorOrRetryGetPieFeatures() {
if (shouldRetryPieFeaturesRequest) {
getPieFeatures()
} else {
uiState.value = UiState.Error("Network Request failed.")
cancelNetworkRequests()
}
}
private fun maybeNotifyView() {
if (oreoFeaturesReceived && pieFeaturesReceived) {
uiState.value = UiState.Success(listOf(oreoFeaturesResult!!, pieFeaturesResult!!))
}
}
override fun onCleared() {
super.onCleared()
cancelNetworkRequests()
stopOreoFeaturesTimeoutHandler()
stopPieFeaturesTimeoutHandler()
}
private fun stopOreoFeaturesTimeoutHandler() {
Timber.d("stopping oreo Features Timeout Handler")
oreoFeaturesTimeoutHandler.removeCallbacksAndMessages(null)
}
private fun cancelNetworkRequests() {
oreoFeaturesCall.cancel()
pieFeaturesCall.cancel()
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase7/callbacks/UiState.kt
================================================
package com.demo.code.usecases.coroutines.usecase7.callbacks
import com.demo.code.mock.VersionFeatures
sealed class UiState {
object Loading : UiState()
data class Success(val versionFeatures: List) : UiState()
data class Error(val message: String) : UiState()
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase7/rx/MockApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase7.rx
import com.google.gson.Gson
import com.demo.code.mock.AndroidVersion
import com.demo.code.mock.VersionFeatures
import com.demo.code.mock.mockVersionFeaturesOreo
import com.demo.code.mock.mockVersionFeaturesPie
import com.demo.code.utils.MockNetworkInterceptor
import io.reactivex.Single
import io.reactivex.schedulers.Schedulers
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.http.GET
import retrofit2.http.Path
fun mockApi(): RxMockApi = createMockApi(
MockNetworkInterceptor()
// timeout on first request for oreo features
.mock(
"http://localhost/android-version-features/27",
Gson().toJson(mockVersionFeaturesOreo),
200,
1050,
persist = false
)
// network error on second request
.mock(
"http://localhost/android-version-features/27",
"Something went wrong on servers side",
500,
200,
persist = false
)
// 3rd request is successful and within timeout
.mock(
"http://localhost/android-version-features/27",
Gson().toJson(mockVersionFeaturesOreo),
200,
100
)
// timeout on first request for pie features
.mock(
"http://localhost/android-version-features/28",
Gson().toJson(mockVersionFeaturesPie),
200,
1050,
persist = false
)
// network error on second request
.mock(
"http://localhost/android-version-features/28",
"Something went wrong on servers side",
500,
200,
persist = false
)
// 3rd request is successful and within timeout
.mock(
"http://localhost/android-version-features/28",
Gson().toJson(mockVersionFeaturesPie),
200,
100
)
)
interface RxMockApi {
@GET("recent-android-versions")
fun getRecentAndroidVersions(): Single>
@GET("android-version-features/{apiLevel}")
fun getAndroidVersionFeatures(@Path("apiLevel") apiLevel: Int): Single
}
fun createMockApi(interceptor: MockNetworkInterceptor): RxMockApi {
val okHttpClient = OkHttpClient.Builder()
.addInterceptor(interceptor)
.build()
val retrofit = Retrofit.Builder()
.baseUrl("http://localhost/")
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
.build()
return retrofit.create(RxMockApi::class.java)
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase7/rx/TimeoutAndRetryRxActivity.kt
================================================
package com.demo.code.usecases.coroutines.usecase7.rx
import android.os.Bundle
import androidx.activity.viewModels
import androidx.lifecycle.Observer
import com.demo.code.base.BaseActivity
import com.demo.code.base.useCase7Description
import com.demo.code.databinding.ActivityRetrynetworkrequestBinding
import com.demo.code.utils.fromHtml
import com.demo.code.utils.setGone
import com.demo.code.utils.setVisible
import com.demo.code.utils.toast
class TimeoutAndRetryRxActivity : BaseActivity() {
override fun getToolbarTitle() = useCase7Description
private val binding by lazy { ActivityRetrynetworkrequestBinding.inflate(layoutInflater) }
private val viewModel: TimeoutAndRetryRxViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
viewModel.uiState().observe(this, Observer { uiState ->
if (uiState != null) {
render(uiState)
}
})
binding.btnPerformSingleNetworkRequest.setOnClickListener {
viewModel.performNetworkRequest()
}
}
private fun render(uiState: UiState) {
when (uiState) {
is UiState.Loading -> {
onLoad()
}
is UiState.Success -> {
onSuccess(uiState)
}
is UiState.Error -> {
onError(uiState)
}
}
}
private fun onLoad() = with(binding) {
progressBar.setVisible()
textViewResult.text = ""
btnPerformSingleNetworkRequest.isEnabled = false
}
private fun onSuccess(uiState: UiState.Success) = with(binding) {
progressBar.setGone()
btnPerformSingleNetworkRequest.isEnabled = true
val versionFeatures = uiState.versionFeatures
val versionFeaturesString = versionFeatures.map {
"New Features of ${it.androidVersion.name} ${it.features.joinToString(
prefix = "- ",
separator = " - "
)}"
}.joinToString(separator = " ")
textViewResult.text = fromHtml(versionFeaturesString)
}
private fun onError(uiState: UiState.Error) = with(binding) {
progressBar.setGone()
btnPerformSingleNetworkRequest.isEnabled = true
toast(uiState.message)
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase7/rx/TimeoutAndRetryRxViewModel.kt
================================================
package com.demo.code.usecases.coroutines.usecase7.rx
import com.demo.code.base.BaseViewModel
import com.demo.code.mock.VersionFeatures
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
import io.reactivex.functions.BiFunction
import io.reactivex.rxkotlin.addTo
import io.reactivex.rxkotlin.subscribeBy
import io.reactivex.schedulers.Schedulers
import timber.log.Timber
import java.util.concurrent.TimeUnit
class TimeoutAndRetryRxViewModel(
private val api: RxMockApi = mockApi()
) : BaseViewModel() {
private val disposables = CompositeDisposable()
fun performNetworkRequest() {
uiState.value = UiState.Loading
val timeout = 1000L
val numberOfRetries = 2
Single.zip(
api.getAndroidVersionFeatures(27)
.timeout(timeout, TimeUnit.MILLISECONDS)
.retry { x, e ->
Timber.e(e)
x <= numberOfRetries
},
api.getAndroidVersionFeatures(28)
.timeout(timeout, TimeUnit.MILLISECONDS)
.retry { x, e ->
Timber.e(e)
x <= numberOfRetries
},
BiFunction> { versionFeaturesOreo, versionFeaturesPie ->
listOf(versionFeaturesOreo, versionFeaturesPie)
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeBy(
onSuccess = { versionFeatures ->
uiState.value = UiState.Success(versionFeatures)
},
onError = { error ->
Timber.e(error)
uiState.value = UiState.Error("Network Request failed")
})
.addTo(disposables)
}
override fun onCleared() {
super.onCleared()
disposables.clear()
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase7/rx/UiState.kt
================================================
package com.demo.code.usecases.coroutines.usecase7.rx
import com.demo.code.mock.VersionFeatures
sealed class UiState {
object Loading : UiState()
data class Success(val versionFeatures: List) : UiState()
data class Error(val message: String) : UiState()
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase8/AndroidVersionDao.kt
================================================
package com.demo.code.usecases.coroutines.usecase8
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
@Dao
interface AndroidVersionDao {
@Query("SELECT * FROM androidversions")
suspend fun getAndroidVersions(): List
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(androidVersionEntity: AndroidVersionEntity)
@Query("DELETE FROM androidversions")
suspend fun clear()
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase8/AndroidVersionDatabase.kt
================================================
package com.demo.code.usecases.coroutines.usecase8
import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
@Database(entities = [AndroidVersionEntity::class], version = 1, exportSchema = false)
abstract class AndroidVersionDatabase : RoomDatabase() {
abstract fun androidVersionDao(): AndroidVersionDao
companion object {
private var INSTANCE: AndroidVersionDatabase? = null
fun getInstance(context: Context): AndroidVersionDatabase {
if (INSTANCE == null) {
synchronized(AndroidVersionDatabase::class) {
INSTANCE = buildRoomDb(context)
}
}
return INSTANCE!!
}
private fun buildRoomDb(context: Context) =
Room.databaseBuilder(
context.applicationContext,
AndroidVersionDatabase::class.java,
"androidversions.db"
).build()
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase8/AndroidVersionEntity.kt
================================================
package com.demo.code.usecases.coroutines.usecase8
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.demo.code.mock.AndroidVersion
@Entity(tableName = "androidversions")
data class AndroidVersionEntity(@PrimaryKey val apiLevel: Int, val name: String)
fun List.mapToUiModelList() = map {
AndroidVersion(it.apiLevel, it.name)
}
fun AndroidVersion.mapToEntity() = AndroidVersionEntity(this.apiLevel, this.name)
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase8/MockApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase8
import com.google.gson.Gson
import com.demo.code.mock.createMockApi
import com.demo.code.mock.mockAndroidVersions
import com.demo.code.utils.MockNetworkInterceptor
fun mockApi() =
createMockApi(
MockNetworkInterceptor()
.mock(
"http://localhost/recent-android-versions",
Gson().toJson(mockAndroidVersions),
200,
5000
)
)
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase8/RoomAndCoroutinesActivity.kt
================================================
package com.demo.code.usecases.coroutines.usecase8
import android.os.Bundle
import androidx.activity.viewModels
import androidx.lifecycle.Observer
import com.demo.code.R
import com.demo.code.base.BaseActivity
import com.demo.code.base.useCase8Description
import com.demo.code.databinding.ActivityQueryfromroomdatabaseBinding
import com.demo.code.utils.fromHtml
import com.demo.code.utils.setGone
import com.demo.code.utils.setVisible
import com.demo.code.utils.toast
class RoomAndCoroutinesActivity : BaseActivity() {
override fun getToolbarTitle() = useCase8Description
private val binding by lazy { ActivityQueryfromroomdatabaseBinding.inflate(layoutInflater) }
private val viewModel: RoomAndCoroutinesViewModel by viewModels {
ViewModelFactory(
mockApi(),
AndroidVersionDatabase.getInstance(applicationContext).androidVersionDao()
)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
viewModel.uiState().observe(this, Observer { uiState ->
if (uiState != null) {
render(uiState)
}
})
binding.btnLoadData.setOnClickListener {
viewModel.loadData()
}
binding.btnClearDatabase.setOnClickListener {
viewModel.clearDatabase()
}
}
private fun render(uiState: UiState) {
when (uiState) {
is UiState.Loading -> {
onLoad(uiState)
}
is UiState.Success -> {
onSuccess(uiState)
}
is UiState.Error -> {
onError(uiState)
}
}
}
private fun onLoad(loadingState: UiState.Loading) = with(binding) {
when (loadingState) {
UiState.Loading.LoadFromDb -> {
progressBarLoadFromDb.setVisible()
textViewLoadFromDatabase.setVisible()
imageViewDatabaseLoadSuccessOrError.setGone()
}
UiState.Loading.LoadFromNetwork -> {
progressBarLoadFromNetwork.setVisible()
textViewLoadFromNetwork.setVisible()
imageViewNetworkLoadSuccessOrError.setGone()
}
}
}
private fun onSuccess(uiState: UiState.Success) = with(binding) {
when (uiState.dataSource) {
DataSource.NETWORK -> {
progressBarLoadFromNetwork.setGone()
imageViewNetworkLoadSuccessOrError.setImageDrawable(getDrawable(R.drawable.ic_check_green_24dp))
imageViewNetworkLoadSuccessOrError.setVisible()
}
DataSource.DATABASE -> {
progressBarLoadFromDb.setGone()
imageViewDatabaseLoadSuccessOrError.setImageDrawable(getDrawable(R.drawable.ic_check_green_24dp))
imageViewDatabaseLoadSuccessOrError.setVisible()
}
}
val readableVersions = uiState.recentVersions.map { "API ${it.apiLevel}: ${it.name}" }
textViewResult.text = fromHtml(
"Recent Android Versions [from ${uiState.dataSource.name}] ${readableVersions.joinToString(
separator = " "
)}"
)
}
private fun onError(uiState: UiState.Error) = with(binding) {
when (uiState.dataSource) {
DataSource.NETWORK -> {
progressBarLoadFromNetwork.setGone()
imageViewNetworkLoadSuccessOrError.setImageDrawable(getDrawable(R.drawable.ic_clear_red_24dp))
imageViewNetworkLoadSuccessOrError.setVisible()
}
DataSource.DATABASE -> {
progressBarLoadFromDb.setGone()
imageViewDatabaseLoadSuccessOrError.setImageDrawable(getDrawable(R.drawable.ic_clear_red_24dp))
imageViewDatabaseLoadSuccessOrError.setVisible()
}
}
toast(uiState.message)
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase8/RoomAndCoroutinesViewModel.kt
================================================
package com.demo.code.usecases.coroutines.usecase8
import androidx.lifecycle.viewModelScope
import com.demo.code.base.BaseViewModel
import com.demo.code.mock.MockApi
import kotlinx.coroutines.launch
class RoomAndCoroutinesViewModel(
private val api: MockApi,
private val database: AndroidVersionDao
) : BaseViewModel() {
fun loadData() {
uiState.value = UiState.Loading.LoadFromDb
viewModelScope.launch {
val localVersions = database.getAndroidVersions()
if (localVersions.isEmpty()) {
uiState.value =
UiState.Error(DataSource.DATABASE, "Database empty!")
} else {
uiState.value =
UiState.Success(DataSource.DATABASE, localVersions.mapToUiModelList())
}
uiState.value = UiState.Loading.LoadFromNetwork
try {
val recentVersions = api.getRecentAndroidVersions()
for (version in recentVersions) {
database.insert(version.mapToEntity())
}
uiState.value = UiState.Success(DataSource.NETWORK, recentVersions)
} catch (exception: Exception) {
uiState.value = UiState.Error(DataSource.NETWORK, "Something went wrong!")
}
}
}
fun clearDatabase() {
viewModelScope.launch {
database.clear()
}
}
}
enum class DataSource(val dataSourceName: String) {
DATABASE("Database"),
NETWORK("Network")
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase8/UiState.kt
================================================
package com.demo.code.usecases.coroutines.usecase8
import com.demo.code.mock.AndroidVersion
sealed class UiState {
sealed class Loading : UiState() {
object LoadFromDb : Loading()
object LoadFromNetwork : Loading()
}
data class Success(val dataSource: DataSource, val recentVersions: List) :
UiState()
data class Error(val dataSource: DataSource, val message: String) : UiState()
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase8/ViewModelFactory.kt
================================================
package com.demo.code.usecases.coroutines.usecase8
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import com.demo.code.mock.MockApi
class ViewModelFactory(private val api: MockApi, private val database: AndroidVersionDao) :
ViewModelProvider.Factory {
override fun create(modelClass: Class): T {
return modelClass.getConstructor(MockApi::class.java, AndroidVersionDao::class.java)
.newInstance(api, database)
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase9/DebuggingCoroutinesActivity.kt
================================================
package com.demo.code.usecases.coroutines.usecase9
import android.os.Bundle
import androidx.activity.viewModels
import androidx.lifecycle.Observer
import com.demo.code.base.BaseActivity
import com.demo.code.base.useCase9Description
import com.demo.code.databinding.ActivityDebuggingcoroutinesBinding
import com.demo.code.utils.fromHtml
import com.demo.code.utils.setGone
import com.demo.code.utils.setVisible
import com.demo.code.utils.toast
class DebuggingCoroutinesActivity : BaseActivity() {
override fun getToolbarTitle() = useCase9Description
private val binding by lazy { ActivityDebuggingcoroutinesBinding.inflate(layoutInflater) }
private val viewModel: DebuggingCoroutinesViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
viewModel.uiState().observe(this, Observer { uiState ->
if (uiState != null) {
render(uiState)
}
})
binding.btnPerformSingleNetworkRequest.setOnClickListener {
viewModel.performSingleNetworkRequest()
}
}
private fun render(uiState: UiState) {
when (uiState) {
is UiState.Loading -> {
onLoad()
}
is UiState.Success -> {
onSuccess(uiState)
}
is UiState.Error -> {
onError(uiState)
}
}
}
private fun onLoad() = with(binding) {
progressBar.setVisible()
textViewResult.text = ""
btnPerformSingleNetworkRequest.isEnabled = false
}
private fun onSuccess(uiState: UiState.Success) = with(binding) {
progressBar.setGone()
btnPerformSingleNetworkRequest.isEnabled = true
val readableVersions = uiState.recentVersions.map { "API ${it.apiLevel}: ${it.name}" }
textViewResult.text = fromHtml(
"Recent Android Versions ${readableVersions.joinToString(separator = " ")}"
)
}
private fun onError(uiState: UiState.Error) = with(binding) {
progressBar.setGone()
btnPerformSingleNetworkRequest.isEnabled = true
toast(uiState.message)
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase9/DebuggingCoroutinesViewModel.kt
================================================
package com.demo.code.usecases.coroutines.usecase9
import androidx.lifecycle.viewModelScope
import com.demo.code.base.BaseViewModel
import com.demo.code.mock.MockApi
import com.demo.code.utils.addCoroutineDebugInfo
import kotlinx.coroutines.*
import timber.log.Timber
class DebuggingCoroutinesViewModel(
private val api: MockApi = mockApi()
) : BaseViewModel() {
fun performSingleNetworkRequest() {
uiState.value = UiState.Loading
// This property needs to be set so that the coroutine name is printed when logging Thread.currentName()
// System.setProperty("kotlinx.coroutines.debug", if (BuildConfig.DEBUG) "on" else "off")
// It is set in [CoroutineUsecasesOnAndroidApplication]
viewModelScope.launch(CoroutineName("Initial Coroutine")) {
Timber.d(addCoroutineDebugInfo("Initial coroutine launched"))
try {
val recentVersions = api.getRecentAndroidVersions()
Timber.d(addCoroutineDebugInfo("Recent Android Versions returned"))
uiState.value = UiState.Success(recentVersions)
} catch (exception: Exception) {
Timber.d(addCoroutineDebugInfo("Loading recent Android Versions failed"))
uiState.value = UiState.Error("Network Request failed")
}
// Perform two calculations in parallel
val calculation1Deferred =
async(CoroutineName("Calculation1")) { performCalculation1() }
val calculation2Deferred =
async(CoroutineName("Calculation2")) { performCalculation2() }
Timber.d(addCoroutineDebugInfo("Result of Calculation1: ${calculation1Deferred.await()}"))
Timber.d(addCoroutineDebugInfo("Result of Calculation2: ${calculation2Deferred.await()}"))
}
}
private suspend fun performCalculation1() = withContext(Dispatchers.Default) {
Timber.d(addCoroutineDebugInfo("Starting Calculation1"))
delay(1000)
Timber.d(addCoroutineDebugInfo("Calculation1 completed"))
13
}
private suspend fun performCalculation2() = withContext(Dispatchers.Default) {
Timber.d(addCoroutineDebugInfo("Starting Calculation2"))
delay(2000)
Timber.d(addCoroutineDebugInfo("Calculation2 completed"))
42
}
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase9/MockApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase9
import com.google.gson.Gson
import com.demo.code.mock.createMockApi
import com.demo.code.mock.mockAndroidVersions
import com.demo.code.utils.MockNetworkInterceptor
fun mockApi() =
createMockApi(
MockNetworkInterceptor()
.mock(
"http://localhost/recent-android-versions",
Gson().toJson(mockAndroidVersions),
200,
1500
)
)
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/coroutines/usecase9/UiState.kt
================================================
package com.demo.code.usecases.coroutines.usecase9
import com.demo.code.mock.AndroidVersion
sealed class UiState {
object Loading : UiState()
data class Success(val recentVersions: List) : UiState()
data class Error(val message: String) : UiState()
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/usecases/flow/usecase1/FlowUseCase1Activity.kt
================================================
package com.demo.code.usecases.flow.usecase1
import android.os.Bundle
import com.demo.code.base.BaseActivity
import com.demo.code.databinding.ActivityFlowUsecase1Binding
class FlowUseCase1Activity : BaseActivity() {
private val binding by lazy { ActivityFlowUsecase1Binding.inflate(layoutInflater) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
}
override fun getToolbarTitle() = "Flow Use Case 1 Activity"
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/utils/Extensions.kt
================================================
package com.demo.code.utils
import android.content.Context
import android.os.Build
import android.text.Html
import android.text.Spanned
import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.Toast
/**
* Extension method to show toast for Context.
*/
fun Context?.toast(text: CharSequence, duration: Int = Toast.LENGTH_LONG) =
this?.let { Toast.makeText(it, text, duration).show() }
fun fromHtml(source: String): Spanned {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Html.fromHtml(source, Html.FROM_HTML_MODE_LEGACY)
} else {
@Suppress("DEPRECATION")
Html.fromHtml(source)
}
}
fun View.setVisible() {
this.visibility = View.VISIBLE
}
fun View.setInvisible() {
this.visibility = View.INVISIBLE
}
fun View.setGone() {
this.visibility = View.GONE
}
fun logWithThreadAndCoroutineInfo(message: String) =
println("[${Thread.currentThread().name}] $message")
fun addCoroutineDebugInfo(message: String) = "[${Thread.currentThread().name}] $message"
/**
* From kotlinextensions.com
* Try to hide the keyboard and returns whether it worked
* https://stackoverflow.com/questions/1109022/close-hide-the-android-soft-keyboard
*/
fun View.hideKeyboard(): Boolean {
try {
val inputMethodManager =
context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
return inputMethodManager.hideSoftInputFromWindow(windowToken, 0)
} catch (ignored: RuntimeException) {
}
return false
}
================================================
FILE: application/Sample-Coroutines/app/src/main/java/com/demo/code/utils/MockNetworkInterceptor.kt
================================================
package com.demo.code.utils
import com.google.gson.Gson
import okhttp3.*
class MockNetworkInterceptor : Interceptor {
private val mockResponses = mutableListOf()
private val gson = Gson()
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()
val mockResponse = findMockResponseInList(request) ?: return chain.proceed(request)
removeResponseIfItShouldNotBePersisted(mockResponse)
simulateNetworkDelay(mockResponse)
return if (mockResponse.status < 400) {
createSuccessResponse(mockResponse, request)
} else {
createErrorResponse(request)
}
}
private fun findMockResponseInList(request: Request): MockResponse? {
return mockResponses.find { mockResponse ->
mockResponse.path == request.url().toString()
}
}
private fun removeResponseIfItShouldNotBePersisted(mockResponse: MockResponse) {
if (!mockResponse.persist) {
mockResponses.remove(mockResponse)
}
}
private fun simulateNetworkDelay(mockResponse: MockResponse) {
Thread.sleep(mockResponse.delayInMs)
}
private fun createErrorResponse(request: Request): Response {
return Response.Builder()
.code(500)
.request(request)
.protocol(Protocol.HTTP_1_1)
.message("Internal Server Error")
.body(
ResponseBody.create(
MediaType.get("application/json"),
gson.toJson(mapOf("cause" to "not sure"))
)
)
.build()
}
private fun createSuccessResponse(
mockResponse: MockResponse,
request: Request
): Response {
return Response.Builder()
.code(mockResponse.status)
.request(request)
.protocol(Protocol.HTTP_1_1)
.message("OK")
.body(
ResponseBody.create(
MediaType.get("application/json"),
mockResponse.body
)
)
.build()
}
fun mock(
path: String,
body: String,
status: Int,
delayInMs: Long = 250,
persist: Boolean = true
) = apply {
val mockResponse =
MockResponse(
path,
body,
status,
delayInMs,
persist
)
mockResponses.add(mockResponse)
}
companion object {
const val INTERNAL_SERVER_ERROR_HTTP_CODE = 500
}
}
data class MockResponse(
val path: String,
val body: String,
val status: Int,
val delayInMs: Long,
val persist: Boolean
)
================================================
FILE: application/Sample-Coroutines/app/src/main/res/drawable/ic_arrow_back_white.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/drawable/ic_check_green_24dp.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/drawable/ic_clear_red_24dp.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/drawable/ic_launcher_background.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/drawable/recyclerview_divider.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/layout/activity_calculateonmain.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/layout/activity_calculationinbackground.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/layout/activity_calculationinmultiplebackgroundthreads.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/layout/activity_channels_usecase1.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/layout/activity_cooperativecancellation.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/layout/activity_debuggingcoroutines.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/layout/activity_exceptionhandling.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/layout/activity_flow_usecase1.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/layout/activity_jobs.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/layout/activity_main.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/layout/activity_networkrequestwithtimeout.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/layout/activity_observable_types.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/layout/activity_perform2sequentialnetworkrequests.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/layout/activity_performanceanalysis.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/layout/activity_performnetworkrequestsconcurrently.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/layout/activity_performsinglenetworkrequest.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/layout/activity_performvariableamountofnetworkrequestsconcurrently.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/layout/activity_queryfromroomdatabase.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/layout/activity_retrynetworkrequest.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/layout/activity_selection.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/layout/activity_suspending_func.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/layout/activity_usecases.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/layout/activity_workmanger.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/layout/recyclerview_item.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/layout/recyclerview_item_calculation_result.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/layout/toolbar.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/main/res/values/colors.xml
================================================
#3F51B5
#303F9F
#C5CAE9
#FF9800
#212121
#757575
#FFFFFF
#BDBDBD
#FFFFFF
#00000000
================================================
FILE: application/Sample-Coroutines/app/src/main/res/values/dimens.xml
================================================
20sp
16dp
================================================
FILE: application/Sample-Coroutines/app/src/main/res/values/strings.xml
================================================
Coroutine Usecases on Android
Load recent Android Versions
Load Features of most recent Android Version
Load Features of Android Versions sequentially
Load Features of Android Versions concurrently
Operation took %d ms
Calculation took %d ms
Converting BigInteger to String took %d ms
TimeOut in ms:
Load Android Versions
Clear Database
loading data from database
loading data from network
Load Recent Android Versions and do some calculations
Factorial of:
Calculate
Number of Coroutines:
Your device has %d cores
Cancel
A work manager worker was requested to send an analytics request.
Coroutine Dispatcher:
yield() during calculation
Use Cases
Jobs
Suspending Functions
Observable Types
Shared Flow
Flow
State Flow
Live Data
Initial Value
- Default
- IO
- Main
- Unconfined
================================================
FILE: application/Sample-Coroutines/app/src/main/res/values/styles.xml
================================================
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/ExampleUnitTest.kt
================================================
package com.demo.code
import org.junit.Assert.assertEquals
import org.junit.Test
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/playground/testing/1_testing_coroutines.kt
================================================
package com.demo.code.playground.testing
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.runBlockingTest
import org.junit.Test
class SystemUnderTest {
suspend fun functionWithDelay(): Int {
delay(1000)
return 42
}
}
fun CoroutineScope.functionThatStartsNewCoroutine() {
launch {
delay(1000)
println("Coroutine completed!")
}
}
class TestClass {
@Test
fun `functionWithDelay should return 42`() = runBlockingTest {
val realTimeStart = System.currentTimeMillis()
val virtualTimeStart = currentTime
functionThatStartsNewCoroutine()
advanceTimeBy(1000)
val realTimeDuration = System.currentTimeMillis() - realTimeStart
val virtualTimeDuration = currentTime - virtualTimeStart
println("Test took $realTimeDuration real ms")
println("Test took $virtualTimeDuration virtual ms")
}
}
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/usecases/coroutines/usecase1/FakeErrorApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase1
import com.demo.code.mock.AndroidVersion
import com.demo.code.mock.MockApi
import com.demo.code.mock.VersionFeatures
import com.demo.code.utils.EndpointShouldNotBeCalledException
import okhttp3.MediaType
import okhttp3.ResponseBody
import retrofit2.HttpException
import retrofit2.Response
class FakeErrorApi() : MockApi {
override suspend fun getRecentAndroidVersions(): List {
throw HttpException(
Response.error>(
500,
ResponseBody.create(MediaType.parse("application/json"), "")
)
)
}
override suspend fun getAndroidVersionFeatures(apiLevel: Int): VersionFeatures {
throw EndpointShouldNotBeCalledException()
}
}
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/usecases/coroutines/usecase1/FakeSuccessApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase1
import com.demo.code.mock.AndroidVersion
import com.demo.code.mock.MockApi
import com.demo.code.mock.VersionFeatures
import com.demo.code.mock.mockAndroidVersions
import com.demo.code.utils.EndpointShouldNotBeCalledException
class FakeSuccessApi() : MockApi {
override suspend fun getRecentAndroidVersions(): List {
return mockAndroidVersions
}
override suspend fun getAndroidVersionFeatures(apiLevel: Int): VersionFeatures {
throw EndpointShouldNotBeCalledException()
}
}
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/usecases/coroutines/usecase1/PerformSingleNetworkRequestViewModelTest.kt
================================================
package com.demo.code.usecases.coroutines.usecase1
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.demo.code.mock.mockAndroidVersions
import com.demo.code.utils.MainCoroutineScopeRule
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runBlockingTest
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TestRule
@ExperimentalCoroutinesApi
class PerformSingleNetworkRequestViewModelTest {
@get:Rule
val testInstantTaskExecutorRule: TestRule = InstantTaskExecutorRule()
@get: Rule
val mainCoroutineScopeRule: MainCoroutineScopeRule = MainCoroutineScopeRule()
private val receivedUiStates = mutableListOf()
@Test
fun `should return Success when network request is successful`() =
mainCoroutineScopeRule.runBlockingTest {
val fakeApi = FakeSuccessApi()
val viewModel =
PerformSingleNetworkRequestViewModel(fakeApi)
observeViewModel(viewModel)
assertTrue(receivedUiStates.isEmpty())
viewModel.performSingleNetworkRequest()
assertEquals(
listOf(
UiState.Loading,
UiState.Success(mockAndroidVersions)
),
receivedUiStates
)
}
@Test
fun `should return Error when network request fails`() =
mainCoroutineScopeRule.runBlockingTest {
val fakeApi = FakeErrorApi()
val viewModel =
PerformSingleNetworkRequestViewModel(fakeApi)
observeViewModel(viewModel)
assertTrue(receivedUiStates.isEmpty())
viewModel.performSingleNetworkRequest()
assertEquals(
listOf(
UiState.Loading,
UiState.Error("Network Request failed!")
),
receivedUiStates
)
}
private fun observeViewModel(viewModel: PerformSingleNetworkRequestViewModel) {
viewModel.uiState().observeForever { uiState ->
if (uiState != null) {
receivedUiStates.add(uiState)
}
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/usecases/coroutines/usecase10/CalculationInBackgroundViewModelTest.kt
================================================
package com.demo.code.usecases.coroutines.usecase10
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.demo.code.utils.MainCoroutineScopeRule
import kotlinx.coroutines.test.runBlockingTest
import org.junit.Assert
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TestRule
class CalculationInBackgroundViewModelTest {
@get:Rule
val testInstantTaskExecutorRule: TestRule = InstantTaskExecutorRule()
@get: Rule
val mainCoroutineScopeRule: MainCoroutineScopeRule = MainCoroutineScopeRule()
private val receivedUiStates = mutableListOf()
@Test
fun `performCalculation() should perform correct calculations`() =
mainCoroutineScopeRule.runBlockingTest {
val viewModel =
CalculationInBackgroundViewModel(mainCoroutineScopeRule.testDispatcher).apply {
observe()
}
Assert.assertTrue(receivedUiStates.isEmpty())
viewModel.performCalculation(1)
Assert.assertEquals(
UiState.Loading,
receivedUiStates.first()
)
Assert.assertEquals(
"1",
(receivedUiStates[1] as UiState.Success).result
)
receivedUiStates.clear()
viewModel.performCalculation(2)
Assert.assertEquals(
UiState.Loading,
receivedUiStates.first()
)
Assert.assertEquals(
"2",
(receivedUiStates[1] as UiState.Success).result
)
receivedUiStates.clear()
viewModel.performCalculation(3)
Assert.assertEquals(
UiState.Loading,
receivedUiStates.first()
)
Assert.assertEquals(
"6",
(receivedUiStates[1] as UiState.Success).result
)
}
private fun CalculationInBackgroundViewModel.observe() {
uiState().observeForever { uiState ->
if (uiState != null) {
receivedUiStates.add(uiState)
}
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/usecases/coroutines/usecase12/FactorialCalculatorTest.kt
================================================
package com.demo.code.usecases.coroutines.usecase12
import junit.framework.Assert.assertEquals
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestCoroutineDispatcher
import kotlinx.coroutines.test.runBlockingTest
import org.junit.Before
import org.junit.Test
import java.math.BigInteger
@ExperimentalCoroutinesApi
class FactorialCalculatorTest {
lateinit var factorialCalculator: FactorialCalculator
private val testDispatcher = TestCoroutineDispatcher()
@Before
fun setUp() {
factorialCalculator = FactorialCalculator(testDispatcher)
}
@Test
fun `createSubRangeList() should create correct range lists`() = runBlockingTest {
assertEquals(
listOf(
SubRange(1, 3),
SubRange(4, 6),
SubRange(7, 9)
),
factorialCalculator.createSubRangeList(9, 3)
)
assertEquals(
listOf(
SubRange(1, 3),
SubRange(4, 6),
SubRange(7, 10)
),
factorialCalculator.createSubRangeList(10, 3)
)
assertEquals(
listOf(
SubRange(1, 3),
SubRange(4, 6),
SubRange(7, 11)
),
factorialCalculator.createSubRangeList(11, 3)
)
}
@Test
fun calculateFactorialOfSubRange() = runBlockingTest {
assertEquals(
BigInteger.valueOf(6),
factorialCalculator.calculateFactorialOfSubRange(SubRange(1, 3))
)
assertEquals(
BigInteger.valueOf(120),
factorialCalculator.calculateFactorialOfSubRange(SubRange(4, 6))
)
assertEquals(
BigInteger.valueOf(55440),
factorialCalculator.calculateFactorialOfSubRange(SubRange(7, 11))
)
}
@Test
fun calculateFactorial() = runBlockingTest {
assertEquals(
BigInteger.valueOf(3628800),
factorialCalculator.calculateFactorial(10, 3)
)
}
}
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/usecases/coroutines/usecase14/AndroidVersionRepositoryTest.kt
================================================
package com.demo.code.usecases.coroutines.usecase14
import com.demo.code.mock.mockAndroidVersions
import com.demo.code.utils.MainCoroutineScopeRule
import junit.framework.Assert.assertEquals
import junit.framework.Assert.fail
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.TestCoroutineScope
import kotlinx.coroutines.test.runBlockingTest
import org.junit.Rule
import org.junit.Test
@ExperimentalCoroutinesApi
class AndroidVersionRepositoryTest {
@get: Rule
val mainCoroutineScopeRule: MainCoroutineScopeRule = MainCoroutineScopeRule()
@Test
fun `getLocalAndroidVersions() should return android versions from database`() =
mainCoroutineScopeRule.runBlockingTest {
val fakeDatabase = FakeDatabase()
val repository = AndroidVersionRepository(fakeDatabase, mainCoroutineScopeRule)
assertEquals(mockAndroidVersions, repository.getLocalAndroidVersions())
}
@Test
fun `loadRecentAndroidVersions() should return android versions from network`() =
mainCoroutineScopeRule.runBlockingTest {
val fakeDatabase = FakeDatabase()
val fakeApi = FakeApi()
val repository = AndroidVersionRepository(
fakeDatabase,
mainCoroutineScopeRule,
api = fakeApi
)
assertEquals(mockAndroidVersions, repository.loadAndStoreRemoteAndroidVersions())
}
@Test
fun `loadRecentAndroidVersions() should continue to load and store android versions when calling scope gets cancelled`() =
mainCoroutineScopeRule.runBlockingTest {
val fakeDatabase = FakeDatabase()
val fakeApi = FakeApi()
val repository = AndroidVersionRepository(
fakeDatabase,
mainCoroutineScopeRule,
api = fakeApi
)
// this coroutine will be executed immediately (eagerly)
// how ever, it will stop its execution at the delay(1) in the fakeApi
val viewModelScope = TestCoroutineScope(SupervisorJob())
viewModelScope.launch {
println("running coroutine!")
repository.loadAndStoreRemoteAndroidVersions()
fail("Scope should be cancelled before versions are loaded!")
}
viewModelScope.cancel()
// continue coroutine execution after delay(1) in the fakeApi
advanceUntilIdle()
assertEquals(true, fakeDatabase.insertedIntoDb)
}
}
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/usecases/coroutines/usecase14/FakeApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase14
import com.demo.code.mock.AndroidVersion
import com.demo.code.mock.MockApi
import com.demo.code.mock.VersionFeatures
import com.demo.code.mock.mockAndroidVersions
import com.demo.code.utils.EndpointShouldNotBeCalledException
import kotlinx.coroutines.delay
class FakeApi : MockApi {
override suspend fun getRecentAndroidVersions(): List {
delay(1)
return mockAndroidVersions
}
override suspend fun getAndroidVersionFeatures(apiLevel: Int): VersionFeatures {
throw EndpointShouldNotBeCalledException()
}
}
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/usecases/coroutines/usecase14/FakeDatabase.kt
================================================
package com.demo.code.usecases.coroutines.usecase14
import com.demo.code.mock.mockAndroidVersions
class FakeDatabase : AndroidVersionDao {
var insertedIntoDb = false
override suspend fun getAndroidVersions(): List {
return mockAndroidVersions.mapToEntityList()
}
override suspend fun insert(androidVersionEntity: AndroidVersionEntity) {
insertedIntoDb = true
}
override suspend fun clear() {}
}
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/usecases/coroutines/usecase2/FakeFeaturesErrorApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase2
import com.demo.code.mock.*
import okhttp3.MediaType
import okhttp3.ResponseBody
import retrofit2.HttpException
import retrofit2.Response
class FakeFeaturesErrorApi : MockApi {
override suspend fun getRecentAndroidVersions(): List {
return mockAndroidVersions
}
override suspend fun getAndroidVersionFeatures(apiLevel: Int): VersionFeatures {
return when (apiLevel) {
27 -> mockVersionFeaturesOreo
28 -> mockVersionFeaturesPie
29 -> throw HttpException(
Response.error>(
500,
ResponseBody.create(MediaType.parse("application/json"), "")
)
)
else -> throw IllegalArgumentException("apiLevel not found")
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/usecases/coroutines/usecase2/FakeSuccessApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase2
import com.demo.code.mock.*
class FakeSuccessApi : MockApi {
override suspend fun getRecentAndroidVersions(): List {
return mockAndroidVersions
}
override suspend fun getAndroidVersionFeatures(apiLevel: Int): VersionFeatures {
return when (apiLevel) {
27 -> mockVersionFeaturesOreo
28 -> mockVersionFeaturesPie
29 -> mockVersionFeaturesAndroid10
else -> throw IllegalArgumentException("apiLevel not found")
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/usecases/coroutines/usecase2/FakeVersionsErrorApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase2
import com.demo.code.mock.AndroidVersion
import com.demo.code.mock.MockApi
import com.demo.code.mock.VersionFeatures
import com.demo.code.utils.EndpointShouldNotBeCalledException
import okhttp3.MediaType
import okhttp3.ResponseBody
import retrofit2.HttpException
import retrofit2.Response
class FakeVersionsErrorApi : MockApi {
override suspend fun getRecentAndroidVersions(): List {
throw HttpException(
Response.error>(
500,
ResponseBody.create(MediaType.parse("application/json"), "")
)
)
}
override suspend fun getAndroidVersionFeatures(apiLevel: Int): VersionFeatures {
throw EndpointShouldNotBeCalledException()
}
}
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/usecases/coroutines/usecase2/Perform2SequentialNetworkRequestsViewModelTest.kt
================================================
package com.demo.code.usecases.coroutines.usecase2
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.demo.code.mock.mockVersionFeaturesAndroid10
import com.demo.code.utils.MainCoroutineScopeRule
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runBlockingTest
import org.junit.Assert
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TestRule
@ExperimentalCoroutinesApi
class Perform2SequentialNetworkRequestsViewModelTest {
@get:Rule
val testInstantTaskExecutorRule: TestRule = InstantTaskExecutorRule()
@get: Rule
val mainCoroutineScopeRule: MainCoroutineScopeRule = MainCoroutineScopeRule()
private val receivedUiStates = mutableListOf()
@Test
fun `should return Success when both network requests are successful`() =
mainCoroutineScopeRule.runBlockingTest {
val fakeApi = FakeSuccessApi()
val viewModel =
Perform2SequentialNetworkRequestsViewModel(
fakeApi
)
viewModel.observe()
Assert.assertTrue(receivedUiStates.isEmpty())
viewModel.perform2SequentialNetworkRequest()
Assert.assertEquals(
listOf(
UiState.Loading,
UiState.Success(mockVersionFeaturesAndroid10)
),
receivedUiStates
)
}
@Test
fun `should return Error when first network requests fails`() =
mainCoroutineScopeRule.runBlockingTest {
val fakeApi = FakeVersionsErrorApi()
val viewModel =
Perform2SequentialNetworkRequestsViewModel(
fakeApi
)
viewModel.observe()
Assert.assertTrue(receivedUiStates.isEmpty())
viewModel.perform2SequentialNetworkRequest()
Assert.assertEquals(
listOf(
UiState.Loading,
UiState.Error("Network Request failed")
),
receivedUiStates
)
}
@Test
fun `should return Error when second network requests fails`() =
mainCoroutineScopeRule.runBlockingTest {
val fakeApi = FakeFeaturesErrorApi()
val viewModel =
Perform2SequentialNetworkRequestsViewModel(
fakeApi
)
viewModel.observe()
Assert.assertTrue(receivedUiStates.isEmpty())
viewModel.perform2SequentialNetworkRequest()
Assert.assertEquals(
listOf(
UiState.Loading,
UiState.Error("Network Request failed")
),
receivedUiStates
)
}
private fun Perform2SequentialNetworkRequestsViewModel.observe() {
uiState().observeForever { uiState ->
if (uiState != null) {
receivedUiStates.add(uiState)
}
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/usecases/coroutines/usecase2/callbacks/FakeFeaturesErrorApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase2.callbacks
import com.demo.code.mock.AndroidVersion
import com.demo.code.mock.VersionFeatures
import com.demo.code.mock.mockAndroidVersions
import retrofit2.Call
import retrofit2.mock.Calls
import java.io.IOException
class FakeFeaturesErrorApi : CallbackMockApi {
override fun getRecentAndroidVersions(): Call> {
return Calls.response(mockAndroidVersions)
}
override fun getAndroidVersionFeatures(apiLevel: Int): Call {
return Calls.failure(IOException())
}
}
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/usecases/coroutines/usecase2/callbacks/FakeSuccessApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase2.callbacks
import com.demo.code.mock.*
import retrofit2.Call
import retrofit2.mock.Calls
class FakeSuccessApi : CallbackMockApi {
override fun getRecentAndroidVersions(): Call> {
return Calls.response(mockAndroidVersions)
}
override fun getAndroidVersionFeatures(apiLevel: Int): Call {
val featureMocks = when (apiLevel) {
27 -> mockVersionFeaturesOreo
28 -> mockVersionFeaturesPie
29 -> mockVersionFeaturesAndroid10
else -> throw IllegalArgumentException("apiLevel not found")
}
return Calls.response(featureMocks)
}
}
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/usecases/coroutines/usecase2/callbacks/FakeVersionsErrorApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase2.callbacks
import com.demo.code.mock.AndroidVersion
import com.demo.code.mock.VersionFeatures
import com.demo.code.mock.mockAndroidVersions
import retrofit2.Call
import retrofit2.mock.Calls
import java.io.IOException
class FakeVersionsErrorApi : CallbackMockApi {
override fun getRecentAndroidVersions(): Call> {
return Calls.response(mockAndroidVersions)
}
override fun getAndroidVersionFeatures(apiLevel: Int): Call {
return Calls.failure(IOException())
}
}
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/usecases/coroutines/usecase2/callbacks/SequentialNetworkRequestsCallbacksViewModelTest.kt
================================================
package com.demo.code.usecases.coroutines.usecase2.callbacks
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.demo.code.mock.mockVersionFeaturesAndroid10
import org.junit.Assert
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TestRule
class SequentialNetworkRequestsCallbacksViewModelTest {
@get:Rule
val testInstantTaskExecutorRule: TestRule = InstantTaskExecutorRule()
private val receivedUiStates: MutableList =
arrayListOf()
@Test
fun `should return Success when both network requests are successful`() {
val fakeApi = FakeSuccessApi()
val viewModel =
SequentialNetworkRequestsCallbacksViewModel(
fakeApi
)
viewModel.observe()
Assert.assertTrue(receivedUiStates.isEmpty())
viewModel.perform2SequentialNetworkRequest()
Assert.assertEquals(
listOf(
UiState.Loading,
UiState.Success(mockVersionFeaturesAndroid10)
),
receivedUiStates
)
}
@Test
fun `should return Error when first network request (recent-android-versions) fails`() {
val fakeApi = FakeVersionsErrorApi()
val viewModel =
SequentialNetworkRequestsCallbacksViewModel(
fakeApi
)
viewModel.observe()
Assert.assertTrue(receivedUiStates.isEmpty())
viewModel.perform2SequentialNetworkRequest()
Assert.assertEquals(
listOf(
UiState.Loading,
UiState.Error("Network Request failed")
),
receivedUiStates
)
}
@Test
fun `should return Error when second network requests (android-version-features) fails`() {
val fakeApi = FakeFeaturesErrorApi()
val viewModel =
SequentialNetworkRequestsCallbacksViewModel(
fakeApi
)
viewModel.observe()
Assert.assertTrue(receivedUiStates.isEmpty())
viewModel.perform2SequentialNetworkRequest()
Assert.assertEquals(
listOf(
UiState.Loading,
UiState.Error("Network Request failed")
),
receivedUiStates
)
}
private fun SequentialNetworkRequestsCallbacksViewModel.observe() {
uiState().observeForever { uiState ->
if (uiState != null) {
receivedUiStates.add(uiState)
}
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/usecases/coroutines/usecase3/FakeErrorApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase3
import com.demo.code.mock.*
import com.demo.code.utils.EndpointShouldNotBeCalledException
import kotlinx.coroutines.delay
import okhttp3.MediaType
import okhttp3.ResponseBody
import retrofit2.HttpException
import retrofit2.Response
class FakeErrorApi(private val responseDelay: Long) : MockApi {
override suspend fun getRecentAndroidVersions(): List {
throw EndpointShouldNotBeCalledException()
}
override suspend fun getAndroidVersionFeatures(apiLevel: Int): VersionFeatures {
delay(responseDelay)
return when (apiLevel) {
27 -> mockVersionFeaturesOreo
28 -> throw HttpException(
Response.error>(
500,
ResponseBody.create(MediaType.parse("application/json"), "")
)
)
29 -> mockVersionFeaturesAndroid10
else -> throw IllegalArgumentException("apiLevel not found")
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/usecases/coroutines/usecase3/FakeSuccessApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase3
import com.demo.code.mock.*
import com.demo.code.utils.EndpointShouldNotBeCalledException
import kotlinx.coroutines.delay
class FakeSuccessApi(private val responseDelay: Long) : MockApi {
override suspend fun getRecentAndroidVersions(): List {
throw EndpointShouldNotBeCalledException()
}
override suspend fun getAndroidVersionFeatures(apiLevel: Int): VersionFeatures {
delay(responseDelay)
return when (apiLevel) {
27 -> mockVersionFeaturesOreo
28 -> mockVersionFeaturesPie
29 -> mockVersionFeaturesAndroid10
else -> throw IllegalArgumentException("apiLevel not found")
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/usecases/coroutines/usecase3/PerformNetworkRequestsConcurrentlyViewModelTest.kt
================================================
package com.demo.code.usecases.coroutines.usecase3
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.demo.code.mock.mockVersionFeaturesAndroid10
import com.demo.code.mock.mockVersionFeaturesOreo
import com.demo.code.mock.mockVersionFeaturesPie
import com.demo.code.utils.MainCoroutineScopeRule
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runBlockingTest
import org.junit.Assert
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TestRule
@ExperimentalCoroutinesApi
class PerformNetworkRequestsConcurrentlyViewModelTest {
@get:Rule
val testInstantTaskExecutorRule: TestRule = InstantTaskExecutorRule()
@get: Rule
val mainCoroutineScopeRule: MainCoroutineScopeRule = MainCoroutineScopeRule()
private val receivedUiStates = mutableListOf()
@Test
fun `performNetworkRequestsSequentially should return data after 3 times the response delay`() =
mainCoroutineScopeRule.runBlockingTest {
val responseDelay = 1000L
val fakeApi = FakeSuccessApi(responseDelay)
val viewModel = PerformNetworkRequestsConcurrentlyViewModel(fakeApi)
viewModel.observe()
Assert.assertTrue(receivedUiStates.isEmpty())
viewModel.performNetworkRequestsSequentially()
val forwardedTime = advanceUntilIdle()
Assert.assertEquals(
listOf(
UiState.Loading,
UiState.Success(
listOf(
mockVersionFeaturesOreo,
mockVersionFeaturesPie,
mockVersionFeaturesAndroid10
)
)
),
receivedUiStates
)
// Verify that requests actually got executed sequentially and it took
// 3000ms to receive all data
Assert.assertEquals(
3000,
forwardedTime
)
}
@Test
fun `performNetworkRequestsConcurrently should return data after the response delay`() =
mainCoroutineScopeRule.runBlockingTest {
val responseDelay = 1000L
val fakeApi = FakeSuccessApi(responseDelay)
val viewModel = PerformNetworkRequestsConcurrentlyViewModel(fakeApi)
viewModel.observe()
Assert.assertTrue(receivedUiStates.isEmpty())
viewModel.performNetworkRequestsConcurrently()
val forwardedTime = advanceUntilIdle()
Assert.assertEquals(
listOf(
UiState.Loading,
UiState.Success(
listOf(
mockVersionFeaturesOreo,
mockVersionFeaturesPie,
mockVersionFeaturesAndroid10
)
)
),
receivedUiStates
)
// Verify that requests actually got executed concurrently within 1000ms
Assert.assertEquals(
1000,
forwardedTime
)
}
@Test
fun `performNetworkRequestsConcurrently should return Error when network request fails`() =
mainCoroutineScopeRule.runBlockingTest {
val responseDelay = 1000L
val fakeApi = FakeErrorApi(responseDelay)
val viewModel = PerformNetworkRequestsConcurrentlyViewModel(fakeApi)
viewModel.observe()
Assert.assertTrue(receivedUiStates.isEmpty())
viewModel.performNetworkRequestsConcurrently()
advanceUntilIdle()
Assert.assertEquals(
listOf(
UiState.Loading,
UiState.Error("Network Request failed")
),
receivedUiStates
)
}
private fun PerformNetworkRequestsConcurrentlyViewModel.observe() {
uiState().observeForever { uiState ->
if (uiState != null) {
receivedUiStates.add(uiState)
}
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/usecases/coroutines/usecase4/FakeFeaturesErrorApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase4
import com.demo.code.mock.*
import kotlinx.coroutines.delay
import okhttp3.MediaType
import okhttp3.ResponseBody
import retrofit2.HttpException
import retrofit2.Response
class FakeFeaturesErrorApi(private val responseDelay: Long) : MockApi {
override suspend fun getRecentAndroidVersions(): List {
delay(responseDelay)
return mockAndroidVersions
}
override suspend fun getAndroidVersionFeatures(apiLevel: Int): VersionFeatures {
delay(responseDelay)
return when (apiLevel) {
27 -> mockVersionFeaturesOreo
28 -> throw HttpException(
Response.error>(
500,
ResponseBody.create(MediaType.parse("application/json"), "")
)
)
29 -> mockVersionFeaturesAndroid10
else -> throw IllegalArgumentException("apiLevel not found")
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/usecases/coroutines/usecase4/FakeSuccessApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase4
import com.demo.code.mock.*
import kotlinx.coroutines.delay
class FakeSuccessApi(private val responseDelay: Long) : MockApi {
override suspend fun getRecentAndroidVersions(): List {
delay(1000)
return mockAndroidVersions
}
override suspend fun getAndroidVersionFeatures(apiLevel: Int): VersionFeatures {
delay(responseDelay)
return when (apiLevel) {
27 -> mockVersionFeaturesOreo
28 -> mockVersionFeaturesPie
29 -> mockVersionFeaturesAndroid10
else -> throw IllegalArgumentException("apiLevel not found")
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/usecases/coroutines/usecase4/FakeVersionsErrorApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase4
import com.demo.code.mock.AndroidVersion
import com.demo.code.mock.MockApi
import com.demo.code.mock.VersionFeatures
import com.demo.code.utils.EndpointShouldNotBeCalledException
import kotlinx.coroutines.delay
import okhttp3.MediaType
import okhttp3.ResponseBody
import retrofit2.HttpException
import retrofit2.Response
class FakeVersionsErrorApi(private val responseDelay: Long) : MockApi {
override suspend fun getRecentAndroidVersions(): List {
delay(responseDelay)
throw throw HttpException(
Response.error>(
500,
ResponseBody.create(MediaType.parse("application/json"), "")
)
)
}
override suspend fun getAndroidVersionFeatures(apiLevel: Int): VersionFeatures {
throw EndpointShouldNotBeCalledException()
}
}
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/usecases/coroutines/usecase4/VariableAmountOfNetworkRequestsViewModelTest.kt
================================================
package com.demo.code.usecases.coroutines.usecase4
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.demo.code.mock.mockVersionFeaturesAndroid10
import com.demo.code.mock.mockVersionFeaturesOreo
import com.demo.code.mock.mockVersionFeaturesPie
import com.demo.code.utils.MainCoroutineScopeRule
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runBlockingTest
import org.junit.Assert
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TestRule
@ExperimentalCoroutinesApi
class VariableAmountOfNetworkRequestsViewModelTest {
@get:Rule
val testInstantTaskExecutorRule: TestRule = InstantTaskExecutorRule()
@get: Rule
val mainCoroutineScopeRule: MainCoroutineScopeRule = MainCoroutineScopeRule()
private val receivedUiStates = mutableListOf()
@Test
fun `performNetworkRequestsSequentially() should return Success UiState on successful network requests after 4000ms`() =
mainCoroutineScopeRule.runBlockingTest {
val responseDelay = 1000L
val fakeApi = FakeSuccessApi(responseDelay)
val viewModel = VariableAmountOfNetworkRequestsViewModel(fakeApi)
viewModel.observe()
Assert.assertTrue(receivedUiStates.isEmpty())
viewModel.performNetworkRequestsSequentially()
val forwardedTime = advanceUntilIdle()
Assert.assertEquals(
listOf(
UiState.Loading,
UiState.Success(
listOf(
mockVersionFeaturesOreo,
mockVersionFeaturesPie,
mockVersionFeaturesAndroid10
)
)
),
receivedUiStates
)
Assert.assertEquals(
4000,
forwardedTime
)
}
@Test
fun `performNetworkRequestsSequentially() should return Error UiState on unsuccessful recent-android-versions network request`() =
mainCoroutineScopeRule.runBlockingTest {
val responseDelay = 1000L
val fakeApi = FakeVersionsErrorApi(responseDelay)
val viewModel = VariableAmountOfNetworkRequestsViewModel(fakeApi)
viewModel.observe()
Assert.assertTrue(receivedUiStates.isEmpty())
viewModel.performNetworkRequestsSequentially()
advanceUntilIdle()
Assert.assertEquals(
listOf(
UiState.Loading,
UiState.Error("Network Request failed")
),
receivedUiStates
)
}
@Test
fun `performNetworkRequestsSequentially() should return Error UiState on unsuccessful android-version-features network request`() =
mainCoroutineScopeRule.runBlockingTest {
val responseDelay = 1000L
val fakeApi = FakeFeaturesErrorApi(responseDelay)
val viewModel = VariableAmountOfNetworkRequestsViewModel(fakeApi)
viewModel.observe()
Assert.assertTrue(receivedUiStates.isEmpty())
viewModel.performNetworkRequestsSequentially()
advanceUntilIdle()
Assert.assertEquals(
listOf(
UiState.Loading,
UiState.Error("Network Request failed")
),
receivedUiStates
)
}
@Test
fun `performNetworkRequestsConcurrently() should return Error UiState on successful network requests after 2000ms`() =
mainCoroutineScopeRule.runBlockingTest {
val responseDelay = 1000L
val fakeApi = FakeSuccessApi(responseDelay)
val viewModel = VariableAmountOfNetworkRequestsViewModel(fakeApi)
viewModel.observe()
Assert.assertTrue(receivedUiStates.isEmpty())
viewModel.performNetworkRequestsConcurrently()
val forwardedTime = advanceUntilIdle()
Assert.assertEquals(
listOf(
UiState.Loading,
UiState.Success(
listOf(
mockVersionFeaturesOreo,
mockVersionFeaturesPie,
mockVersionFeaturesAndroid10
)
)
),
receivedUiStates
)
Assert.assertEquals(
2000,
forwardedTime
)
}
@Test
fun `performNetworkRequestsConcurrently() should return Error UiState on unsuccessful recent-android-versions network request`() =
mainCoroutineScopeRule.runBlockingTest {
val responseDelay = 1000L
val fakeApi = FakeVersionsErrorApi(responseDelay)
val viewModel = VariableAmountOfNetworkRequestsViewModel(fakeApi)
viewModel.observe()
Assert.assertTrue(receivedUiStates.isEmpty())
viewModel.performNetworkRequestsSequentially()
advanceUntilIdle()
Assert.assertEquals(
listOf(
UiState.Loading,
UiState.Error("Network Request failed")
),
receivedUiStates
)
}
@Test
fun `performNetworkRequestsConcurrently() should return Error UiState on unsuccessful android-version-features network request`() =
mainCoroutineScopeRule.runBlockingTest {
val responseDelay = 1000L
val fakeApi = FakeFeaturesErrorApi(responseDelay)
val viewModel = VariableAmountOfNetworkRequestsViewModel(fakeApi)
viewModel.observe()
Assert.assertTrue(receivedUiStates.isEmpty())
viewModel.performNetworkRequestsSequentially()
advanceUntilIdle()
Assert.assertEquals(
listOf(
UiState.Loading,
UiState.Error("Network Request failed")
),
receivedUiStates
)
}
private fun VariableAmountOfNetworkRequestsViewModel.observe() {
uiState().observeForever { uiState ->
if (uiState != null) {
receivedUiStates.add(uiState)
}
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/usecases/coroutines/usecase5/FakeSuccessApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase5
import com.demo.code.mock.*
import kotlinx.coroutines.delay
class FakeSuccessApi(private val responseDelay: Long) : MockApi {
override suspend fun getRecentAndroidVersions(): List {
delay(1000)
return mockAndroidVersions
}
override suspend fun getAndroidVersionFeatures(apiLevel: Int): VersionFeatures {
delay(responseDelay)
return when (apiLevel) {
27 -> mockVersionFeaturesOreo
28 -> mockVersionFeaturesPie
29 -> mockVersionFeaturesAndroid10
else -> throw IllegalArgumentException("apiLevel not found")
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/usecases/coroutines/usecase5/FakeVersionsErrorApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase5
import com.demo.code.mock.AndroidVersion
import com.demo.code.mock.MockApi
import com.demo.code.mock.VersionFeatures
import com.demo.code.utils.EndpointShouldNotBeCalledException
import kotlinx.coroutines.delay
import okhttp3.MediaType
import okhttp3.ResponseBody
import retrofit2.HttpException
import retrofit2.Response
class FakeVersionsErrorApi(private val responseDelay: Long) : MockApi {
override suspend fun getRecentAndroidVersions(): List {
delay(responseDelay)
throw throw HttpException(
Response.error>(
500,
ResponseBody.create(MediaType.parse("application/json"), "")
)
)
}
override suspend fun getAndroidVersionFeatures(apiLevel: Int): VersionFeatures {
throw EndpointShouldNotBeCalledException()
}
}
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/usecases/coroutines/usecase5/NetworkRequestWithTimeoutViewModelTest.kt
================================================
package com.demo.code.usecases.coroutines.usecase5
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.demo.code.mock.mockAndroidVersions
import com.demo.code.utils.MainCoroutineScopeRule
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runBlockingTest
import org.junit.Assert
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TestRule
@ExperimentalCoroutinesApi
class NetworkRequestWithTimeoutViewModelTest {
@get:Rule
val testInstantTaskExecutorRule: TestRule = InstantTaskExecutorRule()
@get: Rule
val mainCoroutineScopeRule: MainCoroutineScopeRule = MainCoroutineScopeRule()
private val receivedUiStates = mutableListOf()
@Test
fun `performNetworkRequest() should return Success UiState on successful network request within timeout`() =
mainCoroutineScopeRule.runBlockingTest {
val responseDelay = 1000L
val timeout = 1001L
val fakeApi = FakeSuccessApi(responseDelay)
val viewModel = NetworkRequestWithTimeoutViewModel(fakeApi)
viewModel.observe()
Assert.assertTrue(receivedUiStates.isEmpty())
viewModel.performNetworkRequest(timeout)
advanceUntilIdle()
Assert.assertEquals(
listOf(
UiState.Loading,
UiState.Success(mockAndroidVersions)
),
receivedUiStates
)
}
@Test
fun `performNetworkRequest() should return Error UiState with timeout error message if timeout gets exceeded`() =
mainCoroutineScopeRule.runBlockingTest {
val responseDelay = 1000L
val timeout = 999L
val fakeApi = FakeSuccessApi(responseDelay)
val viewModel = NetworkRequestWithTimeoutViewModel(fakeApi)
viewModel.observe()
Assert.assertTrue(receivedUiStates.isEmpty())
viewModel.performNetworkRequest(timeout)
advanceUntilIdle()
Assert.assertEquals(
listOf(
UiState.Loading,
UiState.Error("Network Request timed out!")
),
receivedUiStates
)
}
@Test
fun `performNetworkRequest() should return Error UiState on unsuccessful network response`() =
mainCoroutineScopeRule.runBlockingTest {
val responseDelay = 1000L
val timeout = 1001L
val fakeApi = FakeVersionsErrorApi(responseDelay)
val viewModel = NetworkRequestWithTimeoutViewModel(fakeApi)
viewModel.observe()
Assert.assertTrue(receivedUiStates.isEmpty())
viewModel.performNetworkRequest(timeout)
advanceUntilIdle()
Assert.assertEquals(
listOf(
UiState.Loading,
UiState.Error("Network Request failed!")
),
receivedUiStates
)
}
private fun NetworkRequestWithTimeoutViewModel.observe() {
uiState().observeForever { uiState ->
if (uiState != null) {
receivedUiStates.add(uiState)
}
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/usecases/coroutines/usecase6/FakeSuccessApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase6
import com.demo.code.mock.*
import kotlinx.coroutines.delay
class FakeSuccessApi(private val responseDelay: Long) : MockApi {
override suspend fun getRecentAndroidVersions(): List {
delay(1000)
return mockAndroidVersions
}
override suspend fun getAndroidVersionFeatures(apiLevel: Int): VersionFeatures {
delay(responseDelay)
return when (apiLevel) {
27 -> mockVersionFeaturesOreo
28 -> mockVersionFeaturesPie
29 -> mockVersionFeaturesAndroid10
else -> throw IllegalArgumentException("apiLevel not found")
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/usecases/coroutines/usecase6/FakeSuccessOnThirdAttemptApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase6
import com.demo.code.mock.AndroidVersion
import com.demo.code.mock.MockApi
import com.demo.code.mock.VersionFeatures
import com.demo.code.mock.mockAndroidVersions
import com.demo.code.utils.EndpointShouldNotBeCalledException
import kotlinx.coroutines.delay
import java.io.IOException
class FakeSuccessOnThirdAttemptApi(private val responseDelay: Long) : MockApi {
var requestCount = 0
override suspend fun getRecentAndroidVersions(): List {
requestCount++
delay(responseDelay)
if (requestCount < 3) {
throw IOException()
}
return mockAndroidVersions
}
override suspend fun getAndroidVersionFeatures(apiLevel: Int): VersionFeatures {
throw EndpointShouldNotBeCalledException()
}
}
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/usecases/coroutines/usecase6/FakeVersionsErrorApi.kt
================================================
package com.demo.code.usecases.coroutines.usecase6
import com.demo.code.mock.AndroidVersion
import com.demo.code.mock.MockApi
import com.demo.code.mock.VersionFeatures
import com.demo.code.utils.EndpointShouldNotBeCalledException
import kotlinx.coroutines.delay
import okhttp3.MediaType
import okhttp3.ResponseBody
import retrofit2.HttpException
import retrofit2.Response
class FakeVersionsErrorApi(private val responseDelay: Long) : MockApi {
var requestCount = 0
override suspend fun getRecentAndroidVersions(): List {
requestCount++
delay(responseDelay)
throw throw HttpException(
Response.error>(
500,
ResponseBody.create(MediaType.parse("application/json"), "")
)
)
}
override suspend fun getAndroidVersionFeatures(apiLevel: Int): VersionFeatures {
throw EndpointShouldNotBeCalledException()
}
}
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/usecases/coroutines/usecase6/RetryNetworkRequestViewModelTest.kt
================================================
package com.demo.code.usecases.coroutines.usecase6
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.demo.code.mock.mockAndroidVersions
import com.demo.code.utils.MainCoroutineScopeRule
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runBlockingTest
import org.junit.Assert
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TestRule
@ExperimentalCoroutinesApi
class RetryNetworkRequestViewModelTest {
@get:Rule
val testInstantTaskExecutorRule: TestRule = InstantTaskExecutorRule()
@get: Rule
val mainCoroutineScopeRule: MainCoroutineScopeRule = MainCoroutineScopeRule()
private val receivedUiStates = mutableListOf()
@Test
fun `performSingleNetworkRequest() should return Success UiState on successful network response`() =
mainCoroutineScopeRule.runBlockingTest {
val responseDelay = 1000L
val fakeApi = FakeSuccessApi(responseDelay)
val viewModel = RetryNetworkRequestViewModel(fakeApi).apply {
observe()
}
Assert.assertTrue(receivedUiStates.isEmpty())
viewModel.performNetworkRequest()
advanceUntilIdle()
Assert.assertEquals(
listOf(
UiState.Loading,
UiState.Success(mockAndroidVersions)
),
receivedUiStates
)
}
@Test
fun `performSingleNetworkRequest() should retry network request two times`() =
mainCoroutineScopeRule.runBlockingTest {
val responseDelay = 1000L
val fakeApi = FakeSuccessOnThirdAttemptApi(responseDelay)
val viewModel = RetryNetworkRequestViewModel(fakeApi).apply {
observe()
}
Assert.assertTrue(receivedUiStates.isEmpty())
viewModel.performNetworkRequest()
val elapsedTime = advanceUntilIdle()
Assert.assertEquals(
listOf(
UiState.Loading,
UiState.Success(mockAndroidVersions)
),
receivedUiStates
)
Assert.assertEquals(
3,
fakeApi.requestCount
)
// 3*1000 (Request delays) + 100 (initial delay) + 200 (second delay)
Assert.assertEquals(
3300,
elapsedTime
)
}
@Test
fun `performSingleNetworkRequest() should return Error UiState on 3 unsuccessful network responses`() =
mainCoroutineScopeRule.runBlockingTest {
val responseDelay = 1000L
val fakeApi = FakeVersionsErrorApi(responseDelay)
val viewModel = RetryNetworkRequestViewModel(fakeApi).apply {
observe()
}
Assert.assertTrue(receivedUiStates.isEmpty())
viewModel.performNetworkRequest()
val elapsedTime = advanceUntilIdle()
Assert.assertEquals(
listOf(
UiState.Loading,
UiState.Error("Network Request failed")
),
receivedUiStates
)
Assert.assertEquals(
3,
fakeApi.requestCount
)
// 3*1000 response delays + 100 (initial delay) + 200 (second delay)
Assert.assertEquals(
3300,
elapsedTime
)
}
private fun RetryNetworkRequestViewModel.observe() {
uiState().observeForever { uiState ->
if (uiState != null) {
receivedUiStates.add(uiState)
}
}
}
}
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/utils/EndpointShouldNotBeCalledException.kt
================================================
package com.demo.code.utils
class EndpointShouldNotBeCalledException : Throwable()
================================================
FILE: application/Sample-Coroutines/app/src/test/java/com/demo/code/utils/MainCoroutineScopeRule.kt
================================================
package com.demo.code.utils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestCoroutineDispatcher
import kotlinx.coroutines.test.TestCoroutineScope
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.setMain
import org.junit.rules.TestWatcher
import org.junit.runner.Description
// https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-test/
// see: https://github.com/googlecodelabs/kotlin-coroutines/blob/master/coroutines-codelab/finished_code/src/test/java/com/example/android/kotlincoroutines/main/utils/MainCoroutineScopeRule.kt
@ExperimentalCoroutinesApi
class MainCoroutineScopeRule(
val testDispatcher: TestCoroutineDispatcher = TestCoroutineDispatcher()
) : TestWatcher(),
TestCoroutineScope by TestCoroutineScope(testDispatcher) {
override fun starting(description: Description?) {
super.starting(description)
Dispatchers.setMain(testDispatcher)
}
override fun finished(description: Description?) {
super.finished(description)
cleanupTestCoroutines()
Dispatchers.resetMain()
}
}
================================================
FILE: application/Sample-Coroutines/build.gradle.kts
================================================
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath("com.android.tools.build:gradle:${Versions.gradle}")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${Versions.kotlin}")
classpath("com.google.dagger:hilt-android-gradle-plugin:${Versions.version_dagger}")
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
tasks.register("clean", Delete::class) {
delete(rootProject.buildDir)
}
================================================
FILE: application/Sample-Coroutines/buildSrc/build.gradle.kts
================================================
import org.gradle.kotlin.dsl.`kotlin-dsl`
plugins {
`kotlin-dsl`
}
repositories {
jcenter()
}
================================================
FILE: application/Sample-Coroutines/buildSrc/src/main/java/AppConfig.kt
================================================
object AppConfig {
const val compileSdk = 31
const val minSdk = 21
const val targetSdk = 30
const val versionCode = 1
const val versionName = "1.0.0"
const val buildToolsVersion = "29.0.3"
const val androidTestInstrumentation = "androidx.test.runner.AndroidJUnitRunner"
const val proguardConsumerRules = "consumer-rules.pro"
const val dimension = "environment"
}
================================================
FILE: application/Sample-Coroutines/buildSrc/src/main/java/AppDependencies.kt
================================================
import org.gradle.api.artifacts.dsl.DependencyHandler
object AppDependencies {
//test libs
private const val junit = "junit:junit:${Versions.junit}"
private const val coreTesting = "androidx.arch.core:core-testing:${Versions.version_core_testing}"
private const val coroutinesTest = "org.jetbrains.kotlinx:kotlinx-coroutines-test:${Versions.version_coroutines}"
private const val retrofitMock = "com.squareup.retrofit2:retrofit-mock:${Versions.version_retrofit_mock}"
private const val extJUnit = "androidx.test.ext:junit:${Versions.extJunit}"
private const val espressoCore = "androidx.test.espresso:espresso-core:${Versions.espresso}"
private const val kotlinStdLib = "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${Versions.kotlin}"
private const val coroutinesCore = "org.jetbrains.kotlinx:kotlinx-coroutines-core:${Versions.version_coroutines}"
private const val coroutinesAndroid = "org.jetbrains.kotlinx:kotlinx-coroutines-android:${Versions.version_coroutines}"
private const val appcompat = "androidx.appcompat:appcompat:${Versions.version_appcompat}"
private const val material = "com.google.android.material:material:${Versions.version_google_material}"
private const val constraintLayout = "androidx.constraintlayout:constraintlayout:${Versions.version_constraint_layout}"
private const val recyclerView = "androidx.recyclerview:recyclerview:${Versions.version_recyclerview}"
private const val cardView = "androidx.cardview:cardview:${Versions.version_card_view}"
private const val commonJava8 = "androidx.lifecycle:lifecycle-common-java8:${Versions.version_lifecycle}"
private const val retrofit = "com.squareup.retrofit2:retrofit:${Versions.version_retrofit}"
private const val rxJava2 = "com.squareup.retrofit2:adapter-rxjava2:${Versions.version_adapter_rxjava2}"
private const val gson = "com.google.code.gson:gson:${Versions.version_gson}"
private const val converterGson = "com.squareup.retrofit2:converter-gson:${Versions.version_converter_gson}"
private const val rxAndroid = "io.reactivex.rxjava2:rxandroid:${Versions.version_rx_android}"
private const val rxJava = "io.reactivex.rxjava2:rxjava:${Versions.version_rxjava}"
private const val rxKotlin = "io.reactivex.rxjava2:rxkotlin:${Versions.version_rxkotlin}"
private const val workRuntime = "androidx.work:work-runtime:${Versions.version_work_manager}"
private const val timber = "com.jakewharton.timber:timber:${Versions.version_timber}"
private const val roomRuntime = "androidx.room:room-runtime:${Versions.version_room}"
private const val roomCompiler = "androidx.room:room-compiler:${Versions.version_room}"
private const val hiltAndroid = "com.google.dagger:hilt-android:${Versions.version_dagger}"
private const val hiltCompiler = "com.google.dagger:hilt-compiler:${Versions.version_dagger}"
private const val coreKtx = "androidx.core:core-ktx:${Versions.version_ktx_core}"
private const val activityKtx = "androidx.activity:activity-ktx:${Versions.version_ktx_activity}"
private const val viewModelKtx = "androidx.lifecycle:lifecycle-viewmodel-ktx${Versions.version_lifecycle}"
private const val liveDataKtx = "androidx.lifecycle:lifecycle-livedata-ktx:${Versions.version_lifecycle}"
private const val liveDataCompiler = "androidx.lifecycle:lifecycle-compiler:${Versions.version_lifecycle}"
private const val workRuntimeKtx = "androidx.work:work-runtime-ktx:${Versions.version_work_manager}"
private const val roomKtx = "androidx.room:room-ktx:${Versions.version_room}"
val appLibraries = arrayListOf().apply {
add(kotlinStdLib)
add(coroutinesCore)
add(coroutinesAndroid)
add(appcompat)
add(material)
add(constraintLayout)
add(recyclerView)
add(cardView)
add(commonJava8)
add(retrofit)
add(rxJava2)
add(gson)
add(converterGson)
add(rxAndroid)
add(rxJava)
add(rxKotlin)
add(workRuntime)
add(timber)
add(roomRuntime)
add(hiltAndroid)
add(viewModelKtx)
add(liveDataKtx)
add(coreKtx)
add(roomKtx)
add(activityKtx)
add(workRuntimeKtx)
}
val appLibrariesKtx = arrayListOf().apply {
add(liveDataCompiler)
add(roomCompiler)
add(hiltCompiler)
}
val androidTestLibraries = arrayListOf().apply {
add(extJUnit)
add(espressoCore)
}
val testLibraries = arrayListOf().apply {
add(junit)
add(coreTesting)
add(coroutinesTest)
add(retrofitMock)
}
}
//util functions for adding the different type dependencies from build.gradle file
fun DependencyHandler.kapt(list: List) {
list.forEach { dependency -> add("kapt", dependency) }
}
fun DependencyHandler.implementation(list: List) {
list.forEach { dependency -> add("implementation", dependency) }
}
fun DependencyHandler.androidTestImplementation(list: List) {
list.forEach { dependency -> add("androidTestImplementation", dependency) }
}
fun DependencyHandler.testImplementation(list: List) {
list.forEach { dependency -> add("testImplementation", dependency) }
}
================================================
FILE: application/Sample-Coroutines/buildSrc/src/main/java/BuildPlugins.kt
================================================
object BuildPlugins {
const val androidHilt = "dagger.hilt.android.plugin"
const val androidLibrary = "com.android.library"
const val androidApplication = "com.android.application"
const val kotlinAndroid = "kotlin-android"
const val kotlinKapt = "kotlin-kapt"
const val kotlinAndroidExtensions = "kotlin-android-extensions"
}
================================================
FILE: application/Sample-Coroutines/buildSrc/src/main/java/Versions.kt
================================================
object Versions {
//app level
const val gradle = "4.0.1"
const val kotlin = "1.4.0"
//test
const val junit = "4.12"
const val extJunit = "1.1.1"
const val espresso = "3.2.0"
const val version_coroutines = "1.5.0"
const val version_appcompat = "1.3.1"
const val version_google_material = "1.4.0"
const val version_ktx_core = "1.7.0"
const val version_ktx_activity = "1.4.0"
const val version_constraint_layout= "2.1.1"
const val version_recyclerview = "1.2.1"
const val version_card_view = "1.0.0"
const val version_lifecycle = "2.4.0"
const val version_retrofit = "2.9.0"
const val version_adapter_rxjava2 = "2.7.1"
const val version_gson = "2.4.0"
const val version_converter_gson = "2.9.0"
const val version_rx_android = "2.1.1"
const val version_rxjava = "2.2.19"
const val version_rxkotlin = "2.4.0"
const val version_work_manager = "2.7.0"
const val version_timber = "4.7.1"
const val version_room = "2.3.0"
const val version_dagger = "2.38.1"
const val version_core_testing = "2.1.0"
const val version_retrofit_mock = "2.7.1"
}
================================================
FILE: application/Sample-Coroutines/gradle/wrapper/gradle-wrapper.properties
================================================
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
================================================
FILE: application/Sample-Coroutines/gradle.properties
================================================
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
# Android operating system, and which are packaged with your app"s APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
android.enableJetifier=true
# Kotlin code style for this project: "official" or "obsolete":
kotlin.code.style=official
================================================
FILE: application/Sample-Coroutines/gradlew
================================================
#!/bin/sh
#
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
##############################################################################
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"
================================================
FILE: application/Sample-Coroutines/gradlew.bat
================================================
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
================================================
FILE: application/Sample-Coroutines/settings.gradle.kts
================================================
//include(":repository", ":core", ":app")
include(":app")
rootProject.name = "My Application"