在android开发中使用MVP模式进行开发最烦的就是要创建model,presenter,view等等一系列文件。这大大的降低了开发效率,那么有没有方法能够解决这个问题呢?这里不得不感谢AS的伟大,他为我们提供了这一类事插件的功能。

在创建Activity的过程中这一张图片大家一定很熟悉

android 使用uimode android 使用建模文件_模版

当我们点击Empty Activity时给我们创建了一个带XML布局的Activity,并且帮我们在清单文件中注册了Activity。可能大家之前只用了这个功能,却没有想过为什么他能这样帮我们创建好这些个文件。没错今天要说的这个解决办法就是要依赖这个AS提供的可扩展办法。

我这里用的是Mac系统,Windows系统请自行找到位置

android 使用uimode android 使用建模文件_xml_02

打开应用程序->右击显示包内容........按照上面图片底部的路径找到那个文件夹。是不是很惊喜,哈哈哈哈哈。原来我们在创建Activity是可以选择的模版都在这里。既然找到了根源我们就来看一下他的庐山真面目。

android 使用uimode android 使用建模文件_模版_03

android 使用uimode android 使用建模文件_模版_04

发现一个模版主要就是由上面那几个文件构成。

简单说明一下

globals文件主要是配置一些全局的变量

recipe文件用来将模版文件从模版路径输出到我们想要的路径

template文件就是配置我们新建Activity时的那个新建界面

.png的这张图就是我们的模版预览图片

root 就是我们Activity模版真正实现的地方

这里我贴一下我的MVP的模版代码,大家自行理解吧,应该不难的。

1.globals文件

<?xml version="1.0"?>
<globals>
    <global id="hasNoActionBar" type="boolean" value="false" />
    <global id="parentActivityClass" value="" />
    <global id="excludeMenu" type="boolean" value="true" />
    <global id="generateActivityTitle" type="boolean" value="false" />
    <global id="activityClass" value="${pageName}Activity" />
    <#include "../common/common_globals.xml.ftl" />
</globals>

2.recipe文件

<?xml version="1.0"?>
<#import "root://activities/common/kotlin_macros.ftl" as kt>
<recipe>
    <#include "../common/recipe_manifest.xml.ftl" />
    <@kt.addAllKotlinDependencies />


<#if generateActivityLayout>
    <instantiate from="root/res/layout/simple.xml.ftl"
                 to="${escapeXmlAttribute(resOut)}/layout/${activityLayoutName}.xml" />
</#if>

<#if generateKotlin>
    <instantiate from="root/src/app_package/MVPActivity.kt.ftl"
                   to="${escapeXmlAttribute(srcOut)}/${pageName}/view/${pageName}Activity.kt" />
    <open file="${escapeXmlAttribute(srcOut)}/${pageName}/view/${pageName}Activity.kt" />

    <instantiate from="root/src/app_package/MVPContract.kt.ftl"
                   to="${escapeXmlAttribute(srcOut)}/${pageName}/contract/${pageName}Contract.kt" />

    <instantiate from="root/src/app_package/MVPPresenter.kt.ftl"
                   to="${escapeXmlAttribute(srcOut)}/${pageName}/presenter/${pageName}Presenter.kt" />
    <instantiate from="root/src/app_package/MVPModel.kt.ftl"
                   to="${escapeXmlAttribute(srcOut)}/${pageName}/model/${pageName}Model.kt" />
<#else>
<instantiate from="root/src/app_package/MVPActivity.java.ftl"
                   to="${escapeXmlAttribute(srcOut)}/${pageName}/view/${pageName}Activity.java" />
    <open file="${escapeXmlAttribute(srcOut)}/${pageName}/view/${pageName}Activity.java" />

    <instantiate from="root/src/app_package/MVPContract.java.ftl"
                   to="${escapeXmlAttribute(srcOut)}/${pageName}/contract/${pageName}Contract.java" />

    <instantiate from="root/src/app_package/MVPPresenter.java.ftl"
                   to="${escapeXmlAttribute(srcOut)}/${pageName}/presenter/${pageName}Presenter.java" />

    <instantiate from="root/src/app_package/MVPModel.java.ftl"
                   to="${escapeXmlAttribute(srcOut)}/${pageName}/model/${pageName}Model.java" />
</#if>


</recipe>

3.template文件

