隨著公司的并行項(xiàng)目越來(lái)越多粮坞,Android新項(xiàng)目初始化的變成一個(gè)問(wèn)題,一開(kāi)始是每個(gè)人建立項(xiàng)目不一樣侥猩,為此設(shè)計(jì)了清單列表。后來(lái)發(fā)現(xiàn)項(xiàng)目是一致了抵赢,但是每次都要手動(dòng)執(zhí)行列表欺劳,大部分都是簡(jiǎn)單地新建文件,很無(wú)聊铅鲤,而且偶爾思想開(kāi)個(gè)小差划提,還出錯(cuò),又要找問(wèn)題邢享、修bug鹏往,煩~。
都說(shuō)懶惰是程序員的優(yōu)良品質(zhì)驼仪,所以決定研究一下怎么自動(dòng)化整個(gè)過(guò)程掸犬。
需求
經(jīng)過(guò)分析,發(fā)現(xiàn)這里面最核心需求有兩個(gè):
- 根據(jù)模板java文件生成最終的java文件绪爸,主要是替換
類名
、包名
和app包名
宙攻; - 根據(jù)包名規(guī)則生成相應(yīng)的文件夾奠货。
其中涉及的流程有:
- 讀取、解析配置文件座掘;
- 根據(jù)名稱递惋,生成相應(yīng)的文件夾柔滔;
- 根據(jù)模板文件,生成文件夾下相應(yīng)的文件萍虽;
涉及的技術(shù)點(diǎn)有:
- 配置文件的格式用什么好睛廊?
- 怎么解析配置文件?
技術(shù)點(diǎn)1:配置文件的格式用什么好杉编?
經(jīng)過(guò)分析超全,考慮擴(kuò)展性和簡(jiǎn)潔程序,決定json來(lái)寫(xiě)配置邓馒。
方案一:json和文件(夾)的層級(jí)結(jié)構(gòu)保持一致嘶朱。
- type:這一層級(jí)的類型:
-
dir
: 表示文件夾 -
file
: 表示文件
- 如果 type為dir,則需要定義:
-
name
:文件夾的名字 -
list
:子文件(夾)列表 -
package_name
:包名光酣。默認(rèn)為 父級(jí)文件夾名字和自身文件夾的名字的疊加疏遏。
- 如果 type為file,則需要定義:
-
name
:文件的名字 -
template
:模板文件的名字
這樣一個(gè)配置兩個(gè)文件的json如下:
{
"type":"dir",
"name":"baby",
"list":[
{
"type":"dir",
"name":"view",
"list":[
{
"type":"file",
"name":"BabyFragment",
"template":"BaseFragment.java.tpl"
},
{
"type":"file",
"name":"MorningCheckFragment",
"template":"BaseFragment.java.tpl"
}
]
}
]
}
才兩個(gè)文件救军,就有三層嵌套财异,就算是增加同包文件,都要增加三行唱遭,太繁瑣了宝当。換一種思路:
方案二:根據(jù)模板、包名胆萧,把同一個(gè)包名下的同一個(gè)模板的文件匯總在一起
- 第一層:
-
app_id
: 應(yīng)用包名 -
list
: 模板新建列表
- 第二層:模板新建列表項(xiàng)
-
package_name
: 對(duì)應(yīng)的包名 -
template
: 采用的模板 -
fileList
: 需要新建的文件列表
這樣json變成如下:
{
"app_id":"panda.android.test",
"list":[
{
"package_name":"panda.android.test",
"template":"BaseFragment.java.tpl",
"fileList":[
"BabyFragment",
"MorningCheckFragment"
]
}
]
}
簡(jiǎn)單直觀很多庆揩。
怎么解析配置文件?
這里當(dāng)然選擇強(qiáng)大易用的Python了跌穗。
Python字符串替換的3種方法:
1. 字符串替換
將需要替換的內(nèi)容使用格式化符替代订晌,后續(xù)補(bǔ)上替換內(nèi)容;
template = "hello %s , your website is %s " % ("簡(jiǎn)書(shū)","http://www.reibang.com/")
print(template)
也可使用format函數(shù)完成:
template = "hello {0} , your website is {1} ".format("簡(jiǎn)書(shū)","http://www.reibang.com/")
print(template)
2. 字符串命名格式化符替換
使用命名格式化符蚌吸,這樣锈拨,對(duì)于多個(gè)相同變量的引用,在后續(xù)替換只用申明一次即可羹唠;
template = "hello %(name)s 奕枢,your name is %(name), your website is %(message)s" %{"name":"簡(jiǎn)書(shū)","message":"http://www.reibang.com/"}
print(template)
使用format函數(shù)的語(yǔ)法方式:
template = "hello {name} , your name is {name}, your website is {message} ".format(name="大CC",message="http://blog.me115.com")
print(template)
3. 模版方法替換
使用string中的Template方法;
from string import Template
tempTemplate = string.Template("Hello $name ,your website is $message")
print(tempTemplate.substitute(name='大CC',message='http://blog.me115.com'))
有了模版方法后佩微,就可以將模版保存到文件單獨(dú)編輯缝彬,在生成的地方替換為需要的變量。
樣例代碼
- BaseFragment.java.tpl如下:
package ${PACKAGE_NAME};
import ${ANDROID_APP_ID}.R;
import panda.android.lib.base.ui.fragment.BaseFragment;
/**
* Created on ${DATA}.
*/
public class ${CLASS_NAME} extends BaseFragment{
@Override
public int getLayoutId() {
return R.layout.fragment_net;
}
}
- 配置文件如下:
{
"app_id":"panda.android.test",
"list":[
{
"package_name":"panda.android.test",
"template":"BaseFragment.java.tpl",
"fileList":[
"BabyFragment",
"MorningCheckFragment"
]
}
]
}
- 腳本如下:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os,sys,re,traceback
from datetime import datetime
from string import Template
import json
def generateAndroidJavaCode(app_id, package_name, template, fileName):
className = fileName;
path = "./" + package_name.replace('.','/');
filePath = r'%s/%s.java' % (path,className)
if os.path.exists(path) == False:
os.makedirs(path)
class_file = open(filePath,'w')
lines = []
#模版文件
template_file = open(r'BaseFragment.java.tpl','r')
tmpl = Template(template_file.read())
#模版替換
lines.append(tmpl.substitute(
PACKAGE_NAME = package_name,
ANDROID_APP_ID = app_id,
DATA = datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
CLASS_NAME = className))
# 0.將生成的代碼寫(xiě)入文件
class_file.writelines(lines)
class_file.close()
print 'generate %s over. ~ ~' % filePath
## 1. 解析配置文件
configuration = """
{
"app_id":"panda.android.test",
"list":[
{
"package_name":"panda.android.test",
"template":"BaseFragment.java.tpl",
"fileList":[
"BabyFragment",
"MorningCheckFragment"
]
}
]
}
"""
configurationJson = json.loads(configuration);
## 2. 按照模板生成對(duì)應(yīng)的文件
app_id = configurationJson["app_id"]
for filesInfo in configurationJson["list"]:
package_name = filesInfo["package_name"]
template = filesInfo["template"]
for fileName in filesInfo["fileList"]:
generateAndroidJavaCode(app_id, package_name, template, fileName);
-
最后生成的文件如下:
引用
Panda
2016-07-04