<b>對(duì)模板工程的改造有可能造成 Android Studio 更新失敗抚恒!</b>*
最近我從 1.5 -> 1.5.1 更新失敗咱台,就是對(duì)模板工程的改造造成了沖突!
<p>
中午 @drakeet 秀了一波他改造的兩個(gè)小模板俭驮,另外還發(fā)了幾張官方自帶模板的本地位置圖片回溺,我也跟著改造了一把。
添加自定義 Templates
自定義的位置入口在這兒:
然后混萝,選擇 Templates 按 + 就可以一步步操作啦遗遵。
Description 處有些很有用的說(shuō)明,這里指出了多個(gè)占位符號(hào)逸嘀,可以在根據(jù)模板類生成具體的類時(shí)替換成合適的字符车要。
- 靜態(tài)內(nèi)部類實(shí)現(xiàn)的單例。
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end
#parse("File Header.java")
public class ${NAME}{
public static ${NAME} getInstance() {
return ${NAME}Holder.sInstance;
}
private ${NAME}() {
}
private static class ${NAME}Holder {
private static final ${NAME} sInstance = new ${NAME}();
}
}
- BaseAdapter崭倘,引入 provideItemLayout() 方法是為了解決 R 文件引入的包名問(wèn)題翼岁,ViewHolder.bind(Object) 可以將 UI 和數(shù)據(jù)綁定放在一起类垫。
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end
import android.content.Context;
import android.support.annotation.LayoutRes;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import java.util.List;
#parse("File Header.java")
public class ${NAME} extends BaseAdapter {
private Context ctx;
private List<Object> objects;
public ${NAME}(Context ctx, List<Object> objects) {
this.ctx = ctx;
this.objects = objects;
}
private @LayoutRes int provideItemLayout() {
// todo
return 0;
}
@Override
public int getCount() {
return objects == null ? 0 : objects.size();
}
@Override
public Object getItem(int position) {
return objects.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = LayoutInflater.from(ctx).inflate(provideItemLayout(), parent, false);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.bind(objects.get(position));
return convertView;
}
public static class ViewHolder {
public ViewHolder(View convertView) {
// todo
}
public void bind(Object o) {
// todo
}
}
}
- RecyclerView Adapter
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end
import android.content.Context;
import android.support.annotation.LayoutRes;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.List;
#parse("File Header.java")
public class ${NAME} extends RecyclerView.Adapter<${NAME}.ViewHolder> {
private Context ctx;
private List<Object> objects;
public ${NAME}(Context ctx, List<Object> objects) {
this.ctx = ctx;
this.objects = objects;
}
private
@LayoutRes
int provideItemLayout() {
// todo
return 0;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(ctx).inflate(provideItemLayout(), parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.bind(objects.get(position));
}
@Override
public int getItemCount() {
return objects == null ? 0 : objects.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View itemView) {
super(itemView);
//todo
}
public void bind(Object o) {
// todo
}
}
}
改造 gradle-projects
在添加了幾個(gè)自定義的 Templates 之后,我想能不能去改造一下整個(gè) project琅坡,讓它自動(dòng)幫我們創(chuàng)建更多的文件悉患、配置更多的內(nèi)容。
我曾經(jīng)想改造一下榆俺,但是沒有 Google 到方法售躁,然后我創(chuàng)建了一個(gè)工程,把必須要的依賴啊茴晋、包啊陪捷、類啊都配置好,想要以后再新建工程時(shí)直接 copy 一份然后修改包名就行了晃跺,后來(lái)我發(fā)現(xiàn)改包名太累揩局,放棄了。
以下就是手術(shù)過(guò)程掀虎。
找到模板工程位置:
AndroidStudio\plugins\android\lib\templates\gradle-projects
這個(gè)下面有多個(gè)文件夾凌盯,一看名字就知道是干啥的。
改造前請(qǐng)先備份烹玉!
改造前請(qǐng)先備份驰怎!
改造前請(qǐng)先備份!
</p>
先看 NewAndroidProject 有什么可以改造的沒有
研究了一下這個(gè)目錄下的文件二打,我發(fā)現(xiàn)最重要的是recipe.xml.ftl
這個(gè)文件县忌,它描述了工程創(chuàng)建過(guò)程應(yīng)該做些什么,copy 操作是簡(jiǎn)單的復(fù)制继效,instantiate 操作是實(shí)例化症杏,AS 除了生成一些變量替換掉占位符,還會(huì)插入一些內(nèi)容瑞信。globals.xml.ftl
則定義了一些常量厉颤。據(jù)此,我們可以修改的文件是
NewAndroidProject\root\project_ignore
和 NewAndroidProject\root\local.properties.ftl
凡简,前者是整個(gè)工程的 ignore 文件逼友,可以在 https://www.gitignore.io 生成一份拷貝進(jìn)去,后者我們可以定義一些密碼之類的(要確保該文件不會(huì)加入版本控制系統(tǒng))秤涩。
接下來(lái)看看 NewAndroidModule 有什么可以改造的沒有
根據(jù)前面的經(jīng)驗(yàn)帜乞,先研究一下 recipe.xml.ftl
這個(gè)文件,有以下發(fā)現(xiàn):
- 第 4 行的 dependency 定義 appcompat-v7
- 第 14 行實(shí)例化了 build.gradle
- 第 19 行創(chuàng)建了 drawable 文件夾
- 第 33 行拷貝了 module 的 ignore
- 第 37 行生成了 proguard 文件
- 第 55 行生成了 res/value/strings.xml
繼續(xù)研究 NewAndroidModule\root
下的文件筐眷。
- build.gradle.ftl 是 module 的 build.gradle 模板黎烈,我想提前做點(diǎn)配置進(jìn)去。我比較疑惑的是第 65 行的
<#if dependencyList?? >
,這里看起來(lái)是某個(gè)地方定義了一個(gè)依賴列表,但是并沒有發(fā)現(xiàn)∷磐ǎ回過(guò)頭去看recipe.xml.ftl
,它的第 4 行是<dependency mavenUrl="com.android.support:appcompat-v7:${buildApi}.+"/>
肉拓,我猜測(cè)可能這就是定義的地方,于是在這后面仿寫了一句<dependency mavenUrl="com.jakewharton:butterknife:7.0.1"/>
梳庆,創(chuàng)建工程驗(yàn)證確實(shí)如我所猜測(cè)的那樣暖途。 - module_ignore 最簡(jiǎn)單,根據(jù)我們的需要再添加一些語(yǔ)句就行
- proguard-rules.txt.ftl 會(huì)被實(shí)例化到 proguard-rules.pro膏执,可以根據(jù)對(duì)
build.gradle.ftl
的修改適當(dāng)修改
還可以繼續(xù)改造的是:自動(dòng)生成一些包驻售,讓程序架構(gòu)更清晰,先把架子搭起來(lái)嘛更米。