<?xml version="1.0"?>
<template
    format="5"
    revision="5"
    name="MVPAutoActivity"
    minApi="9"
    minBuildApi="14"
    description="一键创建MVP架构的所需要的M、P、V文件">

    <category value="Activity" />
    <formfactor value="Mobile" />

    <parameter
        id="pageName"
        name="Page Name"
        type="string"
        constraints="unique|nonempty"
        default="Main"
        help="填写页面名称,如填写Main会自动生成MainActivity,MainPresenter,MainModel文件"
        />
    <parameter
        id="packageName"
        name="Root Package Name"
        type="string"
        constraints="package"
        default="net.ishandian.app"
        help="填写项目的包名"
        />
    
    <parameter
        id="activityLayoutName"
        name="Activtiy Layout Name"
        type="string"
        constraints="layout|nonempty"
        suggest="${activityToLayout(pageName)}"
        default="activity_main"
        help="填写创建的Activity的布局名称,若布局已经创建就直接填写此包名,没有创建,勾选下面选项"
        />
    <parameter
        id="generateActivityLayout"
        name="Generate Activity Layout"
        type="boolean"
        default="true"
        help="是否生成Activity的布局?若勾选,则用上面的布局作为Activity的布局"
        />
    <parameter
        id="activityPackageName"
        name="Activity Package Name"
        type="string"
        constraints="package"
        suggest="${packageName}.${pageName}.view"
        help="Activity 将被输出到此包下,请认真核实此包名是否是你需要输出的目标包名"
        />
    
    <parameter
        id="contractPackageName"
        name="Contract Package Name"
        type="string"
        constraints="package"
        suggest="${packageName}.${pageName}.contract"
        help="Contract 将被输出到此包下"
        />
    
    <parameter
        id="presenterPackageName"
        name="Presenter Package Name"
        type="string"
        constraints="package"
        suggest="${packageName}.${pageName}.presenter"
        help="Presenter 将被输出到此包下"
        />  


    <parameter
        id="modelPackageName"
        name="Model Package Name"
        type="string"
        constraints="package"
        suggest="${packageName}.${pageName}.model"
        help="Model 将被输出到此包下"
        />  
        
    <parameter
        id="isLauncher"
        name="Launcher Activity"
        type="boolean"
        default="false"
        help="If true, this activity will have a CATEGORY_LAUNCHER intent filter, making it visible in the launcher" />

    <parameter
        id="backwardsCompatibility"
        name="Backwards Compatibility (AppCompat)"
        type="boolean"
        default="true"
        help="If false, this activity base class will be Activity instead of AppCompatActivity" />
    

    <!-- 128x128 thumbnails relative to template.xml -->
    <thumbs>
        <!-- default thumbnail is required -->
        <thumb>template_blank_activity.png</thumb>
    </thumbs>

    <globals file="globals.xml.ftl" />
    <execute file="recipe.xml.ftl" />

</template>

4.MVPActivity.java

package ${activityPackageName};

import ${superClassFqcn};
import android.os.Bundle;

import ${contractPackageName}.${pageName}Contract;
import ${presenterPackageName}.${pageName}Presenter;

import ${packageName}.R;
<#if includeCppSupport!false>
import android.widget.TextView;
</#if>

public class ${pageName}Activity extends ${superClass} implements ${pageName}Contract.View{

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.${activityLayoutName});
<#include "../../../../common/jni_code_usage.java.ftl">
    }
<#include "../../../../common/jni_code_snippet.java.ftl">
}

5.MVPActivity.kt

package ${activityPackageName}

import ${superClassFqcn}
import android.os.Bundle
import ${contractPackageName}.${pageName}Contract
import ${presenterPackageName}.${pageName}Presenter

import ${packageName}.R

class ${pageName}Activity : ${superClass}(),${pageName}Contract.View {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.${activityLayoutName})

<#include "../../../../common/jni_code_usage.kt.ftl">
    }
<#include "../../../../common/jni_code_snippet.kt.ftl">
}

6.MVPContract.java

package ${contractPackageName};

public interface ${pageName}Contract {
    //对于经常使用的关于UI的方法可以定义到IView中,如显示隐藏进度条,和显示文字消息
    interface View {

    }
    //Model层定义接口,外部只需关心Model返回的数据,无需关心内部细节,即是否使用缓存
    interface Model{

    }
}

7.MVPCOntract.kt

package ${contractPackageName}

interface ${pageName}Contract {
    //对于经常使用的关于UI的方法可以定义到IView中,如显示隐藏进度条,和显示文字消息
    interface View

    //Model层定义接口,外部只需关心Model返回的数据,无需关心内部细节,即是否使用缓存
    interface Model

}

8.MVPModel.java

package ${modelPackageName};

import ${contractPackageName}.${pageName}Contract;


public class ${pageName}Model implements ${pageName}Contract.Model{
    
}

9.MVPModel.kt

package ${modelPackageName}

import ${contractPackageName}.${pageName}Contract

class ${pageName}Model constructor() :  ${pageName}Contract.Model{
    
}

10.MVPPresenter.java

package ${presenterPackageName};

import ${contractPackageName}.${pageName}Contract;


public class ${pageName}Presenter {
}

11.MVPPresenter.kt

package ${presenterPackageName}

class ${pageName}Presenter{
    
}