FileObserver递归监听目录(解决无法监听目录的创建、删除问题)

    xiaoxiao2021-04-04  35

    FileObserver递归监听目录解决无法监听目录的创建删除问题 主要内容总结

    FileObserver递归监听目录(解决无法监听目录的创建、删除问题)

    主要内容

    为了解决Android媒体数据库更新不及时的问题,我想打算通过FileObserver监听SD卡根目录下所有文件的变化,然后根据文件的变化对Android媒体数据库进行更新。而FileObserver无法做到递归监听。通过参考FileObserver 研究及其递归监听初步实现这篇博客,在其基础上,主要解决了几个问题:

    无法监听目录的创建、删除开启监听之后,新创建的目录无法监听冗余注册监听的问题

    冗余注册监听我是通过用ArrayMap键值对来解决的,以监听目录的绝对路径作为key,以监听器作为value。(也可以使用ArraySet集合实现)而开启监听之后,新创建的目录无法监听的问题则是通过监听FileObserver.CREATE事件,当创建新目录且该目录还没注册监听时,就注册并启动监听。 接下来,干货来了,代码如下:

    public class RecursiveFileObserver extends FileObserver { Map<String, SingleFileObserver> mObservers; String mPath; int mMask; public RecursiveFileObserver(String path) { this(path, ALL_EVENTS); } public RecursiveFileObserver(String path, int mask) { super(path, mask); mPath = path; mMask = mask; } @Override public void startWatching() { if (mObservers != null) return ; mObservers = new ArrayMap<>(); Stack stack = new Stack(); stack.push(mPath); while (!stack.isEmpty()) { String temp = (String) stack.pop(); mObservers.put(temp, new SingleFileObserver(temp, mMask)); File path = new File(temp); File[] files = path.listFiles(); if (null == files) continue; for (File f: files) { // 递归监听目录 if (f.isDirectory() && !f.getName().equals(".") && !f.getName() .equals("..")) { stack.push(f.getAbsolutePath()); } } } Iterator<String> iterator = mObservers.keySet().iterator(); while (iterator.hasNext()) { String key = iterator.next(); mObservers.get(key).startWatching(); } } @Override public void stopWatching() { if (mObservers == null) return ; Iterator<String> iterator = mObservers.keySet().iterator(); while (iterator.hasNext()) { String key = iterator.next(); mObservers.get(key).stopWatching(); } mObservers.clear(); mObservers = null; } @Override public void onEvent(int event, String path) { int el = event & FileObserver.ALL_EVENTS; switch (el) { case FileObserver.ATTRIB: Log.i("RecursiveFileObserver", "ATTRIB: " + path); break; case FileObserver.CREATE: File file = new File(path); if(file.isDirectory()) { Stack stack = new Stack(); stack.push(path); while (!stack.isEmpty()) { String temp = (String) stack.pop(); if(mObservers.containsKey(temp)) { continue; } else { SingleFileObserver sfo = new SingleFileObserver(temp, mMask); sfo.startWatching(); mObservers.put(temp, sfo); } File tempPath = new File(temp); File[] files = tempPath.listFiles(); if (null == files) continue; for (File f: files) { // 递归监听目录 if (f.isDirectory() && !f.getName().equals(".") && !f.getName() .equals("..")) { stack.push(f.getAbsolutePath()); } } } } Log.i("RecursiveFileObserver", "CREATE: " + path); break; case FileObserver.DELETE: Log.i("RecursiveFileObserver", "DELETE: " + path); break; case FileObserver.DELETE_SELF: Log.i("RecursiveFileObserver", "DELETE_SELF: " + path); break; case FileObserver.MODIFY: Log.i("RecursiveFileObserver", "MODIFY: " + path); break; case FileObserver.MOVE_SELF: Log.i("RecursiveFileObserver", "MOVE_SELF: " + path); break; case FileObserver.MOVED_FROM: Log.i("RecursiveFileObserver", "MOVED_FROM: " + path); break; case FileObserver.MOVED_TO: Log.i("RecursiveFileObserver", "MOVED_TO: " + path); break; } } class SingleFileObserver extends FileObserver { String mPath; public SingleFileObserver(String path) { this(path, ALL_EVENTS); mPath = path; } public SingleFileObserver(String path, int mask) { super(path, mask); mPath = path; } @Override public void onEvent(int event, String path) { if(path != null) { String newPath = mPath + "/" + path; RecursiveFileObserver.this.onEvent(event, newPath); } } } }

    总结

    这算是一个比较好的递归监听解决方案,当然还可以进行优化,比如监听目录的删除事件,并取消该目录的监听。最后,吐槽一下,博客就是个人感想和收获的总结,到处抄来抄去没什么意思。看完别人的博客之后,我们应该写出自己的见解,提出更好的解决方案,而不是收藏、转载和抄袭。最后,借鉴别人的东西,请注明出处。

    转载请注明原文地址: https://ju.6miu.com/read-666219.html

    最新回复(0)