Avatar ·

Как использовать @Parcelize после удаления kotlin-android-extensions?

Привет, коллеги! Я уже несколько лет пишу на Kotlin для Android и привык использовать `@Parcelize` из плагина `kotlin-android-extensions`. Этот плагин сильно упрощал жизнь — достаточно было добавить аннотацию, и класс автоматически реализовывал интерфейс `Parcelable`. Недавно я обновил проект до последней версии Kotlin (1.9.0) и Gradle, и заметил, что `kotlin-android-extensions` помечен как устаревший и будет полностью удален. В официальной документации советуют переходить на `kotlin-parcelize`, но я не совсем понимаю, как это сделать правильно. Проблема в том, что мой старый код выглядит так: ```kotlin // Старый способ (работал с kotlin-android-extensions) @Parcelize data class User( val id: Int, val name: String, val email: String? ) : Parcelable ``` После удаления плагина компилятор не видит `@Parcelize`. Я попробовал просто добавить другой плагин, но сборка падает с ошибками. Документация говорит, что нужно использовать `kotlin-parcelize`, но я не нашел четкой инструкции по миграции. Подскажите, пожалуйста, как правильно настроить проект и использовать `@Parcelize` в новых версиях Kotlin? Нужно ли менять что-то в Gradle-файлах и в самом коде? Заранее спасибо за помощь! <<>>

Пошаговая инструкция по миграции с kotlin-android-extensions на kotlin-parcelize

Вы правы — плагин kotlin-android-extensions окончательно удалён из Kotlin 1.9.0. Но разработчики предусмотрели отдельный плагин kotlin-parcelize, который сохраняет все возможности @Parcelize без лишнего функционала. Вот как правильно выполнить миграцию.

Шаг 1. Обновите Gradle-файлы

В вашем build.gradle.kts (или build.gradle) уровня проекта замените старый плагин на новый:

// build.gradle.kts (уровень проекта)
plugins {
    id("org.jetbrains.kotlin.android") version "1.9.0" apply false
    // Удалите эту строку:
    // id("org.jetbrains.kotlin.android.extensions") version "1.9.0" apply false
    // Добавьте эту:
    id("org.jetbrains.kotlin.plugin.parcelize") version "1.9.0" apply false
}

В файле модуля (app/build.gradle.kts):

// app/build.gradle.kts
plugins {
    id("com.android.application")
    id("org.jetbrains.kotlin.android")
    // Удалите:
    // id("kotlin-android-extensions")
    // Добавьте:
    id("org.jetbrains.kotlin.plugin.parcelize")
}

android {
    // ... остальные настройки
}

Шаг 2. Удалите старые конфигурации

Из build.gradle модуля нужно убрать блок androidExtensions, если он был:

// Удалите это полностью:
androidExtensions {
    experimental = true
}

Шаг 3. Обновите импорты в коде

Теперь @Parcelize находится в другом пакете. Замените импорт:

// БЫЛО (старый плагин):
import kotlinx.android.parcel.Parcelize

// СТАЛО (новый плагин):
import org.jetbrains.parcelize.Parcelize

Шаг 4. Проверьте работу кода

После этих изменений ваш класс будет работать как раньше:

import org.jetbrains.parcelize.Parcelize
import android.os.Parcelable

@Parcelize
data class User(
    val id: Int,
    val name: String,
    val email: String?
) : Parcelable

Дополнительные возможности

Плагин kotlin-parcelize поддерживает все фичи старого плагина:

  • Вложенные Parcelable классы — автоматическая сериализация
  • Пользовательские Parceler — через аннотацию @TypeParceler
  • Игнорирование полей — с помощью @IgnoredOnParcel

Пример с кастомным Parceler для даты:

import org.jetbrains.parcelize.Parcelize
import org.jetbrains.parcelize.TypeParceler
import android.os.Parcelable
import java.util.Date

// Создаём свой Parceler для Date
object DateParceler : Parceler<Date> {
    override fun create(parcel: Parcel) = Date(parcel.readLong())
    override fun Date.write(parcel: Parcel, flags: Int) = parcel.writeLong(time)
}

@Parcelize
@TypeParceler<Date, DateParceler>()
data class Event(
    val name: String,
    val date: Date
) : Parcelable

После миграции не забудьте выполнить Clean Project и Rebuild, чтобы избежать кэшированных ошибок. Если ваш проект использует kotlinx.android.synthetic (биндинг View по id), его нужно заменить на View Binding или Jetpack Compose, так как kotlin-parcelize не включает эту функциональность.

<<>>

Альтернативный подход: ручная реализация Parcelable

Если по каким-то причинам вы не хотите использовать плагин kotlin-parcelize, можно реализовать Parcelable вручную. Это даёт полный контроль над процессом сериализации, но требует больше кода.

import android.os.Parcel
import android.os.Parcelable

data class User(
    val id: Int,
    val name: String,
    val email: String?
) : Parcelable {

    constructor(parcel: Parcel) : this(
        parcel.readInt(),
        parcel.readString() ?: "",
        parcel.readString()
    )

    override fun writeToParcel(parcel: Parcel, flags: Int) {
        parcel.writeInt(id)
        parcel.writeString(name)
        parcel.writeString(email)
    }

    override fun describeContents(): Int = 0

    companion object CREATOR : Parcelable.Creator<User> {
        override fun createFromParcel(parcel: Parcel): User = User(parcel)
        override fun newArray(size: Int): Array<User?> = arrayOfNulls(size)
    }
}

Этот способ полезен, когда:

  • У вас сложная логика сериализации, которую не покрывает @Parcelize
  • Вы хотите избежать дополнительных плагинов в проекте
  • Нужна обратная совместимость со старыми версиями Kotlin

Однако для 90% случаев @Parcelize с плагином kotlin-parcelize — это более удобное и менее подверженное ошибкам решение. Ручная реализация требует внимательно следить за порядком чтения и записи полей, иначе получите RuntimeException.