入口,MainActivity, 选择Activity+Fragment的格式;
展示的样式是,在一个Activity里面包含一个Fragment,不断点击,不断变换当前Fragment的的外观。
R.id.main_rb_af -> {
FragmentSampleActivity2.jump(this, 1)
}
初始化,启动,
private fun init1() {
vb.fs2.visibility = View.VISIBLE
vb.fs2Vp.visibility = View.GONE
val TAG = "ZFileListFragmentTag"
getZFileConfig().fragmentTag = TAG
/*supportFragmentManager
.beginTransaction()
.add(R.id.fs2, getZFragment(), TAG)
.commit()*/
** zfileInitAndStart(R.id.fs2, mListener)**
}
private var mListener: ZFragmentListener? = object : ZFragmentListener() {
.....}
mListener函数,监听有哪些文件被选中,获取具体的文件信息。用来获取选中的文件信息的。
private var mListener: ZFragmentListener? = object : ZFragmentListener() {
/**
* 文件选择
*/
override fun selectResult(selectList: MutableList<ZFileBean>?) {
Toast.makeText(this@FragmentSampleActivity2, "选中了${selectList?.size}个,具体信息查看log", Toast.LENGTH_SHORT).show()
Log.i("ZFileManager", "选中的值 ===>>> ")
selectList?.forEach {
Log.i("ZFileManager", it.toString())
}
finish()
}
/**
* 获取 [Manifest.permission.WRITE_EXTERNAL_STORAGE] 权限失败
* @param activity FragmentActivity
*/
override fun onSDPermissionsFiled(activity: FragmentActivity) {
Toast.makeText(this@FragmentSampleActivity2, "OPS,没有SD卡权限", Toast.LENGTH_SHORT).show()
}
/**
* 获取 [Environment.isExternalStorageManager] (所有的文件管理) 权限 失败
* 请注意:Android 11 及以上版本 才有
*/
override fun onExternalStorageManagerFiled(activity: FragmentActivity) {
Toast.makeText(this@FragmentSampleActivity2, "Environment.isExternalStorageManager = false", Toast.LENGTH_SHORT).show()
}
}
调用库函数:
/**
* 在 [FragmentActivity] 中 [FragmentActivity.onCreate] 使用 --->>> 仅支持 [ZFileListFragment] 嵌套 [FragmentActivity] 中使用
*/
fun FragmentActivity.zfileInitAndStart(id: Int, zFragmentListener: ZFragmentListener?) {
val fragment = ZFileListFragment.newInstance()
fragment.zFragmentListener = zFragmentListener
supportFragmentManager.beginTransaction()
.add(id, fragment, getZFileConfig().fragmentTag)
.commit()
}
文件库函数的实现:
关键类: ZFileListFragment
return ZFileListFragment().apply {
arguments = Bundle().run {
putString(FILE_START_PATH_KEY, newPath)
this
}
}
ZFileListFragment,只需要一个路径参数作为初始化
/**
* 文件管理 核心实现,可以 在 Activity、Fragment or ViewPager中使用
*
* 注意:使用 [FragmentManager] 或者 [ViewPager] 动态添加或直接嵌套使用时
* 1. 无法通过 [ZFileDsl] 获取返回的数据,其他配置将不受影响
* 2. 需在 Activity 中配置 [ZFragmentListener] 来接收选中的文件
* 3. Activity onBackPressed 方法 需要 调用 [onBackPressed]
* 4. Activity onResume 方法 需要调用 [showPermissionDialog]
*/
class ZFileListFragment : Fragment() {
........
}
ZFileListFragment:
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
vb = FragmentZfileListBinding.inflate(inflater, container, false)
return vb?.root
}
1.初始化界面
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
if (!getZFileConfig().needLazy) {
initAll()
}
}
2.如果不是懒加载,则在View创建完毕的时候,初始化initAll()
initAll函数做的工作,设置初始化的文件路径,检测是否有读取文件的权限,初始化UI
如果是有读取文件的权限,则进行文件路径信息的获取
3.文件路径信息的获取,初始化
private var rootPath = "" // 根目录
private var specifyPath: String? = "" // 指定目录
private var nowPath: String? = "" // 当前目录
set(value) {
field = value
getZFileHelp().setCurrentPath(value)
}
private fun initRV() {
hasPermission = true
setPermissionState(View.GONE)
vb?.zfileListRefreshLayout?.property {
getData(nowPath)
}
initPathRecyclerView()
initListRecyclerView()
}
初始化,initAll的时候,当前路径是设置为根路径
nowPath = rootPath;
4.获取当前路径下的所有文件信息
getData(nowPath)
ZFileUtil.getList(requireContext()) {
if (isNullOrEmpty()) {
..............................
} else {
vb?.zfileListRefreshLayout?.isRefreshing = false
**fileListAdapter?.setDatas(this)**
vb?.zfileListListRecyclerView?.scrollToPosition(0)
setEmptyState(View.GONE)
setDoState(View.GONE)
}
}
返回的文件信息,用MutableList<ZFileBean>表示
internal object ZFileUtil {
/**
* 获取文件
*/
fun getList(context: Context, block: MutableList<ZFileBean>?.() -> Unit) {
ZFileListAsync(context, block).start(getZFileConfig().filePath)
}
----
}
internal class ZFileListAsync(
context: Context,
block: MutableList<ZFileBean>?.() -> Unit
) : ZFileAsync(context, block) {
override fun doingWork(filePath: String?) =
getZFileHelp().getFileLoadListener().getFileList(getContext(), filePath)
}
/**
* 更方便的去获取符合要求的数据
*/
open class ZFileAsync(
private var context: Context,
private var block: MutableList<ZFileBean>?.() -> Unit
) {
/**
* 获取数据
* @param filterArray 过滤规则
*/
fun start(filterArray: Array<String>) {
doStart()
async {
sendMessage(OTHER, doingWork(filterArray)) //这段代码在第三方线程中执行----(1)
}
}
//private var block: MutableList<ZFileBean>?.() -> Unit
private fun onPostExecute(list: MutableList<ZFileBean>?) {
destory()
block.invoke(list) //handler获取到文件信息之后,执行block代码,这时候,执行的是UI线程---(2)
onPostExecute()
}
/**
* 获取数据
* @param filterArray 过滤规则
*/
protected open fun doingWork(filterArray: Array<String>): MutableList<ZFileBean>? {
return null
}
.......
}
internal fun async(block: () -> Unit) {
getZFileHelp().getPoolExecutor().execute(object : Thread() {
override fun run() {
block()
}
})
}
5.获取当前路径下的所有文件信息,具体实现:
override fun doingWork(filePath: String?) =
getZFileHelp().getFileLoadListener().getFileList(getContext(), filePath)
/**
* 文件数据获取
*/
private var fileLoadListener: ZFileLoadListener = ZFileDefaultLoadListener()
internal fun getFileLoadListener() = fileLoadListener
/**
* 完全自定义 获取文件数据 (可通过 [File.toZFileBean] 自动转换数据)
*/
interface ZFileLoadListener {
/**
* 获取手机里的文件List
* @param filePath String 指定的文件目录访问,空为SD卡根目录
* @return MutableList<ZFileBean>? list
*/
fun getFileList(context: Context?, filePath: String?): MutableList<ZFileBean>?
}
internal class ZFileDefaultLoadListener : ZFileLoadListener {
/**
* 获取手机里的文件List
* @param filePath String? 指定的文件目录访问,空为SD卡根目录
* @return MutableList<ZFileBean>? list
*/
override fun getFileList(context: Context?, filePath: String?) =
getDefaultFileList(context, filePath)
private fun getDefaultFileList(context: Context?, filePath: String?): MutableList<ZFileBean> {
val path = if (filePath.isNullOrEmpty()) SD_ROOT else filePath
val config = getZFileConfig()
val list = arrayListOf<ZFileBean>()
val listFiles = path.toFile().listFiles(
ZFileFilter(
config.fileFilterArray,
config.isOnlyFolder,
config.isOnlyFile
)
)
if (listFiles.isNullOrEmpty()) return list
for (it in listFiles) {
if (it.path == SAF_DATA_PATH || it.path == SAF_OBB_PATH) {
if (config.showDataAndObbFolder) {
addFileToList(config, list, it)
} else {
continue
}
} else {
addFileToList(config, list, it)
}
}
ZFileSth.sortord(list)
return list
}
private fun addFileToList(
config: ZFileConfiguration,
list: MutableList<ZFileBean>,
file: File
) {
if (config.showHiddenFile) {
list.add(file.toZFileBean())
} else {
if (!file.isHidden) {
list.add(file.toZFileBean())
}
}
}
}