[!]Важно.
- Библиотека находится в статусе разработки и миграции на более актуальные решения. Актуальность данного документа стоит уточнить у холдера библиотеки. В данный момент это r.choryev@redmadrobot.com
- В библиотеке млогут быть спорные решения, но она открыта для предложений.
- В текущих плагинах, для работы со списками используется Groupie.
Т.к. эта библиотека требует использование
jcenter
и уже не кажется таким уж подходящим решением, поэтому она будет удаляться из библиотеки. Поэтому это стоит учесть при разработке ваших новых плагинов и использовать какое-то другое решение.
Debug panel разрабатывается опираясь на подход разработки функционала отдельными плагинами. В данный момент есть несколько модулей на которых основана работа самой панели и разработка и работа плагинов.
- debug-panel-core - Реализация самой панели и базовых классов для поддержки системы плагинов.
- debug-panel-common - Модуль содержащий общие библиотеки, классы и ресурсы переиспользуемые в плагинах.
Библиотеки пробрасываются как сквозные зависимости при помощи типа зависимости
api
. Список предоставляемых библиотек можно посмотреть в файле build.gradle
Для добавления нового плагина необходимо сделать несколько шагов:
- Создать в дирректории plugins новый модуль для реализации своего плагина.
plugins
| your-plugin
- Объявить новый модуль в файле settings.gradle по примеру уже существующих плагинов.
include ':your-plugin'
project(':your-plugin').projectDir = new File(rootDir, 'plugins/your-plugin')
- Добавить в 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
- Создать в своем модуле класс-плагин который и будет отвечать за взаимодействие с 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()
}
}
- Создать Fragment экрана плагина(если он нужен) и унаследовать его от
PluginFragment()
. К фрагменту создать ViewModel и унаследовать отPluginViewModel()
. В этой связке (Fragment+ViewModel), реализовывать пользовательское взаимодействие пользователя с плагином.
В библиотеке не используются библиотеки для реализации DI, т.к.:
- Не хочется тащить их зависимости в библиотеку.
- Библиотека не такая большая чтобы реализовывать полноценный 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
Для тестирования плагина, необходимо:
- Подключить его как зависимость в модуль
sample
.
debugImplementation(project(path: ':your-plugin'))
- Инициировать плагин в App классе sample приложения.
DebugPanel.initialize(
application = this,
plugins = listOf(YourPluggin())
)
- Запустить sample проект
Для того чтобы в релизную сборку не попадали реализации публичных классов вашего модуля, необходимо добавить их в модуль no-op зависимостей.
(Подробнее в статье).
Для этого создайте пакет с именем вашего плагина в модуле debug-panel-no-op и скопируйте ваши публичные классы доступные пользователю в этот пакет.
[!]Важно. Поле package должно остаться оригинальным. Таким, каким оно было в вашем модуле.
Публикация новых плагнинов в основном репозитории должна проходить через создание Merge Request в ветку develop.
Публикация на внутренний Maven пока делается вручную. За публикацией обращаться к r.choryev@redmadrobot.com. В ближайшее время есть планы пересмотреть этот подход.