RxJava精选案例

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

2017-04-13  本文已影响294人  知用改创

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

主要内容

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

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

冗余注册监听我是通过用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);
            }
        }
    }
}

总结

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

上一篇下一篇

猜你喜欢

热点阅读