Was working with FileObserver and ran into some serious limitations/design
issues with it that are really not made clear in the documentation.
In my application among other reasons for needing to observe changes in the
file system I have a file browser. When one is viewing a directory and then
say switches to another app and makes a change to that directory, my app
should react and reflect those changes so that you do not see stale data.
So which paths are monitored are very dynamic and change as the user
navigates my app.
The other design challenge is that I have different parts of the
application that need to react to the file system changes and those
different parts don't necessarily know about each other or care about the
same FileObserver events.
So what I originally did was have those different parts each create their
own FileObserver instance to monitor the events that each cares about.
Turns out that having more than one FileObserver instance for the same path
is not supported. The second FileObserver instance effectively replaces the
first. There is nothing in the documentation about this, I only figured it
out using grepcode.
Looking into it further there are some race conditions that can lead to
indeterminate behavior if you ever create a new instance of FileObserver
for the same path. Consider this:
// Create an initial FileObserver
observer = new FileObserver( myPath, someMask)
{
@Override public void onEvent(int event,
String<http://developer.android.com/reference/java/lang/String.html>path)
{
Log.d(TAG,"In original observer");
}
};
observer.startWatching;
...
// Later replace it with a different FileObserver
observer = new FileObserver(myPath, aDifferentMask)
{
@Override public void onEvent(int event,
String<http://developer.android.com/reference/java/lang/String.html>path)
{
Log.d(TAG,"In new observer");
}
};
observer.startWatching();
If a file system change occurs that falls within the mask, will the onEvent
be called? The answer is that you can't tell for sure. It depends on the
garbage collector. FileObserver has a finalizer that calls stopWatching.
Because both instances internally refer to the same inotify watcher that
means the new one will be stopped as well. So there are several
possibilities:
- The finalizer on the old instance gets called before your new instance
starts. You will get all your future events but there was a small window in
the transition where you could have missed events
- The finalizer is called right after your new observer is started. You
will receive no file events on your new observer.
- The finalizer is callled sometime in the future. You will get file
events for a while and then they will stop after the finalizer is called.
If you call stopWatching on the old instance before starting the new one
you remove the indeterminacy, but you still have a window of time between
the two where a file system change could occur and you will miss it.
Not sure what to do about it at this time. Looks like I will probably
create a wrapper API for FileObserver that supports multiple listeners for
the same path (with different event masks) and that internally only creates
one FileObserver. Unfortunately, the only way I can see to make this work
is to have the FileObserver instances themselves listen for all events and
do the filtering myself because there is no good way around the race
conditions of creating new FileObserver instances with different masks.
So the bottom line is that creating more than one FileObserver instance for
the same path is not supported. So if you create a FileObserver instance
for a path that needs to be the only instance until you call stopWatching
on it.
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en