Андроид-приложение, 55-я неделя

Использование класса «Нав хост» (NavHost)

Я вначале думал, что мне нужно использовать класс «Нав граф» (NavGraph), — оказалось, «Студия» давала подсказку не на тот вариант функции, из-за того что я не указал лямбду; указать её я должен был последним аргументом вызова.

Какие принципы отстаивает фреймворк «Джетпак Компоус»

В относительно старых видеороликах я нашёл наглядные объяснения основных принципов фреймворка:

Вот ссылки на те ролики:

Составление предложения «на лету». Кеш предложения

Главный экран моего приложения — это экран ленты. В ленте, в числе прочего, будет список относительно длинных предложений, каждое из которых можно упростить, убрав часть слов.

Я не храню по нескольку вариантов одного и того же предложения: разные варианты будут создаваться, что называется, «на лету». Хранение полной версии предложения у меня сейчас выглядит так (образец):

Statement("2024-04-10-e1", listOf(
    Lexeme(3, LexemeType.F, ""),
    Lexeme(3, LexemeType.F, "князь"),
    Lexeme(3, LexemeType.L, "Болконский"),
    Lexeme(3, LexemeType.L, "был"),
    Lexeme(2, LexemeType.F, ","),
    Lexeme(2, LexemeType.L, "небольшого"),
    Lexeme(2, LexemeType.L, "роста"),
    Lexeme(2, LexemeType.F, ","),
    Lexeme(3, LexemeType.L, "весьма"),
    Lexeme(3, LexemeType.L, "красивый"),
    Lexeme(3, LexemeType.L, "молодой"),
    Lexeme(3, LexemeType.L, "человек"),
    Lexeme(1, LexemeType.F, ","),
    Lexeme(1, LexemeType.PL, "с"),
    Lexeme(1, LexemeType.PR, "определёнными"),
    Lexeme(1, LexemeType.PL, "и"),
    Lexeme(1, LexemeType.PR, "сухими"),
    Lexeme(1, LexemeType.L, "чертами"),
    Lexeme(3, LexemeType.F, "."),
    Lexeme(3, LexemeType.F, ""),
))

Первый параметр конструктора класса «Лексема» — это «важность», «ранг» (rank) лексемы. Обратите внимание: первый и последний элемент всегда хранят максимально возможное значение этой величины (максимально возможное в рамках данного предложения).

А вот как я создаю строку для отображения, в зависимости от «степени сжатия» (знаки «больше» и «меньше» заменены похожими по внешнему виду фигурными скобками, потому что редактор ХТМЛ-кода, которым я пользуюсь, «ругается» на них):

internal fun refine(statement: Statement, compressionLevel: Int) : String {
    val baseRank = statement.text[0].rank
    val minRank = (
        if (compressionLevel {= 0 || compressionLevel }= baseRank)
            baseRank
        else
            compressionLevel
    )
    val rawText = statement.text.fold("") { sum, lx ->
        sum + (
            if (lx.rank { minRank)
                ""
            else
                (
                    if (lx.type == LexemeType.F)
                        lx.text
                    else
                        (
                            if (lx.type == LexemeType.PR)
                                "\u00A0" + lx.text // non-break space
                            else
                                " " + lx.text // regular space
                        )
                )
        )
    }
    return rawText.substring(0, 1).uppercase() + rawText.substring(1)
}

Я предполагаю, что созданная однажды строка будет кешироваться, благодаря использованию функции «реме́мбер» (remember), так что моя функция «рефа́йн» (refine) не должна вызываться при повторном отображении примера во время прокрутки ленты:

package com.example.myapp.ui
...
import androidx.compose.foundation.layout.Column
import androidx.compose.material3.Card
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
...
@Composable
internal fun StatementCard(
    statement: Statement,
    ...
    compressionLevel: Int = 1,
) {
    Card(...) {
        Column {
            val refinedText = remember(statement, compressionLevel) {
                refine(statement = statement, compressionLevel = compressionLevel)
            }
            Text(
                text = refinedText,
                ...
            )
        }
    }
}

Заметьте: функция «рефайн» была определена как обычная функция, а не как компоусэбэл!

Мои догадки про функции — не-компоусэблы; как и раньше, эти пункты ещё надо будет проверить и уточнить:

  • Возвращаемый такими функциями результат может быть кеширован.
  • Если результат вызова таких функций может быть кеширован, то эти функции не будут вызваны при рекомпозиции.
  • Таким функциям не передаётся параметр «Модификатор».

«Пустая строка»

Нужно будет решить, где лучше хранить текст примеров: в прото-датасторе или в руме. Ну а пока я разрабатываю подходящий подо всё формат данных.

Так называемая «пустая строка» — чем бы она ни была на самом деле — нужна мне для обозначения границ предложения. Границы предложения должны иметь максимальный ранг; это значение используется алгоритмом (смотри выше).

Внешний отступ и внутренний отступ

Можно перевести и так: марджин — внешний отступ, паддинг — внутренний.

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

Актуализация постов

Многие посты этого сайта доступны для нахождения через поисковые системы; однако часть материала, который я публиковал ранее, устарела. Например, компоусэбэл «Леса́» перестал быть «экспериментальной особенностью», так что описание того, как им пользоваться, должно быть переделано. Я собираюсь исправлять подобные места по мере сил и возможностей...