RestApi

Dáta sem, dáta tam.

Nástroje používateľa

Nástoje správy stránok


kotlin-jetpack-compose

Jetpack Compose

Jetpack Compose je predurčený pre tvorbu UI na platforme Android.
Využitie API Jetpack Compose pre Multiplatform popisuje článok: Compose Multiplatform

Úvod

Jetpack Compose je nástroj z produkcie Google. Používa sa pre tvorbu UI (GUI). Zároveň nahrádza pôvodnu deklaráciu formulárov a komponentov pôvodným XML definičnými súbormi za deklaratívne progromavanie, teda všetko je v jednom súbore a pomôcka je online zobrazovanie pri programovaní pomocou anotácie @Preview.

Postup tvorenia kódu je jednoduchý. Vzhľad používateľského rozhrania zobrazovaného na displeji sa postupne skladá z existujúcich, alebo vlastných komponentov. Vlastné komponenty taktiež prijímajú stavy a vysielajú udalosti pomocou Live dát, ktoré využívajú dátové modely. Coroutines následne umožňujú reťaziť zobrazenia a vstupy v krátkom kóde.

Komplexnosť komponentov ho predurčuje pre tvorbu Multiplatform aplikácií pre Android, iOS, desktop, web (export projektu do Xcode, JVM, JavaScript).

Príklad komponentov nástroja Jetpack Compose: tlačítka, textové polia a iné z Material Design 3. Jetpack Compose vyniká jednoduchosťou a dynamikou písaného kódu, rešpektuje modely dynamických dát, združuje kódy pod jeden jazyk - Kotlin a integruje pokročilé technológie: Room (DB), Hilt (vstrekovanie dát) a iné.

developer.android : Ako začať s Jetpack Compose

Príklad kódu, kde UI je v bloku setContent() :

override fun onCreate(savedInstanceState: Bundle?) {
  super.onCreate(savedInstanceState)
  setContent {
      Text(text = "Hello World!")
  }
}

Základné využitie - komponenty

Základné štrukturovanie kompozície je prvkami:

  • Column, FlowColumn
  • Row, FlowRow
  • Box

Modifikátory umožňujú nastaviť rozmery, zarovnanie, odsadenie, interakcie a iné…

Kompletná škála komponentov je na developer.android

Column() - komponenta

Zobrazí objekty pod sebou. Anotácia @Preview zabezpečí náhľad pre funkciu, ktorá by namala prijímať argumenty (okrem modifier) a odovzdávať hodnoty.

@Preview
@Composable
fun ColumnTest() {
  Column(
    horizontalAlignment = Alignment.CenterHorizontally,
    modifier = Modifier.fillMaxWidth().background(Color.Cyan)
  ) {
    Text(text = "Hello")
    Text(text = "Android")
  }
}

Row() - komponenta

Zobrazí objekty vedľa seba. Jednotka dp určuje veľkosť ktorá je nezávislá na hustote pizelov, sp sa škáluje na základe veľkosti textu zariadenia.

@Preview
@Composable
fun RowTest() {
  Row(
    verticalAlignment = Alignment.CenterVertically,
    modifier = Modifier.fillMaxWidth().height(150.dp).background(Color.Cyan)
  ) {
    Text(text = "Hello")
    Text(text = "Android")
  }
}

Card() - komponenta

Container pre ďalšie komponenty (Row(), …)

Card(modifier = modifier, colors = ...) {
  Row(...) {
    Icon(...)
    Column(...) {
      ..
    }
  }
}

Iné komponenty

Link na developers je hore pod nadpisom… ↑

  • Icon() - obrázok
  • Box() {} - kontajner pre iné komponenty
  • Button() {} - tlačítko s kontajnerom
  • TextButton() {} - tlačítko s kontajnerom
  • LazyColumn() {} - kontajner pre viditeľný zoznam položiek
    • item {} - definicia položiek pre LazyColumn()
  • OutlinedTextField() - orámovanie s menovkou
  • OutlinedButton(onclick = {…}, …) {} - tlačítko s container pre TEXT() a iné
  • Checkbox() - zaškrtnutie voľby
  • Scaffold() - kontajner

Material Design

