Инструкция для Android

Конфигурация библиотеки и отрисовка первой DivView

Настройка зависимостей

Добавьте следующие зависимости в build.gradle.kts приложения (Kotlin DSL). Вместо <divkit-version> укажите нужную версию DivKit, а вместо <okhttp-version> — версию OkHttp, которую использует ваше приложение. Версии DivKit доступны на странице релизов.

val divkitVersion = "<divkit-version>"
val okhttpVersion = "<okhttp-version>"

dependencies {
    implementation("com.yandex.div:div:$divkitVersion")
    implementation("com.yandex.div:div-core:$divkitVersion")
    implementation("com.yandex.div:div-json:$divkitVersion")
    implementation("com.yandex.div:div-network-okhttp:$divkitVersion")
    implementation("com.yandex.div:coil:$divkitVersion")
    implementation("com.squareup.okhttp3:okhttp:$okhttpVersion")
}

В примерах ниже используется Coil. Если вы выбрали Glide, замените зависимость com.yandex.div:coil на com.yandex.div:glide с той же версией DivKit.

Для доступа к сети добавьте следующее разрешение внутрь <manifest> в файле AndroidManifest.xml приложения:

<uses-permission android:name="android.permission.INTERNET" />

Настройка сетевого стека

DivKit принимает общий DivNetworkClient для действий отправки данных (submit actions), встроенного резервного загрузчика SVG и загрузки патчей по умолчанию. Это позволяет использовать HTTP-настройки, интерцепторы и куки приложения для этих запросов.

Примечание

Настройте DivKit один раз при инициализации приложения, до первого вызова DivKit.getInstance() или создания Div2Context. Создание Div2Context также инициализирует общий экземпляр DivKit.

Используйте существующий OkHttpClient приложения или создайте его, как показано ниже. Обеспечьте доступ к hostOkHttpClient из кода, который создает загрузчик изображений.

import com.yandex.div.core.DivKit
import com.yandex.div.core.DivKitConfiguration
import com.yandex.div.network.OkHttpDivNetworkClient
import okhttp3.OkHttpClient

val hostOkHttpClient = OkHttpClient.Builder().build()
val networkClient = OkHttpDivNetworkClient(hostOkHttpClient)

DivKit.configure(
    DivKitConfiguration.Builder()
        .networkClient(networkClient)
        .build()
)

Явно настроенные DivDownloader и DivRequestExecutor имеют приоритет при выполнении своих запросов. Для интеграций Lottie, Media3 и Beacon сетевой клиент нужно явно передать в конструкторы. Настройка DivKitConfiguration не подключает эти интеграции автоматически.

Основной загрузчик изображений использует собственный сетевой стек. Передайте hostOkHttpClient в CoilDivImageLoader, как показано ниже, или настройте сетевой стек Glide в приложении. SVG-изображения, которые обрабатывает основной загрузчик, также загружаются через его сетевой стек.

Создание DivConfiguration

Создайте DivConfiguration с тем же hostOkHttpClient, который вы передали в OkHttpDivNetworkClient. Здесь context — это Android Context.

import com.yandex.div.coil.CoilDivImageLoader
import com.yandex.div.core.DivConfiguration

val imageLoader = CoilDivImageLoader(context, hostOkHttpClient)
val configuration = DivConfiguration.Builder(imageLoader).build()

Для DivConfiguration.Builder требуется DivImageLoader. Вы можете реализовать свой загрузчик или использовать CoilDivImageLoader либо GlideDivImageLoader.

Оба готовых загрузчика поддерживают SVG. Если пользовательский загрузчик сообщает, что не поддерживает SVG, DivKit использует встроенный резервный загрузчик для URL, путь которых заканчивается на .svg.

Создание DivData

JSON-документ содержит объект card и необязательный объект templates. Если шаблоны присутствуют, их нужно разобрать перед карточкой. Следующая функция также принимает карточки без шаблонов:

import com.yandex.div.data.DivParsingEnvironment
import com.yandex.div.json.ParsingErrorLogger
import com.yandex.div2.DivData
import org.json.JSONObject

fun JSONObject.asDiv2DataWithTemplates(): DivData {
    val environment = DivParsingEnvironment(ParsingErrorLogger.LOG)
    optJSONObject("templates")?.let { environment.parseTemplates(it) }
    return DivData(environment, getJSONObject("card"))
}

