Run this build using a Java 11 or newer JVM

 
FAILURE: Build failed with an exception.

* What went wrong:
A problem occurred configuring root project 'PillIdentifier'.
> Could not resolve all artifacts for configuration ':classpath'.
   > Could not resolve com.android.tools.build:gradle:8.8.2.
     Required by:
         root project : > com.android.application:com.android.application.gradle.plugin:8.8.2
         root project : > com.android.library:com.android.library.gradle.plugin:8.8.2
      > Dependency requires at least JVM runtime version 11. This build uses a Java 8 JVM.
   > Could not resolve com.google.gms:google-services:4.4.2.
     Required by:
         root project : > com.google.gms.google-services:com.google.gms.google-services.gradle.plugin:4.4.2
      > Dependency requires at least JVM runtime version 11. This build uses a Java 8 JVM.
   > Could not resolve com.google.firebase:firebase-crashlytics-gradle:3.0.3.
     Required by:
         root project : > com.google.firebase.crashlytics:com.google.firebase.crashlytics.gradle.plugin:3.0.3
      > Dependency requires at least JVM runtime version 17. This build uses a Java 8 JVM.

* Try:
> Run this build using a Java 11 or newer JVM.
> Run this build using a Java 17 or newer JVM.
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.

Ошибка возникает из-за того, что ваша сборка использует Java 8, а для работы с Gradle 8.8.2, Google Services 4.4.2 и Firebase Crashlytics 3.0.3 требуется Java 11+ (а для Crashlytics — даже Java 17)
>gradlew --version        

------------------------------------------------------------
Gradle 8.10.2
------------------------------------------------------------

Build time:    2024-09-23 21:28:39 UTC
Revision:      415adb9e06a516c44b391edff552fd42139443f7

Kotlin:        1.9.24
Groovy:        3.0.22
Ant:           Apache Ant(TM) version 1.10.14 compiled on August 16 2023
Launcher JVM:  1.8.0_431 (Oracle Corporation 25.431-b10)
Daemon JVM:    C:\Program Files\Java\jdk-1.8 (no JDK specified, using current Java home) @@@@@@@@@@@@@ JAVA_HOME path
OS:            Windows 10 10.0 amd64



taskkill /F /IM java.exe

 

 

Modify  JAVA_HOME path
Or set gradle.properties

org.gradle.java.home=C:\\Program Files\\Java\\jdk-17.0.11

Моделирование состояния ViewModel в Android: Руководство по чистым и масштабируемым паттернам

 


Плохо спроектированные модели создают каскад проблем для каждого компонента, который от них зависит. В случае моделей представления, если они не соответствуют реальным потребностям экрана, другие компоненты (например, ViewModel) вынуждены обходить эти ограничения, что приводит к раздутым, трудным в сопровождении классам, заполненным хаками и обходными путями. Это несоответствие вносит неясность и путаницу, делая код неочевидным и подверженным ошибкам, что увеличивает затраты на его поддержку.

Рассмотрим два популярных способа моделирования состояния ViewModel:

//🎯 Подход 1
data class ScreenState(
    val isLoading: Boolean,
    val isError: Boolean,
    val data: Data?
)

//🎯 Подход 2
sealed interface ScreenState {
    data object Loading : ScreenState
    data object Error : ScreenState
    data class Content(val data: Data) : ScreenState
}

Оба подхода имеют значительные ограничения и часто требуют множества обходных решений. Давайте разберём их плюсы и минусы, а затем рассмотрим третий, более простой и универсальный вариант.

Подход 1: Простые дата-классы

data class ProductListScreenState(
    val isLoading: Boolean,
    val isError: Boolean,
    val productResults: ProductResults?
)

data class ProductResults(
    val products: List<Product>, 
    val canLoadMore: Boolean
)

Представьте страницу со списком товаров, где данные загружаются из удалённого источника. Во время загрузки отображается спиннер, в случае ошибки показывается экран ошибки с возможностью повторной попытки. Это стандартный сценарий «Загрузка-Контент-Ошибка».

