AndroidStudio为我们提供了针对无用res检查的工具: Lint
Lint可以帮我们检索项目中可能存在错误的地方,平时功能代码写完后,也建议大家用其检查一下代码,帮助我们提高代码的健壮性。但这里主要介绍脚本,就不介绍Lint的使用了。
在一些大一点的项目,Lint在执行之后会Run很长时间,且只是给你找出问题点。在瘦身时可能存在一定量的res需要剔除,用Lint检查起来就会相对慢一些,且有些Code删除之后我们也需要重新检查其是否有引用哪些layout、drawable等,这些也是可以一并检查删除的。
下面是脚本代码,实现起来相对简单暴力,直接放在Android项目下运行即可。
# coding=utf-8
import fnmatch
import os
import subprocess
from typing import Sequence
def run_command(command, project_dir):
subprocess.check_call(command, cwd=project_dir)
def run_gradle_clean(project_dir):
command = ['./gradlew', 'clean']
run_command(command, project_dir)
print(f"Run gradle clean successfully! ==========")
def file_split(split_url):
import os
(parent_path, file_name) = os.path.split(split_url)
(shot_name, extension) = os.path.splitext(file_name)
if split_url.endswith('.9.png'):
return parent_path, file_name, file_name.split(".")[0], '.9.png'
else:
return parent_path, file_name, shot_name, extension
# 驼峰 + 首字母大写
def hump_with_upper_primary(text):
arr = filter(None, text.lower().split('_'))
res = ''
j = 0
for i in arr:
# if j == 0:
# res = i
# else:
res = res + i[0].upper() + i[1:]
j += 1
return res
# 驼峰 + 首字母小写
def hump_with_lower_primary(text):
arr = filter(None, text.lower().split('_'))
res = ''
j = 0
for i in arr:
if j == 0:
res = i
else:
res = res + i[0].upper() + i[1:]
j += 1
return res
def _res_files(_root: str) -> Sequence[str]:
for _base, _, _files in os.walk(_root):
yield from (os.path.join(_base, file) for file in _files if
'/res/' in _base or file == 'AndroidManifest.xml' and 'build' not in _base and 'node_modules' not in _base)
def fuck_unused_normal(_check_dir, _type, _file_shot_name):
if '-' in _type:
_type = _type.split('-')[0]
r_string1 = 'R.' + _type + '.' + _file_shot_name
r_string2 = '@' + _type + '/' + _file_shot_name
for _root, _dirs, _files in os.walk(_check_dir):
for name in _files:
if not match_patterns(file_split(name)[1], check_file_end_fix):
continue
check_file_path = os.path.join(_root, name)
with open(check_file_path, encoding='utf-8') as f:
_content = f.read()
if r_string1 in _content or r_string2 in _content:
# 该文件被其他文件引用了
return True
return False
def fuck_unused_layout(_check_dir, _type, _file_shot_name) -> bool:
r_string1 = 'R.' + _type + '.' + _file_shot_name
r_string2 = '@' + _type + '/' + _file_shot_name
r_string3 = hump_with_upper_primary(_file_shot_name) + 'Binding'
r_string4 = 'kotlinx.android.synthetic.main.' + _file_shot_name
for _root, _dirs, _files in os.walk(_check_dir):
for name in _files:
if not match_patterns(file_split(name)[1], check_file_end_fix):
continue
check_file_path = os.path.join(_root, name)
with open(check_file_path, encoding='utf-8') as f:
_content = f.read()
if (r_string1 in _content
or r_string2 in _content
or r_string3 in _content
or r_string4 in _content):
# 该文件被其他文件引用了
return True
return False
def match_patterns(_file, _patterns):
for _pattern in _patterns:
if fnmatch.fnmatch(_file, _pattern):
return True
return False
def handle_res_list_check_and_remove(_res_path):
res_list = []
for _dir in os.listdir(_res_path):
if match_patterns(_dir, res_type_list):
res_list.append(_dir)
for res_type in res_list:
type_dir = os.path.join(_res_path, res_type)
for file_name in os.listdir(type_dir):
if file_name in ignore_prefix:
continue
file_path = os.path.join(type_dir, file_name)
shot_name = file_split(file_name)[2]
if 'layout' in res_type:
is_ref = fuck_unused_layout(CWD, 'layout', shot_name)
if not is_ref:
print(f'remove {file_path}')
os.remove(file_path)
else:
is_ref = fuck_unused_normal(CWD, res_type, shot_name)
if not is_ref:
print(f'remove {file_path}')
os.remove(file_path)
ignore_root = ['*mjbNormal*', '*mjbForTest*'] # 忽略检查这些文件下是否存在目标资源
ignore_prefix = [] # 忽略的文件
check_file_end_fix = ['*.xml', '*.java', '*.kt'] # 在哪些文件中检查是否有引用目标文件
res_type_list = ['anim*', 'drawable*', 'mipmap*'] # res下哪些资源是可以被当成目标文件的,目标文件会被检查删除
CWD = os.getcwd() # 项目路径
if __name__ == '__main__':
run_gradle_clean(CWD)
for root, dirs, files in os.walk(CWD):
if match_patterns(root, ignore_root):
continue
if root.endswith('/res'):
handle_res_list_check_and_remove(root) # root是项目中各级的res文件路径
食用方式
python3 remove_unused_res.py
可能会有水土不服的情况,使用者可以具体问题具体处理
本文介绍了如何使用Python脚本在AndroidStudio项目中快速检查和删除无用的资源,如layout、drawable和mipmap,以提高代码健壮性和项目性能。脚本通过遍历资源目录,检查文件引用并执行Gradleclean来实现资源剔除。
208

被折叠的 条评论
为什么被折叠?