Jedná sa o designový jazyk. Tu je použitý Material Design 3 (M3). V základe pre aplikáciu používame primárnu a sekundárn farbu - primárna farba je výraznejšia a použije sa pre hlavný prvok. Popis napríklad tlačítok používa aj on farby (v Theme.kt). Typologické pravidlá predpokladajú čo najmenšiu škálu použitých fontov. Pre výber vhodných fontov je možné využiť Google Fonts. Pre zaoblené hrany komponentov sa využije Modifier.
Definície sú v: …/ui/theme/[Theme.kt, Color.kt, Type.kt]
Aplikovanie témy na kód:

@Preview
@Composable
fun ColoredButton() {
  MyApkMaterialTheme {
    Button(
      onClick = { /*TODO*/ },
      modifier = Modifier.clip(CutCornerShape(16.dp)),
      colors = ButtonDefaults.buttonColors(backgroundColor = MaterialTheme.colors.primary)
    ) {
        Text(
          text = "Tlačítko",
          color = MaterialTheme.colors.onPrimary,
          modifier = Modifier.background(MaterialTheme.colors.primary)
        )
    }
  }
}

Stav aplikácie

Je akákoľvek hodnota, ktorá sa mení v čase, napríklad texty v textových komponentoch, dáta či anymácie. Stav v Compose sa ukladá príkazom remember, napríklad (takmer identické vyjadrenia):

val mutableState = remember { mutableStateOf(value) }  // i preferred
var value by remember { mutableStateOf(value) }
val (value, setValue) = remember { mutableStateOf(value) }

State hoisting

┌──────────────────────────────────┐
│       Komponenta so stavom       │
└──────────────────────────────────┘
    ⬇                    ⬆
   Stav               Udalosti
    ⬇                    ⬆
┌──────────────────────────────────┐
│ Komponenta vytvárajúca rozhranie │
└──────────────────────────────────┘

Získanie stavu

val status = mutableState.value,

príklad získania stavu v textovej komponente:

OutlinedTextField(
    value = mutableState.value,
    label = { Text("your number") },
    keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
    onValueChange = { newInput -> mutableState.value = newInput }
)

príklad onClick v tlačidle:

fun OperationButton(modifier: Modifier = Modifier, text: String, onClick: () -> Unit = {}) {
    Button(
        onClick = { onClick() },
        colors = ButtonDefaults.buttonColors(MaterialTheme.colors.secondary),
        modifier = modifier
    )   ...
}

MVVM architektúra

Model-View-ViewModel je koncept pre udržateľné a škálovateľné (rôzne zdroje dát) aplikácie. Model oddeľuje používateľské rozhranie (GUI), dáta a iné komponenty. MVVM sa špecializuje na Android (inde je to MVC a podobne). Vrstvy MVVM architektúry:

  • Model - pre prácu s dátami (DB, YAML, …)
  • View - používateľské rozhranie (GUI), napríklad Compose
  • ViewModel - kontrolér, čiže prepojovacia vrstva medzi Model-View
┌──────┐   ┌───────────┐   ┌───────┐
│ View │◄-►│ ViewModel │◄-►│ Model │
└──────┘   └───────────┘   └───────┘
 Compose                     Room

Plugin kapt pre SQL anotáci

Umožňuje používať anotácie pre metódy a vlastnosti SQL databáz.

Modul kapt je už nepraktický, namiesto neho sa používa ksp. Knižnica Room, ktorá funguje s oboma modelmi. Pri potrebe použiť ksp odporúčam dohľadať príklady pre zápisy do: build.gradle.kts (prj) a build.gradle.kts (:app).
Link na migráciu z kapt na ksp: https://developer.android.com/build/migrate-to-ksp

Plugin ksp pre SQL anotácie

Umožňuje používať anotácie pre metódy a vlastnosti SQL databáz.

Inštalácia

aj napriek dostupným návodom s popisom manuálneho doplnenia buid súborov som testol možnosti správy modulov v projekte (AS) a funguje to spoľahlivo, nakoľko ponúka aktuálne knižnice, Teda zhruba tieto moduly treba nájsť a aplikovať:

  • menu settings → Project structure → Dependencies → app → + : pridať com.google.devtools.ksp.gradle.plugin:1.5.30-1.0.0, potom ho v libs.versions.toml uktualizovať na → "2.2.0-2.0.2" → SyncNow
  • ďalej pridať: androidx.room.gradle.plugin:2.8.0-alpha01
  • taktiež sa v odporúča pridať: androidx.room.compiler

ďalej upraviť:

build.gradle.kts (prj)

verzia musí byť zhodná s verziou Kotlin (v libs.version.toml)