Минусы этого подхода:

  • Модель допускает противоречивые состояния: например, isLoading и isError могут быть true одновременно, что приведёт к отображению двух экранов сразу.
  • Если добавить дополнительные состояния (например, isRefreshing или isPaginating), можно получить 2⁴ возможных комбинаций булевых значений, тогда как реально экран поддерживает только 5 состояний.
  • Каждый раз, когда мы обновляем состояние, приходится сбрасывать все остальные флаги, создавая лишний код.
  • Разработчики, работающие с UI, могут запутаться, какие состояния действительно возможны, и будут вынуждены заглядывать в код ViewModel для уточнения.

Улучшение через enum

data class ProductListScreenState(
    val displayState: DisplayState,
    val productResults: ProductResults?
)

enum class DisplayState {
    LOADING, CONTENT, ERROR
}

Этот подход значительно улучшает ситуацию, но всё ещё имеет недостатки. Например, CONTENT подразумевает, что productResults не должен быть null, но это никак не контролируется.

Подход 2: sealed interface

sealed interface ProductListScreenState {
    data object Loading : ProductListScreenState
    data object Error : ProductListScreenState
    data class Content(val productResults: ProductResults) : ProductListScreenState
}

Этот вариант решает проблему противоречивых состояний, так как каждое состояние явно представлено. Однако он затрудняет совместное использование данных между состояниями.

Проблема: если нам нужно отображать приветственное сообщение с именем пользователя, нам придётся хранить это значение отдельно и вручную синхронизировать его со всеми состояниями.

sealed interface ProductListScreenState {
    val fullName: String
    data class Loading(override val fullName: String) : ProductListScreenState
    data class Error(override val fullName: String) : ProductListScreenState
    data class Content(override val fullName: String, val productResults: ProductResults) : ProductListScreenState
}

Такой код становится громоздким и сложным в обслуживании.

Финальный подход: Объединение data class и sealed interface

Используем дата-класс для данных, присутствующих во всех состояниях, и sealed interface для состояний, которые взаимоисключаемы.

data class ProductListScreenState(
    val fullName: String,
    val displayState: DisplayState
)

sealed interface DisplayState {
    data object Loading : DisplayState
    data object Error : DisplayState
    data class Content(val productResults: ProductResults) : DisplayState
}

Масштабируемость модели

Допустим, нам нужно добавить поддержку:

  • Перезагрузки данных при повороте экрана.
  • Pull-to-refresh с индикатором загрузки вверху.
  • Пагинации с индикатором загрузки внизу.

Обновленная модель состояния:

data class ProductListScreenState(
    val fullName: String,
    val displayState: DisplayState? = null
)

sealed interface DisplayState {
    data object Loading : DisplayState
    data object Error : DisplayState
    data class Content(
        val productResults: ProductResults,
        val contentDisplayState: ContentDisplayState? = null
    ) : DisplayState
}

sealed interface ContentDisplayState {
    data object Refreshing : ContentDisplayState
    data object Paginating : ContentDisplayState
    data object PaginationError : ContentDisplayState
}

Теперь состояния чётко структурированы и масштабируемы, а код ViewModel остаётся простым и лаконичным.

Вывод:

Этот гибридный подход объединяет лучшие качества data class и sealed interface, обеспечивая чистоту, масштабируемость и удобочитаемость кода. 🎯

B-USB

Volume: F:
Controller: Silicon Motion SM3257 ENAA   {CHIPSET 3257ENAA}
Possible Memory Chip(s):
  Samsung K9ACGD8U0Ax2 *2
Memory Type: TLC
Flash ID: ECDE98CE 74C4
Flash CE: 4
Flash Channels: Single
Chip F/W: ISP 140704-AA-
MP: N0708V1
MPTOOL Ver.: 2.05.36
VID: 090C
PID: 1000

Manufacturer: SMI Corporation
Product: USB DISK
Query Vendor ID: SMI     
Query Product ID: USB DISK        
Query Product Revision: 1100
Physical Disk Capacity: 32463912960 Bytes
Windows Disk Capacity:  32462860288 Bytes
Internal Tags: QT2R-TZ2L
File System: NTFS
Relative Offset: 1024 KB
USB Version: 2.00
Declared Power: 300 mA
ContMeas ID: 1DA7-04-FF
Microsoft Windows 10 x64 Build 19045
------------------------------------
http://www.antspec.com/usbflashinfo/
Program Version: 9.4.0.645

psw: 320