没错,Butter Knife 就是 大名鼎鼎的 Android 大神 Jake Wharton 开源的View 注入框架 ,在过去的两年里,赢得了近万人的点赞,近两千人建立了代码分支。配合着Android Studiobutterknife-zelezny 插件的使用极大的提高了Android 项目的开发效率,先让我们看一看 butterknife-zelezny 的辉煌表现吧
仅仅几秒钟的时间,就可以将布局 中所有声明了ID的控件全部生成变量并绑定到相应的View 上。 虽然注解的方式也受性能的诟病,但是相比起 findViewByid的痛苦及开发效率的提升这简直不值一提,相信不少程序员为了妥协无知产品经理定下的工期(没错是产品定下的工期)而选择了 Butter Knife,当然,我相信也有一些朋友是为了所谓的代码的优雅。
无论怎样,做为时代的产物,Butter Knife 已经深深嵌进了成千上万个Android应用项目中。
在我开发的项目中,同样也使用了这个东西,当然,我使用Butter Knife的初衷不是因为 代码的优雅,而是为了应付瞬息万变的产品需求与落后的开发速度之间的矛盾。
直到有一天,突然有这样一个需求:把整个项目打包成SDK。
打包成SDK给自己用本来是没有什么的,无非就是 把 build.gradle 的插件换一下而已。
apply plugin: 'com.android.library' //apply plugin: 'com.android.application'然而,如果这个SDK 是给别人用的,那么问题就来了,把一个55K的 Butter Knife jar 包 放到 这里面,仅仅是为了替代findViewById,这不管怎么说都会让人觉得有些奇怪。
事实证明,我要立刻减少对Butter Knife 的依赖,好在已经有善良的朋友为万能的AndroidStudio 开发了一套新的插件
https://github.com/boredream/BorePlugin 到目前为止,我也没有明白这位仁兄为什么把这个项目叫 BorePlugin 不过这并不影响我们使用。让我们见识一下真正的生产力工具吧。
可是,以前的项目怎么办呢?想想一个一个的去改都头大了!但是,做为一个优秀的工程师,决不能忍受这样的痛苦,为此,有朋友为我们准备好了修改项目的 python 脚本 。配置好你的python 环境。把这个脚本放到项目目录下,运行脚本,很快@BindView
标签 全变成了 标准的 findViewByid
# -*- coding: utf-8 -*-
import os
import re
# CLASS_NAME_PATTERN = re.compile('')
BUTTER_KNIFE_PATTERN = re.compile('(ButterKnife.bind\(.*?,*\s*(.*)\);)')
BIND_PATTERN = re.compile('(@Bind\((.*?)\)\s*(.*?)\s+(.*?);)')
CLICK_PATTERN = re.compile('(@OnClick\(\s*\{?(.*?)\}\s*\))')
FIND_VIEW_FORMAT_WITH_VIEW = ' %s = (%s) %sfindViewById(%s);\n'
# FIND_VIEW_FORMAT = ' %s = (%s) findViewById(%s);\n'
SET_CLICK_FORMAT = ' %s.setOnClickListener(this);\n'
SET_CLICK_FORMAT_BY_FIND_VIEW = ' %sfindViewById(%s).setOnClickListener(this);\n'
def insert_find_view_method(source, add):
pos = source.rfind('}')
changed = source[:pos] + add
if pos + 1 < len(source): # not last
changed += source[pos + 1:]
return changed
def get_click_str(binds, click_id, view):
for i in binds:
if click_id == i[1].replace(' ', ''):
return str.format(SET_CLICK_FORMAT % (i[3]))
return str.format(SET_CLICK_FORMAT_BY_FIND_VIEW % (view, click_id))
def replace_butter_knife(java_path):
with open(java_path) as java_file:
content = java_file.read()
butters = BUTTER_KNIFE_PATTERN.findall(content)
m_view = ""
if butters:
butter = butters[0]
# print butter
content = content.replace(butter[0], "initView();")
if butter[0].find(',') != -1 and butter[1]:
m_view = butter[1].split(',')[1].replace(" ", "") + '.'
binds = BIND_PATTERN.findall(content)
init_method = '\n private void initView() {\n'
for bind in binds:
view_id = bind[1]
view_type = bind[2]
view_filed = bind[3]
content = content.replace(bind[0], 'private'+" "+view_type + " " + view_filed + ";")
# if m_view:
init_method += str.format(FIND_VIEW_FORMAT_WITH_VIEW % (view_filed, view_type, m_view, view_id))
# else:
# init_method += str.format(FIND_VIEW_FORMAT % (view_filed, view_type, view_id))
onclick = CLICK_PATTERN.findall(content)
if onclick:
content = content.replace(onclick[0][0], '@Override')
click_ids = onclick[0][1].replace(' ', '').split(',')
for click_id in click_ids:
# print click_id
init_method += get_click_str(binds, click_id, m_view)
init_method += " }\n}"
content = insert_find_view_method(content, init_method)
java_file.close()
new = open(java_path, "wb")
new.write(content)
new.close()
print os.path.split(java_path)[1] + " DONE"
# print content
if __name__ == '__main__':
current_path = os.getcwd()
input_path = ''
input_path = raw_input(r'press enter to start replace butter knife')
if input_path == '':
for root, dirs, files in os.walk(current_path):
for f in files:
if os.path.splitext(f)[1] == '.java':
replace_butter_knife(os.path.join(root, f))
脚本下载地址 http://download.csdn.net/download/github_14899071/9522171
然而,这对于不了解 python 的朋友无疑是一场灾难!安装python 环境,还要学着运行python 命令,想想就够了。
时间总是能带给人们意想不到的惊喜,就在几天前,没错,几天前,有大神开源了一款AndroidStudio 插件神器,现在,你不再需要python 基础,不需要python 环境,也不需要python 脚本。你只要会安装AndroidStudio 插件就可以 RemoveButterKnife,从此和 Butter Knife 说再见 了!
让我们见识一下吧!
更重要的是
没错,作者看起来像个中国人
深受Butter Knife之害的朋友,快来体验一下 https://github.com/u3shadow/RemoveButterKnife 吧。