diff --git a/README.md b/README.md index cdfa28c6..b9c44f55 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,16 @@ Our app is designed to be easy to use and lightweight. Plus, it's free and open Download Android Studio Tutorials: Java Edition from the Google Play Store and begin your Android development journey today. It's free, easy to use, and perfect for beginners. +## Architecture + +The app follows the modern layered architecture recommended by Google. The UI layer observes +immutable state from ViewModels. Business logic is encapsulated in use case classes within the +domain layer, which interact with repositories in the data layer. Each screen now exposes its +operations through a small set of use cases. This pattern was inspired by the +[Android Clean Architecture](https://github.com/android10/Android-CleanArchitecture) sample but +implemented in a simplified form to avoid adding heavy dependencies. The result keeps the UI +simple and ensures a clear separation of concerns across the whole app. + ## Feedback We are constantly updating and improving Android Studio Tutorials: Java Edition to give you the best possible experience. If you have suggested features or improvements, please leave a review. If something isn't working correctly, let us know so we can fix it. diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/domain/about/GetCurrentYearUseCase.java b/app/src/main/java/com/d4rk/androidtutorials/java/domain/about/GetCurrentYearUseCase.java new file mode 100644 index 00000000..fbd94e0f --- /dev/null +++ b/app/src/main/java/com/d4rk/androidtutorials/java/domain/about/GetCurrentYearUseCase.java @@ -0,0 +1,16 @@ +package com.d4rk.androidtutorials.java.domain.about; + +import com.d4rk.androidtutorials.java.ui.screens.about.repository.AboutRepository; + +/** Provides current year as a string. */ +public class GetCurrentYearUseCase { + private final AboutRepository repository; + + public GetCurrentYearUseCase(AboutRepository repository) { + this.repository = repository; + } + + public String invoke() { + return repository.getCurrentYear(); + } +} diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/domain/about/GetVersionStringUseCase.java b/app/src/main/java/com/d4rk/androidtutorials/java/domain/about/GetVersionStringUseCase.java new file mode 100644 index 00000000..00839cda --- /dev/null +++ b/app/src/main/java/com/d4rk/androidtutorials/java/domain/about/GetVersionStringUseCase.java @@ -0,0 +1,16 @@ +package com.d4rk.androidtutorials.java.domain.about; + +import com.d4rk.androidtutorials.java.ui.screens.about.repository.AboutRepository; + +/** Returns the formatted app version string. */ +public class GetVersionStringUseCase { + private final AboutRepository repository; + + public GetVersionStringUseCase(AboutRepository repository) { + this.repository = repository; + } + + public String invoke() { + return repository.getVersionString(); + } +} diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/domain/android/GetLessonUseCase.java b/app/src/main/java/com/d4rk/androidtutorials/java/domain/android/GetLessonUseCase.java new file mode 100644 index 00000000..d8768c92 --- /dev/null +++ b/app/src/main/java/com/d4rk/androidtutorials/java/domain/android/GetLessonUseCase.java @@ -0,0 +1,16 @@ +package com.d4rk.androidtutorials.java.domain.android; + +import com.d4rk.androidtutorials.java.ui.screens.android.repository.LessonRepository; + +/** Retrieves lesson data by name. */ +public class GetLessonUseCase { + private final LessonRepository repository; + + public GetLessonUseCase(LessonRepository repository) { + this.repository = repository; + } + + public LessonRepository.Lesson invoke(String lessonName) { + return repository.getLesson(lessonName); + } +} diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/domain/help/LaunchReviewFlowUseCase.java b/app/src/main/java/com/d4rk/androidtutorials/java/domain/help/LaunchReviewFlowUseCase.java new file mode 100644 index 00000000..fd38e5e7 --- /dev/null +++ b/app/src/main/java/com/d4rk/androidtutorials/java/domain/help/LaunchReviewFlowUseCase.java @@ -0,0 +1,18 @@ +package com.d4rk.androidtutorials.java.domain.help; + +import android.app.Activity; +import com.d4rk.androidtutorials.java.ui.screens.help.repository.HelpRepository; +import com.google.android.play.core.review.ReviewInfo; + +/** Launches the in-app review flow. */ +public class LaunchReviewFlowUseCase { + private final HelpRepository repository; + + public LaunchReviewFlowUseCase(HelpRepository repository) { + this.repository = repository; + } + + public void invoke(Activity activity, ReviewInfo info) { + repository.launchReviewFlow(activity, info); + } +} diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/domain/help/RequestReviewFlowUseCase.java b/app/src/main/java/com/d4rk/androidtutorials/java/domain/help/RequestReviewFlowUseCase.java new file mode 100644 index 00000000..f5c4aada --- /dev/null +++ b/app/src/main/java/com/d4rk/androidtutorials/java/domain/help/RequestReviewFlowUseCase.java @@ -0,0 +1,16 @@ +package com.d4rk.androidtutorials.java.domain.help; + +import com.d4rk.androidtutorials.java.ui.screens.help.repository.HelpRepository; + +/** Requests the Google Play review flow. */ +public class RequestReviewFlowUseCase { + private final HelpRepository repository; + + public RequestReviewFlowUseCase(HelpRepository repository) { + this.repository = repository; + } + + public void invoke(HelpRepository.OnReviewInfoListener listener) { + repository.requestReviewFlow(listener); + } +} diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/domain/home/GetDailyTipUseCase.java b/app/src/main/java/com/d4rk/androidtutorials/java/domain/home/GetDailyTipUseCase.java new file mode 100644 index 00000000..b77e8f4a --- /dev/null +++ b/app/src/main/java/com/d4rk/androidtutorials/java/domain/home/GetDailyTipUseCase.java @@ -0,0 +1,19 @@ +package com.d4rk.androidtutorials.java.domain.home; + +import com.d4rk.androidtutorials.java.ui.screens.home.repository.HomeRepository; + +/** Use case that provides the daily tip text. */ +public class GetDailyTipUseCase { + private final HomeRepository repository; + + public GetDailyTipUseCase(HomeRepository repository) { + this.repository = repository; + } + + /** + * Returns today's tip string. + */ + public String invoke() { + return repository.getDailyTip(); + } +} diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/domain/home/GetPromotedAppsUseCase.java b/app/src/main/java/com/d4rk/androidtutorials/java/domain/home/GetPromotedAppsUseCase.java new file mode 100644 index 00000000..b48e781e --- /dev/null +++ b/app/src/main/java/com/d4rk/androidtutorials/java/domain/home/GetPromotedAppsUseCase.java @@ -0,0 +1,26 @@ +package com.d4rk.androidtutorials.java.domain.home; + +import com.d4rk.androidtutorials.java.data.model.PromotedApp; +import com.d4rk.androidtutorials.java.ui.screens.home.repository.HomeRepository; + +import java.util.List; + +/** Use case that fetches promoted apps from the repository. */ +public class GetPromotedAppsUseCase { + private final HomeRepository repository; + + public interface Callback { + void onResult(List apps); + } + + public GetPromotedAppsUseCase(HomeRepository repository) { + this.repository = repository; + } + + /** + * Fetches the promoted apps and returns them via the callback. + */ + public void invoke(Callback callback) { + repository.fetchPromotedApps(callback::onResult); + } +} diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/domain/main/ApplyLanguageSettingsUseCase.java b/app/src/main/java/com/d4rk/androidtutorials/java/domain/main/ApplyLanguageSettingsUseCase.java new file mode 100644 index 00000000..0af07c4c --- /dev/null +++ b/app/src/main/java/com/d4rk/androidtutorials/java/domain/main/ApplyLanguageSettingsUseCase.java @@ -0,0 +1,16 @@ +package com.d4rk.androidtutorials.java.domain.main; + +import com.d4rk.androidtutorials.java.ui.screens.main.repository.MainRepository; + +/** Applies the saved language preference. */ +public class ApplyLanguageSettingsUseCase { + private final MainRepository repository; + + public ApplyLanguageSettingsUseCase(MainRepository repository) { + this.repository = repository; + } + + public void invoke() { + repository.applyLanguageSettings(); + } +} diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/domain/main/ApplyThemeSettingsUseCase.java b/app/src/main/java/com/d4rk/androidtutorials/java/domain/main/ApplyThemeSettingsUseCase.java new file mode 100644 index 00000000..0fa78538 --- /dev/null +++ b/app/src/main/java/com/d4rk/androidtutorials/java/domain/main/ApplyThemeSettingsUseCase.java @@ -0,0 +1,16 @@ +package com.d4rk.androidtutorials.java.domain.main; + +import com.d4rk.androidtutorials.java.ui.screens.main.repository.MainRepository; + +/** Applies theme preference and returns true if changed. */ +public class ApplyThemeSettingsUseCase { + private final MainRepository repository; + + public ApplyThemeSettingsUseCase(MainRepository repository) { + this.repository = repository; + } + + public boolean invoke(String[] darkModeValues) { + return repository.applyThemeSettings(darkModeValues); + } +} diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/domain/main/BuildShortcutIntentUseCase.java b/app/src/main/java/com/d4rk/androidtutorials/java/domain/main/BuildShortcutIntentUseCase.java new file mode 100644 index 00000000..be557a5e --- /dev/null +++ b/app/src/main/java/com/d4rk/androidtutorials/java/domain/main/BuildShortcutIntentUseCase.java @@ -0,0 +1,17 @@ +package com.d4rk.androidtutorials.java.domain.main; + +import android.content.Intent; +import com.d4rk.androidtutorials.java.ui.screens.main.repository.MainRepository; + +/** Creates an intent for the app shortcut. */ +public class BuildShortcutIntentUseCase { + private final MainRepository repository; + + public BuildShortcutIntentUseCase(MainRepository repository) { + this.repository = repository; + } + + public Intent invoke(boolean isInstalled) { + return repository.buildShortcutIntent(isInstalled); + } +} diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/domain/main/GetAppUpdateManagerUseCase.java b/app/src/main/java/com/d4rk/androidtutorials/java/domain/main/GetAppUpdateManagerUseCase.java new file mode 100644 index 00000000..dec14c16 --- /dev/null +++ b/app/src/main/java/com/d4rk/androidtutorials/java/domain/main/GetAppUpdateManagerUseCase.java @@ -0,0 +1,17 @@ +package com.d4rk.androidtutorials.java.domain.main; + +import com.d4rk.androidtutorials.java.ui.screens.main.repository.MainRepository; +import com.google.android.play.core.appupdate.AppUpdateManager; + +/** Provides the AppUpdateManager instance. */ +public class GetAppUpdateManagerUseCase { + private final MainRepository repository; + + public GetAppUpdateManagerUseCase(MainRepository repository) { + this.repository = repository; + } + + public AppUpdateManager invoke() { + return repository.getAppUpdateManager(); + } +} diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/domain/main/GetBottomNavLabelVisibilityUseCase.java b/app/src/main/java/com/d4rk/androidtutorials/java/domain/main/GetBottomNavLabelVisibilityUseCase.java new file mode 100644 index 00000000..121e2760 --- /dev/null +++ b/app/src/main/java/com/d4rk/androidtutorials/java/domain/main/GetBottomNavLabelVisibilityUseCase.java @@ -0,0 +1,16 @@ +package com.d4rk.androidtutorials.java.domain.main; + +import com.d4rk.androidtutorials.java.ui.screens.main.repository.MainRepository; + +/** Returns bottom navigation label visibility preference. */ +public class GetBottomNavLabelVisibilityUseCase { + private final MainRepository repository; + + public GetBottomNavLabelVisibilityUseCase(MainRepository repository) { + this.repository = repository; + } + + public String invoke(String key, String defaultValue) { + return repository.getBottomNavLabelVisibility(key, defaultValue); + } +} diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/domain/main/GetDefaultTabPreferenceUseCase.java b/app/src/main/java/com/d4rk/androidtutorials/java/domain/main/GetDefaultTabPreferenceUseCase.java new file mode 100644 index 00000000..37460727 --- /dev/null +++ b/app/src/main/java/com/d4rk/androidtutorials/java/domain/main/GetDefaultTabPreferenceUseCase.java @@ -0,0 +1,16 @@ +package com.d4rk.androidtutorials.java.domain.main; + +import com.d4rk.androidtutorials.java.ui.screens.main.repository.MainRepository; + +/** Returns the default tab preference string. */ +public class GetDefaultTabPreferenceUseCase { + private final MainRepository repository; + + public GetDefaultTabPreferenceUseCase(MainRepository repository) { + this.repository = repository; + } + + public String invoke(String key, String defaultValue) { + return repository.getDefaultTabPreference(key, defaultValue); + } +} diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/domain/main/IsAppInstalledUseCase.java b/app/src/main/java/com/d4rk/androidtutorials/java/domain/main/IsAppInstalledUseCase.java new file mode 100644 index 00000000..a1a2522a --- /dev/null +++ b/app/src/main/java/com/d4rk/androidtutorials/java/domain/main/IsAppInstalledUseCase.java @@ -0,0 +1,17 @@ +package com.d4rk.androidtutorials.java.domain.main; + +import android.content.pm.PackageManager; +import com.d4rk.androidtutorials.java.ui.screens.main.repository.MainRepository; + +/** Checks if an app is installed by package name. */ +public class IsAppInstalledUseCase { + private final MainRepository repository; + + public IsAppInstalledUseCase(MainRepository repository) { + this.repository = repository; + } + + public boolean invoke(PackageManager pm, String packageName) { + return repository.isAppInstalled(pm, packageName); + } +} diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/domain/main/MarkStartupScreenShownUseCase.java b/app/src/main/java/com/d4rk/androidtutorials/java/domain/main/MarkStartupScreenShownUseCase.java new file mode 100644 index 00000000..cd6b0e2a --- /dev/null +++ b/app/src/main/java/com/d4rk/androidtutorials/java/domain/main/MarkStartupScreenShownUseCase.java @@ -0,0 +1,16 @@ +package com.d4rk.androidtutorials.java.domain.main; + +import com.d4rk.androidtutorials.java.ui.screens.main.repository.MainRepository; + +/** Marks that the startup screen has been shown. */ +public class MarkStartupScreenShownUseCase { + private final MainRepository repository; + + public MarkStartupScreenShownUseCase(MainRepository repository) { + this.repository = repository; + } + + public void invoke() { + repository.markStartupScreenShown(); + } +} diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/domain/main/ShouldShowStartupScreenUseCase.java b/app/src/main/java/com/d4rk/androidtutorials/java/domain/main/ShouldShowStartupScreenUseCase.java new file mode 100644 index 00000000..7967b28d --- /dev/null +++ b/app/src/main/java/com/d4rk/androidtutorials/java/domain/main/ShouldShowStartupScreenUseCase.java @@ -0,0 +1,16 @@ +package com.d4rk.androidtutorials.java.domain.main; + +import com.d4rk.androidtutorials.java.ui.screens.main.repository.MainRepository; + +/** Determines if the startup screen should be shown. */ +public class ShouldShowStartupScreenUseCase { + private final MainRepository repository; + + public ShouldShowStartupScreenUseCase(MainRepository repository) { + this.repository = repository; + } + + public boolean invoke() { + return repository.shouldShowStartupScreen(); + } +} diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/domain/quiz/LoadQuizQuestionsUseCase.java b/app/src/main/java/com/d4rk/androidtutorials/java/domain/quiz/LoadQuizQuestionsUseCase.java new file mode 100644 index 00000000..fb92aa01 --- /dev/null +++ b/app/src/main/java/com/d4rk/androidtutorials/java/domain/quiz/LoadQuizQuestionsUseCase.java @@ -0,0 +1,18 @@ +package com.d4rk.androidtutorials.java.domain.quiz; + +import com.d4rk.androidtutorials.java.data.model.QuizQuestion; +import com.d4rk.androidtutorials.java.ui.screens.quiz.repository.QuizRepository; +import java.util.List; + +/** Loads quiz questions from assets. */ +public class LoadQuizQuestionsUseCase { + private final QuizRepository repository; + + public LoadQuizQuestionsUseCase(QuizRepository repository) { + this.repository = repository; + } + + public List invoke() { + return repository.loadQuestions(); + } +} diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/domain/settings/ApplyConsentUseCase.java b/app/src/main/java/com/d4rk/androidtutorials/java/domain/settings/ApplyConsentUseCase.java new file mode 100644 index 00000000..12d23dbc --- /dev/null +++ b/app/src/main/java/com/d4rk/androidtutorials/java/domain/settings/ApplyConsentUseCase.java @@ -0,0 +1,16 @@ +package com.d4rk.androidtutorials.java.domain.settings; + +import com.d4rk.androidtutorials.java.ui.screens.settings.repository.SettingsRepository; + +/** Applies the Firebase consent settings. */ +public class ApplyConsentUseCase { + private final SettingsRepository repository; + + public ApplyConsentUseCase(SettingsRepository repository) { + this.repository = repository; + } + + public void invoke() { + repository.applyConsent(); + } +} diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/domain/settings/GetSharedPreferencesUseCase.java b/app/src/main/java/com/d4rk/androidtutorials/java/domain/settings/GetSharedPreferencesUseCase.java new file mode 100644 index 00000000..385167d5 --- /dev/null +++ b/app/src/main/java/com/d4rk/androidtutorials/java/domain/settings/GetSharedPreferencesUseCase.java @@ -0,0 +1,17 @@ +package com.d4rk.androidtutorials.java.domain.settings; + +import android.content.SharedPreferences; +import com.d4rk.androidtutorials.java.ui.screens.settings.repository.SettingsRepository; + +/** Provides shared preferences used by the settings screen. */ +public class GetSharedPreferencesUseCase { + private final SettingsRepository repository; + + public GetSharedPreferencesUseCase(SettingsRepository repository) { + this.repository = repository; + } + + public SharedPreferences invoke() { + return repository.getSharedPreferences(); + } +} diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/domain/settings/OnPreferenceChangedUseCase.java b/app/src/main/java/com/d4rk/androidtutorials/java/domain/settings/OnPreferenceChangedUseCase.java new file mode 100644 index 00000000..28473c08 --- /dev/null +++ b/app/src/main/java/com/d4rk/androidtutorials/java/domain/settings/OnPreferenceChangedUseCase.java @@ -0,0 +1,17 @@ +package com.d4rk.androidtutorials.java.domain.settings; + +import com.d4rk.androidtutorials.java.ui.screens.settings.repository.SettingsRepository; + +/** Handles a preference change and returns true if theme changed. */ +public class OnPreferenceChangedUseCase { + private final SettingsRepository repository; + + public OnPreferenceChangedUseCase(SettingsRepository repository) { + this.repository = repository; + } + + public boolean invoke(String key) { + repository.handlePreferenceChange(key); + return repository.applyTheme(); + } +} diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/domain/startup/LoadConsentFormUseCase.java b/app/src/main/java/com/d4rk/androidtutorials/java/domain/startup/LoadConsentFormUseCase.java new file mode 100644 index 00000000..67e6376a --- /dev/null +++ b/app/src/main/java/com/d4rk/androidtutorials/java/domain/startup/LoadConsentFormUseCase.java @@ -0,0 +1,17 @@ +package com.d4rk.androidtutorials.java.domain.startup; + +import android.app.Activity; +import com.d4rk.androidtutorials.java.ui.screens.startup.repository.StartupRepository; + +/** Loads and shows the consent form if required. */ +public class LoadConsentFormUseCase { + private final StartupRepository repository; + + public LoadConsentFormUseCase(StartupRepository repository) { + this.repository = repository; + } + + public void invoke(Activity activity, StartupRepository.OnFormError onError) { + repository.loadConsentForm(activity, onError); + } +} diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/domain/startup/RequestConsentInfoUseCase.java b/app/src/main/java/com/d4rk/androidtutorials/java/domain/startup/RequestConsentInfoUseCase.java new file mode 100644 index 00000000..f5e4e06c --- /dev/null +++ b/app/src/main/java/com/d4rk/androidtutorials/java/domain/startup/RequestConsentInfoUseCase.java @@ -0,0 +1,18 @@ +package com.d4rk.androidtutorials.java.domain.startup; + +import android.app.Activity; +import com.d4rk.androidtutorials.java.ui.screens.startup.repository.StartupRepository; +import com.google.android.ump.ConsentRequestParameters; + +/** Requests consent info update via UMP. */ +public class RequestConsentInfoUseCase { + private final StartupRepository repository; + + public RequestConsentInfoUseCase(StartupRepository repository) { + this.repository = repository; + } + + public void invoke(Activity activity, ConsentRequestParameters params, Runnable onSuccess, StartupRepository.OnFormError onError) { + repository.requestConsentInfoUpdate(activity, params, onSuccess, onError); + } +} diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/domain/support/InitBillingClientUseCase.java b/app/src/main/java/com/d4rk/androidtutorials/java/domain/support/InitBillingClientUseCase.java new file mode 100644 index 00000000..5a473bd5 --- /dev/null +++ b/app/src/main/java/com/d4rk/androidtutorials/java/domain/support/InitBillingClientUseCase.java @@ -0,0 +1,16 @@ +package com.d4rk.androidtutorials.java.domain.support; + +import com.d4rk.androidtutorials.java.ui.screens.support.repository.SupportRepository; + +/** Initializes billing client and invokes callback when connected. */ +public class InitBillingClientUseCase { + private final SupportRepository repository; + + public InitBillingClientUseCase(SupportRepository repository) { + this.repository = repository; + } + + public void invoke(Runnable onConnected) { + repository.initBillingClient(onConnected); + } +} diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/domain/support/InitMobileAdsUseCase.java b/app/src/main/java/com/d4rk/androidtutorials/java/domain/support/InitMobileAdsUseCase.java new file mode 100644 index 00000000..dd873a24 --- /dev/null +++ b/app/src/main/java/com/d4rk/androidtutorials/java/domain/support/InitMobileAdsUseCase.java @@ -0,0 +1,17 @@ +package com.d4rk.androidtutorials.java.domain.support; + +import com.d4rk.androidtutorials.java.databinding.ActivitySupportBinding; +import com.d4rk.androidtutorials.java.ui.screens.support.repository.SupportRepository; + +/** Initializes Google Mobile Ads. */ +public class InitMobileAdsUseCase { + private final SupportRepository repository; + + public InitMobileAdsUseCase(SupportRepository repository) { + this.repository = repository; + } + + public void invoke(ActivitySupportBinding binding) { + repository.initMobileAds(binding); + } +} diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/domain/support/InitiatePurchaseUseCase.java b/app/src/main/java/com/d4rk/androidtutorials/java/domain/support/InitiatePurchaseUseCase.java new file mode 100644 index 00000000..1dcdf6aa --- /dev/null +++ b/app/src/main/java/com/d4rk/androidtutorials/java/domain/support/InitiatePurchaseUseCase.java @@ -0,0 +1,17 @@ +package com.d4rk.androidtutorials.java.domain.support; + +import android.app.Activity; +import com.d4rk.androidtutorials.java.ui.screens.support.repository.SupportRepository; + +/** Launches billing flow for a product. */ +public class InitiatePurchaseUseCase { + private final SupportRepository repository; + + public InitiatePurchaseUseCase(SupportRepository repository) { + this.repository = repository; + } + + public void invoke(Activity activity, String productId) { + repository.initiatePurchase(activity, productId); + } +} diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/domain/support/QueryProductDetailsUseCase.java b/app/src/main/java/com/d4rk/androidtutorials/java/domain/support/QueryProductDetailsUseCase.java new file mode 100644 index 00000000..f0df70f8 --- /dev/null +++ b/app/src/main/java/com/d4rk/androidtutorials/java/domain/support/QueryProductDetailsUseCase.java @@ -0,0 +1,18 @@ +package com.d4rk.androidtutorials.java.domain.support; + +import java.util.List; +import com.d4rk.androidtutorials.java.ui.screens.support.repository.SupportRepository; + +/** Queries in-app product details. */ +public class QueryProductDetailsUseCase { + private final SupportRepository repository; + + public QueryProductDetailsUseCase(SupportRepository repository) { + this.repository = repository; + } + + public void invoke(List productIds, + SupportRepository.OnProductDetailsListener listener) { + repository.queryProductDetails(productIds, listener); + } +} diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/about/AboutViewModel.java b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/about/AboutViewModel.java index 0f8cdc67..89c7ce53 100644 --- a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/about/AboutViewModel.java +++ b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/about/AboutViewModel.java @@ -6,6 +6,8 @@ import androidx.lifecycle.AndroidViewModel; import com.d4rk.androidtutorials.java.ui.screens.about.repository.AboutRepository; +import com.d4rk.androidtutorials.java.domain.about.GetVersionStringUseCase; +import com.d4rk.androidtutorials.java.domain.about.GetCurrentYearUseCase; /** @@ -14,23 +16,27 @@ public class AboutViewModel extends AndroidViewModel { private final AboutRepository repository; + private final GetVersionStringUseCase getVersionStringUseCase; + private final GetCurrentYearUseCase getCurrentYearUseCase; public AboutViewModel(@NonNull Application application) { super(application); repository = new AboutRepository(application); + getVersionStringUseCase = new GetVersionStringUseCase(repository); + getCurrentYearUseCase = new GetCurrentYearUseCase(repository); } /** * Returns a formatted version string, e.g. "v1.2.3 (45)". */ public String getVersionString() { - return repository.getVersionString(); + return getVersionStringUseCase.invoke(); } /** * Returns the current year, e.g. "2024". */ public String getCurrentYear() { - return repository.getCurrentYear(); + return getCurrentYearUseCase.invoke(); } } diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/CodeViewModel.java b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/CodeViewModel.java index 1dfc78de..4842974c 100644 --- a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/CodeViewModel.java +++ b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/CodeViewModel.java @@ -5,13 +5,15 @@ import androidx.lifecycle.ViewModel; import com.d4rk.androidtutorials.java.ui.screens.android.repository.LessonRepository; +import com.d4rk.androidtutorials.java.domain.android.GetLessonUseCase; public class CodeViewModel extends ViewModel { private final MutableLiveData lesson = new MutableLiveData<>(); private final LessonRepository repository = new LessonRepository(); + private final GetLessonUseCase getLessonUseCase = new GetLessonUseCase(repository); public void setLessonName(String lessonName) { - lesson.setValue(repository.getLesson(lessonName)); + lesson.setValue(getLessonUseCase.invoke(lessonName)); } public LiveData getLesson() { diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/help/HelpActivity.java b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/help/HelpActivity.java index 533d4be0..6ac4ac32 100644 --- a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/help/HelpActivity.java +++ b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/help/HelpActivity.java @@ -164,7 +164,7 @@ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { if (requireActivity() instanceof HelpActivity helpActivity) { HelpViewModel vm = helpActivity.getHelpViewModel(); - vm.requestReviewFlow(helpActivity, new HelpRepository.OnReviewInfoListener() { + vm.requestReviewFlow(new HelpRepository.OnReviewInfoListener() { @Override public void onSuccess(ReviewInfo info) { vm.launchReviewFlow(helpActivity, info); diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/help/HelpViewModel.java b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/help/HelpViewModel.java index f45488ca..c5b87950 100644 --- a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/help/HelpViewModel.java +++ b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/help/HelpViewModel.java @@ -8,6 +8,8 @@ import androidx.lifecycle.AndroidViewModel; import com.d4rk.androidtutorials.java.ui.screens.help.repository.HelpRepository; +import com.d4rk.androidtutorials.java.domain.help.RequestReviewFlowUseCase; +import com.d4rk.androidtutorials.java.domain.help.LaunchReviewFlowUseCase; import com.google.android.play.core.review.ReviewInfo; /** @@ -16,24 +18,28 @@ */ public class HelpViewModel extends AndroidViewModel { + private final RequestReviewFlowUseCase requestReviewFlowUseCase; + private final LaunchReviewFlowUseCase launchReviewFlowUseCase; + public HelpViewModel(@NonNull Application application) { super(application); + HelpRepository repository = new HelpRepository(application); + requestReviewFlowUseCase = new RequestReviewFlowUseCase(repository); + launchReviewFlowUseCase = new LaunchReviewFlowUseCase(repository); } /** * Requests a review flow. On success, you get a ReviewInfo. * On failure, handle the exception (like fallback to the Play Store). */ - public void requestReviewFlow(Activity activity, HelpRepository.OnReviewInfoListener listener) { - HelpRepository repository = new HelpRepository(activity); - repository.requestReviewFlow(listener); + public void requestReviewFlow(HelpRepository.OnReviewInfoListener listener) { + requestReviewFlowUseCase.invoke(listener); } /** * Launches the in-app review flow with the given ReviewInfo. */ public void launchReviewFlow(Activity activity, ReviewInfo info) { - HelpRepository repository = new HelpRepository(activity); - repository.launchReviewFlow(activity, info); + launchReviewFlowUseCase.invoke(activity, info); } } \ No newline at end of file diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/help/repository/HelpRepository.java b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/help/repository/HelpRepository.java index ec597918..4f2361c7 100644 --- a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/help/repository/HelpRepository.java +++ b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/help/repository/HelpRepository.java @@ -1,6 +1,7 @@ package com.d4rk.androidtutorials.java.ui.screens.help.repository; import android.app.Activity; +import android.content.Context; import androidx.annotation.NonNull; @@ -15,8 +16,8 @@ public class HelpRepository { private final ReviewManager reviewManager; - public HelpRepository(@NonNull Activity activity) { - this.reviewManager = ReviewManagerFactory.create(activity); + public HelpRepository(@NonNull Context context) { + this.reviewManager = ReviewManagerFactory.create(context); } /** diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/home/HomeViewModel.java b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/home/HomeViewModel.java index 14a13487..99fa2f52 100644 --- a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/home/HomeViewModel.java +++ b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/home/HomeViewModel.java @@ -11,6 +11,8 @@ import com.d4rk.androidtutorials.java.R; import com.d4rk.androidtutorials.java.data.model.PromotedApp; import com.d4rk.androidtutorials.java.ui.screens.home.repository.HomeRepository; +import com.d4rk.androidtutorials.java.domain.home.GetDailyTipUseCase; +import com.d4rk.androidtutorials.java.domain.home.GetPromotedAppsUseCase; import java.util.ArrayList; import java.util.List; @@ -19,6 +21,8 @@ public class HomeViewModel extends AndroidViewModel { private final HomeRepository homeRepository; + private final GetDailyTipUseCase getDailyTipUseCase; + private final GetPromotedAppsUseCase getPromotedAppsUseCase; private final MutableLiveData announcementTitle = new MutableLiveData<>(); private final MutableLiveData announcementSubtitle = new MutableLiveData<>(); @@ -28,12 +32,14 @@ public class HomeViewModel extends AndroidViewModel { public HomeViewModel(@NonNull Application application) { super(application); homeRepository = new HomeRepository(application); + getDailyTipUseCase = new GetDailyTipUseCase(homeRepository); + getPromotedAppsUseCase = new GetPromotedAppsUseCase(homeRepository); announcementTitle.setValue(application.getString(R.string.announcement_title)); announcementSubtitle.setValue(application.getString(R.string.announcement_subtitle)); - dailyTip.setValue(homeRepository.getDailyTip()); + dailyTip.setValue(getDailyTipUseCase.invoke()); - homeRepository.fetchPromotedApps(apps -> { + getPromotedAppsUseCase.invoke(apps -> { if (apps.isEmpty()) { promotedApps.postValue(apps); return; diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/main/MainViewModel.java b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/main/MainViewModel.java index 3f1cda99..bb9c5a88 100644 --- a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/main/MainViewModel.java +++ b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/main/MainViewModel.java @@ -11,6 +11,15 @@ import com.d4rk.androidtutorials.java.R; import com.d4rk.androidtutorials.java.ui.screens.main.repository.MainRepository; +import com.d4rk.androidtutorials.java.domain.main.ApplyThemeSettingsUseCase; +import com.d4rk.androidtutorials.java.domain.main.GetBottomNavLabelVisibilityUseCase; +import com.d4rk.androidtutorials.java.domain.main.GetDefaultTabPreferenceUseCase; +import com.d4rk.androidtutorials.java.domain.main.ApplyLanguageSettingsUseCase; +import com.d4rk.androidtutorials.java.domain.main.ShouldShowStartupScreenUseCase; +import com.d4rk.androidtutorials.java.domain.main.MarkStartupScreenShownUseCase; +import com.d4rk.androidtutorials.java.domain.main.IsAppInstalledUseCase; +import com.d4rk.androidtutorials.java.domain.main.BuildShortcutIntentUseCase; +import com.d4rk.androidtutorials.java.domain.main.GetAppUpdateManagerUseCase; import com.google.android.material.navigation.NavigationBarView; import com.google.android.play.core.appupdate.AppUpdateManager; @@ -21,6 +30,15 @@ public class MainViewModel extends AndroidViewModel { private final MainRepository mainRepository; + private final ApplyThemeSettingsUseCase applyThemeSettingsUseCase; + private final GetBottomNavLabelVisibilityUseCase getBottomNavLabelVisibilityUseCase; + private final GetDefaultTabPreferenceUseCase getDefaultTabPreferenceUseCase; + private final ApplyLanguageSettingsUseCase applyLanguageSettingsUseCase; + private final ShouldShowStartupScreenUseCase shouldShowStartupScreenUseCase; + private final MarkStartupScreenShownUseCase markStartupScreenShownUseCase; + private final IsAppInstalledUseCase isAppInstalledUseCase; + private final BuildShortcutIntentUseCase buildShortcutIntentUseCase; + private final GetAppUpdateManagerUseCase getAppUpdateManagerUseCase; private final MutableLiveData bottomNavLabelVisibility = new MutableLiveData<>(); private final MutableLiveData defaultNavDestination = new MutableLiveData<>(); private final MutableLiveData themeChanged = new MutableLiveData<>(); @@ -28,6 +46,15 @@ public class MainViewModel extends AndroidViewModel { public MainViewModel(@NonNull Application application) { super(application); mainRepository = new MainRepository(application); + applyThemeSettingsUseCase = new ApplyThemeSettingsUseCase(mainRepository); + getBottomNavLabelVisibilityUseCase = new GetBottomNavLabelVisibilityUseCase(mainRepository); + getDefaultTabPreferenceUseCase = new GetDefaultTabPreferenceUseCase(mainRepository); + applyLanguageSettingsUseCase = new ApplyLanguageSettingsUseCase(mainRepository); + shouldShowStartupScreenUseCase = new ShouldShowStartupScreenUseCase(mainRepository); + markStartupScreenShownUseCase = new MarkStartupScreenShownUseCase(mainRepository); + isAppInstalledUseCase = new IsAppInstalledUseCase(mainRepository); + buildShortcutIntentUseCase = new BuildShortcutIntentUseCase(mainRepository); + getAppUpdateManagerUseCase = new GetAppUpdateManagerUseCase(mainRepository); } private static int getVisibilityMode(String labelVisibilityStr, String[] bottomNavBarLabelsValues) { @@ -47,7 +74,7 @@ private static int getVisibilityMode(String labelVisibilityStr, String[] bottomN * This can be called from onCreate() or similar lifecycle methods in MainActivity. */ public void applySettings() { - boolean changedTheme = mainRepository.applyThemeSettings( + boolean changedTheme = applyThemeSettingsUseCase.invoke( getApplication().getResources().getStringArray(R.array.preference_theme_values) ); themeChanged.setValue(changedTheme); @@ -57,7 +84,7 @@ public void applySettings() { String[] bottomNavBarLabelsValues = getApplication().getResources().getStringArray(R.array.preference_bottom_navigation_bar_labels_values); - String labelVisibilityStr = mainRepository.getBottomNavLabelVisibility(labelKey, labelDefaultValue); + String labelVisibilityStr = getBottomNavLabelVisibilityUseCase.invoke(labelKey, labelDefaultValue); int visibilityMode = getVisibilityMode(labelVisibilityStr, bottomNavBarLabelsValues); bottomNavLabelVisibility.setValue(visibilityMode); @@ -65,7 +92,7 @@ public void applySettings() { String defaultTabValue = getApplication().getString(R.string.default_value_tab); String[] defaultTabValues = getApplication().getResources().getStringArray(R.array.preference_default_tab_values); - String startFragmentIdValue = mainRepository.getDefaultTabPreference(defaultTabKey, defaultTabValue); + String startFragmentIdValue = getDefaultTabPreferenceUseCase.invoke(defaultTabKey, defaultTabValue); int startFragmentId; if (startFragmentIdValue.equals(defaultTabValues[0])) { startFragmentId = R.id.navigation_home; @@ -77,21 +104,21 @@ public void applySettings() { startFragmentId = R.id.navigation_home; } defaultNavDestination.setValue(startFragmentId); - mainRepository.applyLanguageSettings(); + applyLanguageSettingsUseCase.invoke(); } /** * Checks if we need to show the startup screen. */ public boolean shouldShowStartupScreen() { - return mainRepository.shouldShowStartupScreen(); + return shouldShowStartupScreenUseCase.invoke(); } /** * Mark startup screen as shown. */ public void markStartupScreenShown() { - mainRepository.markStartupScreenShown(); + markStartupScreenShownUseCase.invoke(); } /** @@ -99,14 +126,14 @@ public void markStartupScreenShown() { */ public boolean isAndroidTutorialsInstalled() { PackageManager pm = getApplication().getPackageManager(); - return mainRepository.isAppInstalled(pm, "com.d4rk.androidtutorials.java"); + return isAppInstalledUseCase.invoke(pm, "com.d4rk.androidtutorials.java"); } /** * Build the intent for the shortcut (opens app if installed, or fallback to the Play Store). */ public Intent getShortcutIntent(boolean isInstalled) { - return mainRepository.buildShortcutIntent(isInstalled); + return buildShortcutIntentUseCase.invoke(isInstalled); } /** @@ -134,6 +161,6 @@ public LiveData getThemeChanged() { * Expose the AppUpdateManager if the Activity wants to directly check for in-app updates. */ public AppUpdateManager getAppUpdateManager() { - return mainRepository.getAppUpdateManager(); + return getAppUpdateManagerUseCase.invoke(); } } \ No newline at end of file diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/quiz/QuizViewModel.java b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/quiz/QuizViewModel.java index 84f52f46..c24bebf6 100644 --- a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/quiz/QuizViewModel.java +++ b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/quiz/QuizViewModel.java @@ -9,6 +9,7 @@ import com.d4rk.androidtutorials.java.data.model.QuizQuestion; import com.d4rk.androidtutorials.java.ui.screens.quiz.repository.QuizRepository; +import com.d4rk.androidtutorials.java.domain.quiz.LoadQuizQuestionsUseCase; import java.util.List; @@ -20,11 +21,13 @@ public class QuizViewModel extends AndroidViewModel { private final List questions; private final MutableLiveData currentIndex = new MutableLiveData<>(0); private final MutableLiveData score = new MutableLiveData<>(0); + private final LoadQuizQuestionsUseCase loadQuizQuestionsUseCase; public QuizViewModel(@NonNull Application application) { super(application); QuizRepository repository = new QuizRepository(application); - questions = repository.loadQuestions(); + loadQuizQuestionsUseCase = new LoadQuizQuestionsUseCase(repository); + questions = loadQuizQuestionsUseCase.invoke(); } public QuizQuestion getCurrentQuestion() { diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/settings/SettingsViewModel.java b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/settings/SettingsViewModel.java index 490c319b..e7f1dcbe 100644 --- a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/settings/SettingsViewModel.java +++ b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/settings/SettingsViewModel.java @@ -7,6 +7,9 @@ import androidx.lifecycle.AndroidViewModel; import com.d4rk.androidtutorials.java.ui.screens.settings.repository.SettingsRepository; +import com.d4rk.androidtutorials.java.domain.settings.OnPreferenceChangedUseCase; +import com.d4rk.androidtutorials.java.domain.settings.GetSharedPreferencesUseCase; +import com.d4rk.androidtutorials.java.domain.settings.ApplyConsentUseCase; /** @@ -16,10 +19,16 @@ public class SettingsViewModel extends AndroidViewModel { private final SettingsRepository settingsRepository; + private final OnPreferenceChangedUseCase onPreferenceChangedUseCase; + private final GetSharedPreferencesUseCase getSharedPreferencesUseCase; + private final ApplyConsentUseCase applyConsentUseCase; public SettingsViewModel(@NonNull Application application) { super(application); settingsRepository = new SettingsRepository(application); + onPreferenceChangedUseCase = new OnPreferenceChangedUseCase(settingsRepository); + getSharedPreferencesUseCase = new GetSharedPreferencesUseCase(settingsRepository); + applyConsentUseCase = new ApplyConsentUseCase(settingsRepository); } /** @@ -28,15 +37,14 @@ public SettingsViewModel(@NonNull Application application) { */ public boolean onPreferenceChanged(String key) { if (key == null) return false; - settingsRepository.handlePreferenceChange(key); - return settingsRepository.applyTheme(); + return onPreferenceChangedUseCase.invoke(key); } public SharedPreferences getSharedPreferences() { - return settingsRepository.getSharedPreferences(); + return getSharedPreferencesUseCase.invoke(); } public void applyConsent() { - settingsRepository.applyConsent(); + applyConsentUseCase.invoke(); } } \ No newline at end of file diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/startup/StartupViewModel.java b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/startup/StartupViewModel.java index 8d14f604..4d2a5250 100644 --- a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/startup/StartupViewModel.java +++ b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/startup/StartupViewModel.java @@ -8,6 +8,8 @@ import androidx.lifecycle.AndroidViewModel; import com.d4rk.androidtutorials.java.ui.screens.startup.repository.StartupRepository; +import com.d4rk.androidtutorials.java.domain.startup.RequestConsentInfoUseCase; +import com.d4rk.androidtutorials.java.domain.startup.LoadConsentFormUseCase; import com.google.android.ump.ConsentRequestParameters; /** @@ -16,8 +18,14 @@ */ public class StartupViewModel extends AndroidViewModel { + private final RequestConsentInfoUseCase requestConsentInfoUseCase; + private final LoadConsentFormUseCase loadConsentFormUseCase; + public StartupViewModel(@NonNull Application application) { super(application); + StartupRepository repository = new StartupRepository(application); + requestConsentInfoUseCase = new RequestConsentInfoUseCase(repository); + loadConsentFormUseCase = new LoadConsentFormUseCase(repository); } /** @@ -27,20 +35,13 @@ public void requestConsentInfoUpdate(Activity activity, ConsentRequestParameters params, Runnable onSuccess, StartupRepository.OnFormError onError) { - StartupRepository localRepo = new StartupRepository(activity); - localRepo.requestConsentInfoUpdate( - activity, - params, - onSuccess, - onError - ); + requestConsentInfoUseCase.invoke(activity, params, onSuccess, onError); } /** * Load the consent form (and show it if required). */ public void loadConsentForm(Activity activity, StartupRepository.OnFormError onError) { - StartupRepository localRepo = new StartupRepository(activity); - localRepo.loadConsentForm(activity, onError); + loadConsentFormUseCase.invoke(activity, onError); } } \ No newline at end of file diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/startup/repository/StartupRepository.java b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/startup/repository/StartupRepository.java index c675e88d..6ee4e198 100644 --- a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/startup/repository/StartupRepository.java +++ b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/startup/repository/StartupRepository.java @@ -1,6 +1,7 @@ package com.d4rk.androidtutorials.java.ui.screens.startup.repository; import android.app.Activity; +import android.content.Context; import com.google.android.ump.ConsentForm; import com.google.android.ump.ConsentInformation; @@ -17,8 +18,8 @@ public class StartupRepository { private final ConsentInformation consentInformation; private ConsentForm consentForm; - public StartupRepository(Activity activity) { - consentInformation = UserMessagingPlatform.getConsentInformation(activity); + public StartupRepository(Context context) { + consentInformation = UserMessagingPlatform.getConsentInformation(context); } /** diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/support/SupportViewModel.java b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/support/SupportViewModel.java index d70fa4c2..aacb00a6 100644 --- a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/support/SupportViewModel.java +++ b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/support/SupportViewModel.java @@ -8,32 +8,44 @@ import com.d4rk.androidtutorials.java.databinding.ActivitySupportBinding; import com.d4rk.androidtutorials.java.ui.screens.support.repository.SupportRepository; +import com.d4rk.androidtutorials.java.domain.support.InitBillingClientUseCase; +import com.d4rk.androidtutorials.java.domain.support.QueryProductDetailsUseCase; +import com.d4rk.androidtutorials.java.domain.support.InitiatePurchaseUseCase; +import com.d4rk.androidtutorials.java.domain.support.InitMobileAdsUseCase; import java.util.List; public class SupportViewModel extends AndroidViewModel { private final SupportRepository repository; + private final InitBillingClientUseCase initBillingClientUseCase; + private final QueryProductDetailsUseCase queryProductDetailsUseCase; + private final InitiatePurchaseUseCase initiatePurchaseUseCase; + private final InitMobileAdsUseCase initMobileAdsUseCase; public SupportViewModel(@NonNull Application application) { super(application); repository = new SupportRepository(application); + initBillingClientUseCase = new InitBillingClientUseCase(repository); + queryProductDetailsUseCase = new QueryProductDetailsUseCase(repository); + initiatePurchaseUseCase = new InitiatePurchaseUseCase(repository); + initMobileAdsUseCase = new InitMobileAdsUseCase(repository); } public void initBillingClient(Runnable onConnected) { - repository.initBillingClient(onConnected); + initBillingClientUseCase.invoke(onConnected); } public void queryProductDetails(List productIds, SupportRepository.OnProductDetailsListener listener) { - repository.queryProductDetails(productIds, listener); + queryProductDetailsUseCase.invoke(productIds, listener); } public void initiatePurchase(Activity activity, String productId) { - repository.initiatePurchase(activity, productId); + initiatePurchaseUseCase.invoke(activity, productId); } public void initMobileAds(ActivitySupportBinding binding) { - repository.initMobileAds(binding); + initMobileAdsUseCase.invoke(binding); } } \ No newline at end of file