Обработка карточки и вывод на экран

Выведем на экран небольшой текст:

val card = """
{
    "card": {
        "log_id": "text",
        "states": [
            {
                "state_id": 0,
                "div": {
                    "type": "text",
                    "text": "Hello, DivKit!"
                }
            }
        ]
    }
}
""".trimIndent()

Создайте View в главном потоке, например в методе onCreate класса AppCompatActivity. В этом примере this ссылается на Activity, которая предоставляет контекст с темой и выступает владельцем жизненного цикла. yourViewGroup — существующий контейнер в верстке Activity, а configuration — созданная выше конфигурация.

import com.yandex.div.DivDataTag
import com.yandex.div.core.Div2Context
import com.yandex.div.core.view2.Div2View
import org.json.JSONObject

val divData = JSONObject(card).asDiv2DataWithTemplates()
val divContext = Div2Context(
    baseContext = this,
    configuration = configuration,
    lifecycleOwner = this
)
val div2View = Div2View(divContext)
div2View.setData(divData, DivDataTag("your_unique_tag_here"))
yourViewGroup.addView(div2View)

Если все сделано без ошибок, на экране появится надпись «Hello, DivKit!».

Посмотреть интерактивный пример

Обработка действий пользователя

Чтобы сделать интерфейс интерактивным, добавьте обработку действий. Для примера превратим текст в интерактивную кнопку, при нажатии которой появится Android Toast.

Модификация JSON

В DivKit сознательно нет таких высокоуровневых сущностей, как «карточка товара» или «кнопка». Кнопкой может быть любой элемент. Изменим внешний вид надписи «Hello, DivKit!» и добавим действие при нажатии:

Посмотреть интерактивный пример

В примере мы изменили внешний вид элемента: добавили скругление углов и отступы, поменяли цвет фона и текста, добавили анимацию при нажатии и поменяли расположение текста внутри View. И главное — добавили действие при нажатии:

    "actions": [
        {
            "log_id": "button_pressed",
            "url": "notification://show-toast?text=Hello%2C%20DivKit%21"
        }
    ]

Поддержка новых действий на уровне кода в Android

Чтобы обрабатывать новые типы действий, создайте свою реализацию DivActionHandler и добавьте ее в DivConfiguration.
Начнем с реализации DivActionHandler:

import android.widget.Toast
import com.yandex.div.core.DivActionHandler
import com.yandex.div.core.DivViewFacade
import com.yandex.div.json.expressions.ExpressionResolver
import com.yandex.div2.DivAction

class NotificationDivActionHandler : DivActionHandler() {
    override fun handleAction(
        action: DivAction,
        view: DivViewFacade,
        resolver: ExpressionResolver
    ): Boolean {
        if (super.handleAction(action, view, resolver)) {
            return true
        }

        val uri = action.url?.evaluate(resolver) ?: return false
        if (uri.authority != "show-toast" || uri.scheme != "notification") return false
        val text = uri.getQueryParameter("text") ?: return false

        Toast.makeText(view.view.context, text, Toast.LENGTH_LONG).show()
        return true
    }
}

Вызовите super.handleAction(action, view, resolver), чтобы действия по умолчанию продолжали работать. Если действие еще не обработано, проверяем пользовательскую схему URL и показываем Toast. Используйте переданный resolver, чтобы вычислять URL действия в его текущей области видимости.

Добавьте NotificationDivActionHandler() при создании конфигурации, до создания Div2Context и Div2View. Замените предыдущий пример конфигурации следующим:

    val configuration = DivConfiguration.Builder(imageLoader)
        .actionHandler(NotificationDivActionHandler())
        .build()

Так можно повлиять из JSON-верстки не только на состояние самой карточки, но и на все приложение.

Пример проекта

Готовый к запуску пример доступен на GitHub: минималистичное приложение с базовой интеграцией DivKit, кастомными шрифтами, обработчиком действий и расширениями (Rive, Markdown, pinch-to-zoom).

Узнать больше

Вы можете обсуждать интересующие вас темы в сообществе пользователей DivKit в Telegram: https://t.me/divkit_community_ru.

Репозиторий DivKit

Предыдущая
Следующая