ButterKnife弃坑脚本

背景

ButterKnife虽然帮助我们省去了繁琐的findViewById(),使用起来非常的快捷方便,但是有利必然也有弊,ButterKnife在编译期间会额外生成class文件,对App的方法数增加贡献不小,并且在library module中使用ButterKnife有着诸多不便,因此项目优化弃坑ButterKnife势在必行。

脚本说明

(1)解析@BindView注解得到view id,并在ButterKnife.bind调用处生成findViewById,从而达到替换效果。
(2)支持指定目录参数,遍历目录,递归替换,脚本运行完后需要手动清除imports。
(3)暂不支持替换@OnClick注解。
(4)console输出文件完成状态。

Example

sky:~ sky$ python replace_butterknife.py DiscountStartShowController.java

脚本code

#!/usr/bin/env python
# by sky
 
import os, sys, re
 
butter_knife_egx = re.compile('.*@BindView\(R[2]?.id.(.*)\)')
view_define_egx = re.compile('\s*(.*)\s+(.*);')
butter_bind_egx = re.compile('\s*ButterKnife.bind\([^,]+[,]?\s*(.*)\);')
 
def convert(file):
  butterknifeline = False
  view_id = None
  list = file.readlines()
  new_list = []
  findview_lines = []
 
  for index in range(len(list)):
    line = list[index]
    if butterknifeline:
      result = view_define_egx.match(line)
      if result:
 
        # private TextView tvTitle
        view_define_line = '\t' + 'private ' + result.group(1) + ' ' + result.group(2) + ';\n'
 
        # tvTitle = findViewById(R.id.tv_title)
        new_line = '\t' + result.group(2) + ' = '
        if result.group(1) != 'View':
          new_line += '(' + result.group(1) + ')'
 
        new_line += 'findViewById(R.id.' + view_id +');\n'
 
        findview_lines.append(new_line)
        new_list.append(view_define_line)
        butterknifeline = False
      else:
        new_list.append(line)
    else:
      m = butter_knife_egx.match(line)
      if m:
        view_id = m.group(1)
        butterknifeline = True
      elif len(findview_lines) > 0:
        m = butter_bind_egx.match(line)
        if m:
          parent_view = m.group(1)
          create_findviewbyid(new_list, findview_lines, parent_view)
          findview_lines = []
        else:
          new_list.append(line)
      else:
        new_list.append(line)
 
  file.seek(0)
  file.writelines(new_list)
 
 
# tvTitle = view.findViewById(R.id.tv_title)
def create_findviewbyid(new_list, findview_lines, parent_view):
  for line in findview_lines:
    if parent_view:
      line = line.replace('findViewById', parent_view + '.findViewById')
    new_list.append(line)
 
 
# recurse replace butter knife
def convert_recurse(path_name):
  if os.path.isfile(path_name):
    if not path_name.endswith('.java'):
      return
    with open(path_name, 'r+') as f:
      convert(f)
      print path_name + ' is done'
  elif os.path.isdir(path_name):
    for file_name in os.listdir(path_name):
      convert_recurse(path_name + '/' + file_name)
  else:
    print path_name + ' is invalid'
 
 
if __name__ == "__main__":
 
  if len(sys.argv) < 2:
    print 'args error'
    quit()
 
  path_name = sys.argv[1]
  convert_recurse(path_name)

你可能感兴趣的:(Android开发,Python)