递归遍历Android DocumentFile目录树时listFiles()始终返回根目录文件问题排查
问题根因
- 核心错误是递归时误用了
DocumentFile.fromTreeUri()方法:该方法仅用于解析从系统文件选择器ACTION_OPEN_DOCUMENT_TREE返回的根目录URI,传入任意子文件/子文件夹的URI时,该方法都会自动回溯到整棵目录树的根节点,导致每次调用listFiles()都返回根目录的文件列表。
修复方案
推荐直接传递DocumentFile对象递归,避免URI来回转换带来的额外开销和错误,修改后代码如下:
1. 修改WalkTree方法入参和逻辑
private void WalkTree(DocumentFile dirFile) { Log.d( TAG, "当前遍历目录: " + dirFile.getName() ); DocumentFile files[] = dirFile.listFiles(); if( files == null ) { Log.d( TAG, "files is null in LoadFileList()" ); return; } for( DocumentFile f : files ) { if( f.isDirectory() ) { Log.d( TAG, "FOLDER: " + f.getName()); if( f.getName().toLowerCase().contains("lost.dir") ) { Log.d( TAG, "IGNORE LOST.DIR"); } else { // 直接传递子目录DocumentFile对象递归 WalkTree(f); } } else { Log.d( TAG, "FILE: " + f.getName()); } } }
2. 修改onActivityResult调用逻辑
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode,resultCode,data); if(resultCode == RESULT_OK && requestCode == RQS_OPEN_DOCUMENT_TREE){ Uri uriTree = data.getData(); Log.d(TAG, "WalkTree根URI: " + uriTree.toString() ); DocumentFile rootDir = DocumentFile.fromTreeUri(this, uriTree); if (rootDir != null && rootDir.isDirectory()) { WalkTree(rootDir); } } }
额外注意事项
- 遍历大容量存储设备时需放到子线程执行,避免阻塞UI触发ANR
- 若必须通过URI传递子目录,递归时请使用
DocumentFile.fromSingleUri(context, 子目录URI)替代fromTreeUri,但该方案性能低于直接传递DocumentFile对象
内容的提问来源于stack exchange,提问作者SparkyNZ
相关产品推荐
相关产品推荐

