Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Re:Android Studio 설정 살펴보기 및 생산성 올리기

Re:Android Studio 설정 살펴보기 및 생산성 올리기

"DroidKnights 2023"에서 발표한 "Re:Android Studio 설정 살펴보기 및 생산성 올리기" 발표 자료입니다.

pluulove (노현석)

September 12, 2023
Tweet

More Decks by pluulove (노현석)

Other Decks in Programming

Transcript

  1. Re:Android Studio

    ࢸ੿ ࢓ಝࠁӝ ߂ ࢤ࢑ࢿ ৢܻӝ
    Pluu

    KakaoBank


    Google Developer Experts

    View Slide

  2. উ֞ೞࣁਃ

    pluuੑפ׮


    KakaoBank


    Android App Developer


    Google Developer Experts

    View Slide

  3. Sample
    ❏ https://github.com/Pluu/AndroidStudio_Presentation


    ❏ https://github.com/Pluu/intellij-platform-plugin-template/tree/develop

    View Slide

  4. Part 1 Part 2
    Android Studio
    ࢸ੿ ࢓ಝࠁӝ


    (30min)
    Custom Plugin

    ઁ੘


    (15 min)

    View Slide

  5. Tools
    Android Studio


    Giraffe
    IntelliJ IDEA


    2023.2

    View Slide

  6. PART 1


    Android Studio
    ࢸ੿ ࢓ಝࠁӝ

    View Slide

  7. Search Everywhere


    Double ⇧ Shift
    Find Action


    ⌘ Сmd + ⇧ Shift + A
    Show Context Actions


    ⌥ Opt + ↩ Enter
    Navigate between code issues


    F2 / ⇧ Shift + F2
    View recent files


    ⌘ Сmd + E
    Complete Current Statement


    ⌘ Сmd + ⇧ Shift + ↩ Enter
    Reformat Code


    ⌘ Сmd + ⌥ Opt + L
    Invoke refactoring


    ⌃ Ctrl + T
    Extend or shrink selection


    ⌥ Opt + ↑ / ⌥ Opt + ↓
    Add/remove line or block comment


    ⌘ Сmd + / / ⌘ Сmd + ⌥ Opt + /
    Go To Declaration


    ⌘ Сmd + B
    Find Usages


    ⌥ Opt + F7
    Focus the Project tool window


    ⌘ Сmd + 1
    Focus the editor


    ⎋ Esc
    IntelliJ IDEA੄
    ਬਊೠ ױ୷ః
    IntelliJ IDEA keyboard shortcuts : https://www.jetbrains.com/help/idea/mastering-keyboard-shortcuts.html
    Reformat Code


    ⌘ Сmd + ⌥ Opt + L
    View recent files


    ⌘ Сmd + E
    Show Context Actions


    ⌥ Opt + ↩ Enter
    Find Action


    ⌘ Сmd + ⇧ Shift + A
    Extend or shrink selection


    ⌥ Opt + ↑ / ⌥ Opt + ↓
    Go To Declaration


    ⌘ Сmd + B
    Find Usages


    ⌥ Opt + F7
    Navigate between code issues


    F2 / ⇧ Shift + F2
    Focus the Project tool window


    ⌘ Сmd + 1
    Invoke refactoring


    ⌃ Ctrl + T

    View Slide

  8. • Inlay Hints


    • Surround With…


    • Complete Current Statement


    • Chose Content to Paste


    • Highlighted Error


    • Move Between method


    • Refactor


    • Change Signature


    • Extract/Introduce


    • Recent Files


    • Quick Definition
    • Quick Lists


    • My Productivity


    • Logcat > Fold Lines Like This


    • Compare


    • Put parameters on separate lines


    • Interactively Rebase


    • Version Control > Shelf


    • Layout Editor


    • Live Templates


    • File and Code Templates


    • Logcat Color


    • Postfix Completion


    • Method Separators
    Demo…

    View Slide

  9. Copy References Path


    Preferences | Appearance & Behavior | New UI

    View Slide

  10. LIVE DEMO

    View Slide

  11. Quick List


    Preferences | Appearance & Behavior | Quick Lists

    View Slide

  12. Quick List


    Preferences | Appearance & Behavior | Quick Lists

    View Slide

  13. My Productivity


    Help - My Productivity

    View Slide

  14. Put parameters on separate lines

    View Slide

  15. Interactively Rebase
    https://www.jetbrains.com/help/idea/edit-project-history.html#interactive-rebase

    View Slide

  16. Interactively Rebase

    View Slide

  17. Interactively Rebase
    Fixup

    View Slide

  18. Interactively Rebase
    Fixup

    View Slide

  19. Shelf

    View Slide

  20. Shelf

    View Slide

  21. Shelf

    View Slide

  22. Shelf

    View Slide

  23. Live Templates
    ❏ ߈ࠂ,ઑѤ,ࢶ঱ ١ ੌ߈੸ੋ
    ҳޙਸ ௏٘ী ࢗੑ
    Live templates : https://www.jetbrains.com/help/idea/using-live-templates.html#live_templates_types

    View Slide

  24. Toast.makeText(, "", Toast.LENGTH_SHORT).show()
    toast
    Sample Live Templates

    View Slide

  25. Live Templates


    Preferences | Editor | Live Templates

    View Slide

  26. Live Templates


    Preferences | Editor | Live Templates

    View Slide

  27. Logcat Colors


    Preferences | Editor | Color Scheme | Android Logcat

    View Slide

  28. Postfix
    Completion
    ❏ ੑ۱ೠ ಴അध ઱ਤী

    మ೒݁ ௏٘ܳ ୶о


    ❏ ੼(.) ٍী ৘ডয ੑ۱ೞҊ
    ࢶఖೞݶ మ೒݁ ௏٘о ୶о

    View Slide

  29. Postfix Completion


    Preferences | Editor | General | Postfix Completion

    View Slide

  30. Postfix Completion


    Preferences | Editor | General | Postfix Completion

    View Slide

  31. Inlay Hints


    Preferences | Editor | Inlay Hints

    View Slide

  32. Inlay Hints


    Preferences | Editor | Inlay Hints
    ❏ Enable
    Parameter names / Types /
    Values

    View Slide

  33. Inlay Hints


    Preferences | Editor | Inlay Hints
    Enabled

    View Slide

  34. Surround With


    ⌘ Cmd + ⌥ Option + T / Code - Surround With...

    View Slide

  35. Surround With


    ⌘ Cmd + ⌥ Option + T / Code - Surround With...

    View Slide

  36. Chose Content to Paste


    ⌘ Сmd + ⇧ Shift + V / Edit - Paste - Paste from History

    View Slide

  37. Change Signature


    ⌘ Сmd + F6 / Refactor - Change Signature

    View Slide

  38. Recent Files


    ⌘ Сmd + E / View - Recent Files

    View Slide

  39. Expression Type


    ⇧ Shift + ⌃ Ctrl + P / View - Type Info

    View Slide

  40. Quick Definition


    ⌥ Option + Space / View | Quick Definition

    View Slide

  41. PART 2


    Custom Plugin


    ઁ੘

    View Slide

  42. Plugin੄ ೙ਃࢿ
    ❏ Android Studio੄ ӝࠄ ӝמ੄ ইए਑


    ❏ ӝࠄ ઁҕ ࣻળҗ ೐۽ં౟ ҳઑ৬੄ ࠛӐഋ


    ❏ ࠁੌ۞ ೒ۨ੉౟ ௏٘ ഑਷ ز੘ٜ


    ❏ ழझథ ӝמ੄ ೙ਃࢿ

    View Slide

  43. Activity


    Wizard
    Module


    Wizard
    Plugin Demo

    View Slide

  44. Wizard
    File
    File
    File
    File
    File
    Code Block
    File
    Template
    Live
    Template

    View Slide

  45. ؀ࠗ࠙ ࢎਊ೧ࠄ Wizard

    View Slide

  46. Code ߧ۹
    Custom
    Not


    Custom

    View Slide

  47. PART 2-1


    Custom Module
    Wizard

    View Slide

  48. Create Module

    View Slide

  49. New Feature Module
    1
    2
    3

    View Slide

  50. Settings
    build.gradle
    AndroidManifest.xml
    .gitignore Proguard files


    - proguard-rules.pro


    - consumer-rules.pro
    Test


    - UI Test


    - Unit Test
    Update New
    build.gradle
    Custom ৔৉

    View Slide




  51. ...






    implementation="pluu.FeatureModuleDescriptionProvider"/>









    META-INF/plugin.xml

    View Slide

  52. Module ࢤࢿ ױ҅ ੿੄
    class FeatureModuleDescriptionProvider : ModuleDescriptionProvider {


    override fun getDescriptions(project: Project) =


    listOf(


    FeatureModuleTemplateGalleryEntry()


    )


    }
    Module ࢤࢿ਷ 1ױ҅݅ ੿੄


    ೙ਃী ٮۄ ୶о ࢶ঱
    https://cs.android.com/android-studio/platform/tools/adt/idea/+/mirror-goog-studio-main:android-npw/src/com/android/tools/idea/
    npw/module/ModuleDescriptionProvider.kt

    View Slide

  53. View Slide

  54. class FeatureModuleTemplateGalleryEntry : ModuleGalleryEntry {


    override val icon: Icon = PluuIcons.Konata


    override val name: String = PluuBundle.message(“...”)


    override val description: String = PluuBundle.message(“...”)


    override fun toString(): String = name


    override fun createStep(


    project: Project,


    moduleParent: String,


    projectSyncInvoker: ProjectSyncInvoker


    ): SkippableWizardStep<*> {


    val basePackage = getSuggestedProjectPackage()


    val model = NewFeatureModuleModel.fromExistingProject(


    ...


    п Step߹ ز੘ ੿੄
    ݽٕ ݾ۾ী ֢୹ೡ ੿ࠁ

    View Slide



  55. override val name: String = PluuBundle.message(“...”)


    override val description: String = PluuBundle.message(“...”)


    override fun toString(): String = name


    override fun createStep(


    project: Project,


    moduleParent: String,


    projectSyncInvoker: ProjectSyncInvoker


    ): SkippableWizardStep<*> {


    val basePackage = getSuggestedProjectPackage()


    val model = NewFeatureModuleModel.fromExistingProject(


    ...


    )


    return ConfigureFeatureModuleStep(model, LOWEST_ACTIVE_API, basePackage,
    name)


    }


    }
    п Step߹ ز੘ ੿੄
    1.Wizard ࢤࢿী ೙ਃೠ ੿ࠁ


    2.ੑ۱ ಬ ੿ࠁ ੿੄

    View Slide

  56. View Slide

  57. class ConfigureFeatureModuleStep(


    model: NewFeatureModuleModel,


    minSdkLevel: Int,


    basePackage: String?,


    title: String


    ) : ConfigureModuleStep(...) {


    private val appName = JBTextField(model.applicationName.get())


    private val bytecodeCombo = BytecodeLevelComboProvider().createComponent()


    private val conventionPluginCheckbox = JBCheckBox("Use Gradle convention
    plugin")


    override fun createMainPanel(): DialogPanel = panel {


    row(contextLabel("Module name",
    AndroidBundle.message("android.wizard.module.help.name"))) {




    ੑ۱ ಬ
    ੑ۱ਵ۽ ߉ਸ UI ੿੄
    import javax.swing.JTextField;
    import javax.swing.JComboBox;
    import javax.swing JCheckBox;

    View Slide



  58. private val bytecodeCombo = BytecodeLevelComboProvider().createComponent()


    private val conventionPluginCheckbox = JBCheckBox("Use Gradle convention
    plugin")


    override fun createMainPanel(): DialogPanel = panel {


    row(contextLabel("Module name",
    AndroidBundle.message("android.wizard.module.help.name"))) {


    cell(moduleName).align(AlignX.FILL)


    }


    ...


    row("Language") {


    cell(languageCombo).align(AlignX.FILL)


    }


    ...


    row {


    cell(conventionPluginCheckbox).align(AlignX.FILL)


    }


    }.withBorder(empty(6))


    ੑ۱ ಬ
    JBCheckBox
    JTextField
    JTextField

    View Slide

  59. class NewFeatureModuleModel(


    projectModelData: ProjectModelData,


    template: NamedModuleTemplate,


    moduleParent: String,


    override val formFactor: ObjectProperty,


    override val category: ObjectProperty,


    commandName: String = "New Module",


    override val isLibrary: Boolean = false,


    wizardContext: WizardUiContext


    ) : ModuleModel(


    ...


    ) {


    val bytecodeLevel = OptionalValueProperty(getInitialBytecodeLevel())


    val conventionPlugin = BoolValueProperty(true)


    ModuleModel ੿੄
    ModuleStepীࢲ ࢎਊೡ ؘ੉ఠ

    View Slide



  60. wizardContext: WizardUiContext


    ) : ModuleModel(


    ...


    ) {


    val bytecodeLevel = OptionalValueProperty(getInitialBytecodeLevel())


    val conventionPlugin = BoolValueProperty(true)


    override val renderer = object : ModuleTemplateRenderer() {


    override val recipe: Recipe


    get() = { td: TemplateData ->


    generateFeatureModule(


    data = td as ModuleTemplateData,


    bytecodeLevel = bytecodeLevel.value,


    useVersionCatalog = true,


    useConventionPlugins = conventionPlugin.get()


    )


    }


    }


    ModuleModel ੿੄
    ModuleModel੄ ೨ब


    ౵ੌ ࢤࢿ ۽૒੉ ઓ੤

    View Slide

  61. fun RecipeExecutor.generateFeatureModule(


    data: ModuleTemplateData,


    useKts: Boolean = false,


    addLintOptions: Boolean = false,


    bytecodeLevel: BytecodeLevel = BytecodeLevel.default,


    useVersionCatalog: Boolean = false,


    useConventionPlugins: Boolean = false


    ) {


    ...


    createDefaultDirectories(moduleOut, srcOut)


    addIncludeToSettings(data.name)


    val gradleFile: String = if (useConventionPlugins) {


    buildFeatureGradle(




    ౵ੌ ࢤࢿ
    1.ಫ؊ ࢤࢿ


    2.settings.gradle ୶о

    View Slide



  62. ...


    createDefaultDirectories(moduleOut, srcOut)


    addIncludeToSettings(data.name)


    val gradleFile: String = if (useConventionPlugins) {


    buildFeatureGradle(


    isKts = useKts,


    applicationId = data.namespace,


    useVersionCatalog = useVersionCatalog


    )


    } else {


    buildGradle(...)


    }


    save(gradleFile, moduleOut.resolve(FN_BUILD_GRADLE))


    if (isLibraryProject) {


    if (useConventionPlugins) {




    ౵ੌ ࢤࢿ
    Custom build.gradle
    Default build.gradle
    build.gradle ੷੢

    View Slide



  63. }


    save(gradleFile, moduleOut.resolve(FN_BUILD_GRADLE))


    if (isLibraryProject) {


    if (useConventionPlugins) {


    // build-logic


    applyPlugin(PluuPlugin.Convension.LIBRARY, null)


    applyPlugin(PluuPlugin.Convension.HILT, null)


    } else {


    applyPlugin(PluuPlugin.Android.LIBRARY, null)


    }


    }


    if (!useConventionPlugins) {


    addKotlinIfNeeded(...)


    requireJavaVersion(...)


    }



    ౵ੌ ࢤࢿ
    plugins {


    id 'pluu.android.library'


    id 'pluu.android.hilt'


    }
    plugins {


    id 'com.android.library'


    }

    View Slide



  64. addKotlinIfNeeded(...)


    requireJavaVersion(...)


    }


    if (data.useGenericLocalTests) {


    addLocalTests(...)


    addTestDependencies()


    }


    if (data.useGenericInstrumentedTests) {


    addInstrumentedTests(...)


    addTestDependencies()


    }


    save(


    generateManifest(


    hasApplicationBlock = !isLibraryProject,


    theme = "@style/${data.themesData.main.name}",


    ),



    ౵ੌ ࢤࢿ
    Unit Test
    Instrument Test

    View Slide



  65. addInstrumentedTests(...)


    addTestDependencies()


    }


    save(


    generateManifest(


    hasApplicationBlock = !isLibraryProject,


    theme = "@style/${data.themesData.main.name}",


    ),


    manifestOut.resolve(FN_ANDROID_MANIFEST_XML)


    )


    save(gitignore(), moduleOut.resolve(".gitignore"))


    proguardRecipe(moduleOut, isLibraryProject)


    }
    ౵ੌ ࢤࢿ
    AndroidManifest.xml
    Proguard
    gitignore

    View Slide

  66. PART 2-1


    Custom Activity
    Wizard

    View Slide

  67. Create Activity

    View Slide

  68. New Activity Wizard

    View Slide

  69. New Activity Wizard

    View Slide

  70. AndroidManifest.xml
    _____Activity.kt
    Update New
    build.gradle
    activity______.xml
    _____ViewModel.kt
    Custom ৔৉
    _____Activity.kt
    activity______.xml
    _____ViewModel.kt

    View Slide

  71. META-INF/plugin.xml



    ...







    implementation="pluu.WizardTemplateProviderImpl"/>








    Wizard Provider

    View Slide

  72. WizardTemplateProvider
    https://cs.android.com/android-studio/platform/tools/base/+/mirror-goog-studio-main:wizard/template-plugin/src/com/android/
    tools/idea/wizard/template/WizardTemplateProvider.kt
    class WizardTemplateProviderImpl: WizardTemplateProvider() {


    override fun getTemplates(): List = listOf(


    sampleActivitySetupTemplate


    )


    }
    ழझథਵ۽ ઁҕೡ


    Wizard Template ੿੄

    View Slide

  73. val sampleActivitySetupTemplate


    get() = template {


    name = ...


    minApi = MIN_API


    description = ...


    category = Category.Activity


    formFactor = FormFactor.Mobile


    screens = listOf(


    WizardUiContext.ActivityGallery,


    WizardUiContext.MenuEntry,


    WizardUiContext.NewProject,


    WizardUiContext.NewModule




    WizardTemplateProvider
    Activity,


    Fragment,


    Application,


    Folder,


    Service,


    UiComponent,


    Automotive,


    XML,


    Wear,


    AIDL,


    Widget,


    Google,


    Compose,


    Other;
    Mobile,


    Wear,


    Tv,


    Automotive,


    Generic;

    View Slide

  74. val sampleActivitySetupTemplate


    get() = template {


    name = ...


    minApi = MIN_API


    description = ...


    category = Category.Activity


    formFactor = FormFactor.Mobile


    screens = listOf(


    WizardUiContext.ActivityGallery,


    WizardUiContext.MenuEntry,


    WizardUiContext.NewProject,


    WizardUiContext.NewModule




    WizardTemplateProvider
    Activity,


    Fragment,


    Application,


    Folder,


    Service,


    UiComponent,


    Automotive,


    XML,


    Wear,


    AIDL,


    Widget,


    Google,


    Compose,


    Other;
    Mobile,


    Wear,


    Tv,


    Automotive,


    Generic;
    Category

    View Slide



  75. category = Category.Activity


    formFactor = FormFactor.Mobile


    screens = listOf(


    WizardUiContext.ActivityGallery,


    WizardUiContext.MenuEntry,


    WizardUiContext.NewProject,


    WizardUiContext.NewModule


    )


    lateinit var activityClass: StringParameter


    val layoutName = stringParameter {


    name = "Layout Name"


    default = "activity_main"


    suggest = { activityToLayout(activityClass.value) }


    help = "The name of the layout to create for the activity"


    constraints = listOf(LAYOUT, UNIQUE, NONEMPTY)




    WizardTemplateProvider
    Wizardо ࠁৈ૕ ਤ஖

    View Slide

  76. WizardUiContext.NewProject,


    WizardUiContext.NewModule


    )


    lateinit var activityClass: StringParameter


    val layoutName = stringParameter {


    name = "Layout Name"


    default = "activity_main"


    suggest = { activityToLayout(activityClass.value) }


    help = "The name of the layout to create for the activity"


    constraints = listOf(LAYOUT, UNIQUE, NONEMPTY)


    }


    activityClass = stringParameter {


    ...


    suggest = { layoutToActivity(layoutName.value) }


    }



    WizardTemplateProvider
    ୶ୌ ౵ੌݺ
    ੑ۱ಬ ղ੄ ׮ܲ ೦ݾب ࢎਊ оמ

    View Slide



  77. suggest = { layoutToActivity(layoutName.value) }


    }


    val useBinding = enumParameter {


    name = "Use binding"


    default = ViewBindingType.ViewBinding


    help = "Help"


    }


    val isViewModel = booleanParameter {


    name = "Use ViewModel"


    default = true


    help = "(Default true), Use ViewModel"


    }


    val viewModelClass = stringParameter { ... }


    val packageNameParam = defaultPackageNameParameter


    WizardTemplateProvider
    Enum
    Boolean

    View Slide

  78. val viewModelClass = stringParameter { ... }


    val packageNameParam = defaultPackageNameParameter


    widgets(


    TextFieldWidget(activityClass),


    TextFieldWidget(layoutName),


    CheckBoxWidget(isViewModel),


    TextFieldWidget(viewModelClass),


    EnumWidget(useBinding),


    Separator,


    PackageNameWidget(packageNameParam)


    )


    thumb { File("empty-activity").resolve("template_empty_activity.png") }


    recipe = { data ->


    sampleActivitySetup(



    WizardTemplateProvider
    ۨ੉ইਓ ߓ஖

    View Slide



  79. thumb { File("empty-activity").resolve("template_empty_activity.png") }


    recipe = { data ->


    sampleActivitySetup(


    moduleData = data as ModuleTemplateData,


    packageName = packageNameParam.value,


    activityClass = activityClass.value,


    layoutName = layoutName.value,


    isUsedViewModel = isViewModel.value,


    viewModelClass = viewModelClass.value,


    viewBindingType = useBinding.value


    )


    }


    }



    WizardTemplateProvider
    ౵ੌ ࢤࢿ ਃ୒

    View Slide

  80. fun RecipeExecutor.sampleActivitySetup(...) {


    // Add, Dependencies


    if (!useConventionPlugin) {


    addAllKotlinDependencies(moduleData)


    }


    addMaterialDependency(useAndroidX)


    addDependency("com.android.support:appcompat-v7:$appCompatVersion.+")


    addDependency("com.android.support.constraint:constraint-layout:+")


    if (isUsedViewModel) {


    addDependency("androidx.activity:activity-ktx:+")


    addLifecycleDependencies(true)


    }


    // Add, Manifest



    ౵ੌ ࢤࢿ
    Gradle ઙࣘࢿ ੿੄
    Support ۄ੉࠳ߡܻח ࢤࢿद


    AndroidX۽ ؀୓ؽ

    View Slide



  81. addDependency("androidx.activity:activity-ktx:+")


    addLifecycleDependencies(true)


    }


    // Add, Manifest


    generateManifest(


    moduleData, activityClass, packageName,


    isLauncher = false,


    hasNoActionBar = false,


    generateActivityTitle = false


    )


    // Create, Activity


    val simpleActivityPath = srcOut.resolve("$activityClass.$ktOrJavaExt")


    val simpleActivity = basicActivityKt(


    isNewProject = moduleData.isNewModule,


    applicationPackage = projectData.applicationPackage,


    packageName = packageName,


    ౵ੌ ࢤࢿ
    AndroidManifest.xmlী ୶о

    View Slide



  82. generateActivityTitle = false


    )


    // Create, Activity


    val simpleActivityPath = srcOut.resolve("$activityClass.$ktOrJavaExt")


    val simpleActivity = basicActivityKt(


    isNewProject = moduleData.isNewModule,


    applicationPackage = projectData.applicationPackage,


    packageName = packageName,


    useAndroidX = useAndroidX,


    activityClass = activityClass,


    layoutName = layoutName,


    viewBindingType = viewBindingType,


    isUsedViewModel = isUsedViewModel,


    viewModelClass = viewModelClass,


    )


    save(simpleActivity, simpleActivityPath)


    open(simpleActivityPath)


    ౵ੌ ࢤࢿ
    Custom Activity Template

    View Slide

  83. Activity Wizard Sample

    View Slide



  84. )


    save(simpleActivity, simpleActivityPath)


    open(simpleActivityPath)


    // Create, Layout


    if (viewBindingType.isDataBinding) {


    save(


    generateDataBindingSimpleXml(activityClass, packageName),


    resOut.resolve("layout/${layoutName}.xml")


    )


    } else {


    generateSimpleLayout(moduleData, activityClass, layoutName)


    }


    open(resOut.resolve("layout/${layoutName}.xml"))


    // Create, ViewModel


    if (isUsedViewModel) {


    val viewModel = viewModelKt(packageName, useAndroidX, viewModelClass)



    ౵ੌ ࢤࢿ
    DataBindingਊ Layout ࢤࢿ
    ӝઓ SimpleLayout ഝਊ

    View Slide

  85. Layout Wizard Sample

    View Slide



  86. generateSimpleLayout(moduleData, activityClass, layoutName)


    }


    open(resOut.resolve("layout/${layoutName}.xml"))


    // Create, ViewModel


    if (isUsedViewModel) {


    val viewModel = viewModelKt(packageName, useAndroidX, viewModelClass)


    val viewModelPath = srcOut.resolve("${viewModelClass}.${ktOrJavaExt}")


    save(viewModel, viewModelPath)


    open(viewModelPath)


    }


    // Enable, BuildFeature


    if (viewBindingType.isViewBinding) {


    setBuildFeature("viewBinding", true)


    } else if (viewBindingType.isDataBinding) {


    setBuildFeature("dataBinding", true)


    }


    ౵ੌ ࢤࢿ
    ViewModel ౵ੌ ࢤࢿ

    View Slide

  87. ViewModel Wizard Sample

    View Slide



  88. save(viewModel, viewModelPath)


    open(viewModelPath)


    }


    // Enable, BuildFeature


    if (viewBindingType.isViewBinding) {


    setBuildFeature("viewBinding", true)


    } else if (viewBindingType.isDataBinding) {


    setBuildFeature("dataBinding", true)


    }


    if (!useConventionPlugin && generateKotlin) {


    requireJavaVersion("1.8", true)


    }


    }
    ౵ੌ ࢤࢿ
    BuildFeature ഝࢿച

    View Slide

  89. Summary
    Plugin
    File Template
    ࢤࢿ դ੉ب
    ׮ࣻ ౵ੌ
    ױੌ ౵ੌ
    Live Template ௏٘ ࠶۟
    ઁড ࢎ೦
    য۰਑
    ए਑ ~ ઺р
    ए਑
    AS ߸҃ द


    ࣻ੿ ೙ਃ
    Plugin
    Plugin

    View Slide

  90. Plugin Summary
    ❏ Android Studio Wizardਊ ੗ܐח డহ੉ ࠗ઒


    ❏ Android Studio ࣗझ ௏٘ীࢲ ଺ח ߑߨ੉ Ѩ࢝੄ 80%


    ❏ ೐۽ં౟੄ ழझథ ࣻળী ٮۄࢲ Template ഑਷ Wizard ࢶఖ

    View Slide

  91. Reference
    ❏ intellij-community : https://github.com/JetBrains/intellij-community


    ❏ JetBrains/android : https://github.com/JetBrains/android


    ❏ Android Studio source : https://cs.android.com/android-studio

    View Slide

  92. THANK YOU
    Pluu

    KakaoBank


    Google Developer Experts

    View Slide