Skip to content

Latest commit

 

History

History
182 lines (135 loc) · 9.78 KB

plugin_development.md

File metadata and controls

182 lines (135 loc) · 9.78 KB

Разработка новых плагинов

[!]Важно.

  1. Библиотека находится в статусе разработки и миграции на более актуальные решения. Актуальность данного документа стоит уточнить у холдера библиотеки. В данный момент это r.choryev@redmadrobot.com
  2. В библиотеке млогут быть спорные решения, но она открыта для предложений.
  3. В текущих плагинах, для работы со списками используется Groupie. Т.к. эта библиотека требует использование jcenter и уже не кажется таким уж подходящим решением, поэтому она будет удаляться из библиотеки. Поэтому это стоит учесть при разработке ваших новых плагинов и использовать какое-то другое решение.

Общая структура

Debug panel разрабатывается опираясь на подход разработки функционала отдельными плагинами. В данный момент есть несколько модулей на которых основана работа самой панели и разработка и работа плагинов.

  • debug-panel-core - Реализация самой панели и базовых классов для поддержки системы плагинов.
  • debug-panel-common - Модуль содержащий общие библиотеки, классы и ресурсы переиспользуемые в плагинах. Библиотеки пробрасываются как сквозные зависимости при помощи типа зависимости api. Список предоставляемых библиотек можно посмотреть в файле build.gradle

Создание нового плагина

Для добавления нового плагина необходимо сделать несколько шагов:

  1. Создать в дирректории plugins новый модуль для реализации своего плагина.
plugins
|   your-plugin
  1. Объявить новый модуль в файле settings.gradle по примеру уже существующих плагинов.
include ':your-plugin'

project(':your-plugin').projectDir = new File(rootDir, 'plugins/your-plugin')
  1. Добавить в build.gradle файл вашего модуля следующие настройки:
android {
    /*.......*/
    
    compileSdkVersion build_versions.compile_sdk

    defaultConfig {
        minSdkVersion build_versions.min_sdk
        targetSdkVersion build_versions.target_sdk

        versionCode getVersionCodeFromProperties()
        versionName getVersionNameFromProperties()
    }

    /*.......*/


    kotlinOptions {
        freeCompilerArgs += "-Xexplicit-api=strict"
    }
}

dependencies {
    implementation(
            project(path: ':debug-panel-core'),
            project(path: ':debug-panel-common'),

            deps.kotlin.stdlib
    )
}

[!]Важно. Конфигурация будет меняться при дальнейшей миграции с Groovy на Kotlin

  1. Создать в своем модуле класс-плагин который и будет отвечать за взаимодействие с DebugPanel. Для этого класс должен унаследоваться от класса Plugin() и реализовать необходимые методы. В качестве аргументов класса можно передать необходимые для инициализации плагина данные.
    (О методе getPluginContainer() и PluginDependencyContainer() можно будет почитать ниже)
public class YourPlugin(
    /*some arguments*/
) : Plugin() {

    internal companion object {
        const val NAME = "AWESOME PLUGIN"
    }

    override fun getName(): String = NAME

    /*Plugin dependency container initializing*/
    override fun getPluginContainer(commonContainer: CommonContainer): PluginDependencyContainer {
        return YourPluginContainer(sharedPreferences)
    }

    /*Plugin Fragment initializing*/
    override fun getFragment(): Fragment? {
        return YourPluginFragment()
    }

    /*Plugin Setting Fragment initializing.*/ 
    override fun getSettingFragment(): Fragment { //Нужно только если есть отдельный экран для настройки плагина.
        return YourPluginSettingFragment()
    }
}
  1. Создать Fragment экрана плагина(если он нужен) и унаследовать его от PluginFragment(). К фрагменту создать ViewModel и унаследовать от PluginViewModel(). В этой связке (Fragment+ViewModel), реализовывать пользовательское взаимодействие пользователя с плагином.

PluginDependencyContainer

В библиотеке не используются библиотеки для реализации DI, т.к.:

  1. Не хочется тащить их зависимости в библиотеку.
  2. Библиотека не такая большая чтобы реализовывать полноценный DI.

Вместо этого, в библиотеке используется подход с Service Locator. Для этого необходимо создать свой класс-контейнер, унаследовать его от PluginDependencyContainer и внутри него инициировать необходимые зависимости. Если вам для этого понадобится Context, его можно получить из CommonContainer который прилетает в качестве аргумента в методе getPluginContainer() при инициализации плагина. Пример реализации можно посмотреть тут

Работа с классом плагина

Класс-плагин, описание которого было в пункте 4, является точкой инициализации вашего плагина. Поэтому доступ к данным и различным экземплярам классов нужно реализовывать через него. Чтобу получить доступ к самому плагину, нужно использовать метод getPlugin<YourPlugin>(). Например для получения контейнера зависимостей плагина, нужно вызвать:

getPlugin<YourPlugin>()
    .getContainer<YourPluginContainer>()

Пример использования плагина для получения ViewModel во Fragment:

 private val viewModel by lazy {
        obtainShareViewModel {
            getPlugin<ServersPlugin>()
                .getContainer<ServersPluginContainer>()
                .createServersViewModel()
        }
    }

Области видимости

Все внутренние классы используемые только для работы плагина и не требующиеся для работы клиентского приложения, должны иметь область видимости inner

Тестирование

Для тестирования плагина, необходимо:

  1. Подключить его как зависимость в модуль sample.
 debugImplementation(project(path: ':your-plugin'))
  1. Инициировать плагин в App классе sample приложения.
  DebugPanel.initialize(
            application = this,
            plugins = listOf(YourPluggin())
)
  1. Запустить sample проект

No-op зависимости

Для того чтобы в релизную сборку не попадали реализации публичных классов вашего модуля, необходимо добавить их в модуль no-op зависимостей. (Подробнее в статье).
Для этого создайте пакет с именем вашего плагина в модуле debug-panel-no-op и скопируйте ваши публичные классы доступные пользователю в этот пакет.

[!]Важно. Поле package должно остаться оригинальным. Таким, каким оно было в вашем модуле.

Публикация

Публикация новых плагнинов в основном репозитории должна проходить через создание Merge Request в ветку develop.

Публикация на внутренний Maven пока делается вручную. За публикацией обращаться к r.choryev@redmadrobot.com. В ближайшее время есть планы пересмотреть этот подход.