plugins {
  ...
  id("com.google.devtools.ksp") version "2.2.0-2.0.2" apply false
}

build.gradle.kts (:app)

plugins {
  ...
  id("com.google.devtools.ksp")
}
 
compileOptions {  // 17 is minimum
    sourceCompatibility = JavaVersion.VERSION_17
    targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
    jvmTarget = "17"
}
 
dependencies {
  ...
  ksp(libs.androidx.room.compiler.v272)
}

následne až v kóde budú použité metódy Room, tak potvrdiť import: @Entity ⇒ import room.common ⇒ build.gradle.kts(:app)
zárovaň sa upravuje automaticky aj blok dependencies {…} v build.gradle.kts(:app) a aj libs.versions.toml (kde občas treba potvriť vyššie verzie knižníc)

Knižnica Room

Je určená pre prácu s SQLite Android. Prevádza riadky na objekty a naopak. Základné komponenty knižnice:

  • Entity - riadok je objekt, stĺpec je atribút (vlastnosť, t.j hodnota)
  • DAO - (Data Access Object) operácie nad DB (INSERT, SELECT, UPDATE, DELETE, …)
  • Database Class - objekt pre spojenie s DB. Obsahuje metódy pre získanie DAO a nastavenie parametrov

Príklad použitia knižnice Room:

import androidx.room.Entity
import androidx.room.PrimaryKey
 
/** 1. define data object and make entity : data/MyData.kt */
@Entity
data class MyData(
    @PrimaryKey(autoGenerate = true) val recordId: Long? = null, // primary key
    val name: String
)
// ... any functions for operations with entity
 
/** 2. interface : data/MyDataDao.kt */
@Dao
interface MyDataDao {
    @Query("SELECT * FROM MyData")
    fun getAll(): Flow<List<MyData>>  // Flow: see coroutines
 
    @Insert
    fun insert(myData: MyData)
 
    @Update
    fun update(myData: MyData)
 
    @Delete
    fun delete(myData: MyData)
}
 
/** 3. class of database : data/AppDatabase.kt */
@Database(entities = [MyData::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
    abstract fun myDataDao(): MyDataDao
}
 
/** 4. instance for all project : service/ServiceLocator.kt */
object ServiceLocator {
    private var _myDataDao: MyDataDao? = null
 
    val myDataDao: MyDataDao?
        get() = _myDataDao
 
    fun setMyDataDao(myDataDao: MyDataDao) {
        _myDataDao = myDataDao
    }
}
 
/**
    5. application class : application/ExampleApplication.kt
       - need edit AndroidManifest.xml ->
         <application ... android:name=".application.ExampleApplication" ... </application>
*/
class ExampleApplication : Application() {
    override fun onCreate() {
        super.onCreate()
 
        val db = Room.databaseBuilder(
            applicationContext,
            AppDatabase::class.java,
            "myData-database"
        ).build()
 
        ServiceLocator.setMyDataDao(db.myDataDao())
    }
}

Následne treba vytvoriť ViewModel, ktorý prepojí prezentačnú vrstvu s dátovou vrstvou (modelom), čím bude idea MVVM naplnená. Mal by obsahovať metódy nad dátami (získanie, vloženie, úpravu a mazanie) pomocou metód z rozhrania DAO.
Metódy nad dátami je vhodné realizovať v bloku init {…} pomocou coroutines: viewModelScope.launch {…} a uložiť do kolekcie(í).

Farby aplikácie

Postupy pre zmeny odporúča Material Design 3. Základný princíp je použitie Primárnych a Sekundárnych farieb, ako pre svetlý, tak i pre tmavý režim zobrazenia.

Deklarácia farieb

Samotná deklarácia faireb je v ui/theme/Color.kt.
Generovanie farieb môže zabezpečiť aj Figma - Material Theme Builder, alebo Material Theme Builder na GitHub.

Deklarácia farebných schém

Samotná deklarácia tém je v ui/theme/Theme.kt.

Pridanie vlastných fontov

Ďalšie fonty je možné získať na adrese Google
Pre ich použitie je treba stiahnuť zip a vytvoriť v AS: app → new Android Resource Directory : font/font a doňho nakopírovať vybrané zo stiahnutého zip-u.
Samotná deklarácia tém je v ui/theme/Type.kt.


Linky

kotlin-jetpack-compose.txt · Posledná úprava: od attilajancik