Pressing back while folder is loading goes to parent, it should only stop loading the folder.
This is only expected, not a bug =_=
It should only cancel loading the folder... Why would it not? How would I cancel a folder loading if not?
It's not necessary at all. Most of the times, we're loading a file system, not a website. So implementing this would be pointless.
Plus, you can always go back if you're on a network and want to cancel.
Loading folders of >1000 can be slow in some devices, in such cases it would be useful.
Plus, you can always go back if you're on a network and want to cancel.
You can go back, but that would re request the parent folder (unless caching is used, I don't think we do).
No other file manager does this, I don't think why we need to do. Something like this won't fit design anywhere.
How will it not fit design?
@EmmanuelMess It seems that you have a misconception about actual reason behind loading speed of huge folders. The "reading from filesystem" part is very fast. And directories themselves aren't that big. There are bugs in many file managers (including Amaze), that might cause directories to load slower then necessary. Loading a directory with ~1000 files really should not be slow by design.
It is true that obtaining 2200 files' information takes ~5s from adb (ran "adb shell time ls -l"), which is quite fast.
But there will always be a big enough folder or a bad enough connection, or some other situation, where the user might choose to cancel the folder loading, what I am proposing is that it is unintuitive that "back" while the loading "icon" is open goes to the parent folder. Another solution would be to not make the loading "icon" appear at all, but would make no sense, would it?
@Alexander-- , could you point to the issues where these loading bugs are described, or make a short description of some of them?
@EmmanuelMess
It is true that obtaining 2200 files' information takes ~5s from adb (ran "adb shell time ls -l")
Here are my results:
generic_x86:/data/test # time ls -l > /dev/null
0m00.05s real 0m00.05s user 0m00.00s system
generic_x86:/data/test # time ls -1fa > /dev/null
0m00.02s real 0m00.02s user 0m00.00s system
The results above has been produced on emulator in directory with 2200 files (each filename of 150-character). In your case the result might be slightly skewered by using adb (the time, required to pass output over usb, might not be negligible).
Note the difference between ls -l (sorted, filtered, full details) and ls -fa (unsorted, print filenames only). More on that later.
But there will always be a big enough folder
Not really, you are extremely unlikely to see folders approaching 1Gb. Try to create such folder yourself, — you will run out of inodes well before directory size reaches a gigabyte (this is because Android uses aufs for sdcard partitions, and aufs is notorious for wasteful inode management).
As for remote filesystems, their specifics differ a lot from local files, so let's put those aside for now (there are different reasons, why this issue won't work out for them anyway).
could you point to the issues where these loading bugs are described, or make a short description of some of them?
I won't give you any links, but here are some practical observation, that correlate nicely with ls -l behaviour, mentioned above.
Many file managers read a lot of data from disk to display directory contents. The main part of data — directory listing — is small (the filesystem footprint of a directory essentially amounts to length of it's filenames). But there is also metadata of files: creation times, permissions etc., which is heavily fragmented on disk and have to be queried individually for each file.
In Linux the file metadata is read by stat system call. The following methods perform that call internally:
File#isDirectory
File#isFile
File#lastModified
File#length
Following methods can use either stat or separate access call, but in practice that makes little difference (except for exists(), which might be slightly more efficient if implemented via access):
File#canRead
File#canWrite
File#canExecute
File#exists
All these File methods obtain full stat structure with all metadata about a file, then throw away unneeded fields. That information is never cached in java or native code. The metadata itself can sometimes be cached by filesystem cache, but that depends on access patterns, and you still pay overhead of system call.
In practice that means, that calling File#isDirectory results in reading a chunk of data from filesystem. Calling it 2200 times results in reading from filesystem 2200 times...
If a file manager eagerly builds up some kind of FileInfo[] to back up it's file listing, it is highly likely to perform all those 2200+ stat calls in advance before displaying the directory. In practice, there is likely to be a lot more than 2200 calls (getting size, modification date etc.) If those calls aren't done lazily, you will observe heavy delays when opening huge directories.
There are several ways to mitigate that issue. You can use a different API, that allows to obtain entire stat structure in single system call, then keep that metadata around instead of calling length(), isDirectory() etc. separately. One such API is available in API 21+: Os#stat.
More importantly, it is possible to postpone getting detailed file info until the RecyclerView is forced to bind the viewholder for involved file. That is: lazily get file information inside onBindViewHolder callback. That way the long initial delay is avoided, and initially displaying a directory will amount to single readdir and several stat calls for items visible on screen.
The difference between getting directory entries and calling stat on boatload of files is also the cause of difference between timings of ls -l and ls -af. Former has to stat all files in advance, then sort results. Later does not have to stat files and can display results immediately.
Most helpful comment
@EmmanuelMess
Here are my results:
generic_x86:/data/test # time ls -l > /dev/null 0m00.05s real 0m00.05s user 0m00.00s system generic_x86:/data/test # time ls -1fa > /dev/null 0m00.02s real 0m00.02s user 0m00.00s systemThe results above has been produced on emulator in directory with 2200 files (each filename of 150-character). In your case the result might be slightly skewered by using adb (the time, required to pass output over usb, might not be negligible).
Note the difference between
ls -l(sorted, filtered, full details) andls -fa(unsorted, print filenames only). More on that later.Not really, you are extremely unlikely to see folders approaching 1Gb. Try to create such folder yourself, — you will run out of inodes well before directory size reaches a gigabyte (this is because Android uses aufs for sdcard partitions, and aufs is notorious for wasteful inode management).
As for remote filesystems, their specifics differ a lot from local files, so let's put those aside for now (there are different reasons, why this issue won't work out for them anyway).
I won't give you any links, but here are some practical observation, that correlate nicely with
ls -lbehaviour, mentioned above.Many file managers read a lot of data from disk to display directory contents. The main part of data — directory listing — is small (the filesystem footprint of a directory essentially amounts to length of it's filenames). But there is also metadata of files: creation times, permissions etc., which is heavily fragmented on disk and have to be queried individually for each file.
In Linux the file metadata is read by
statsystem call. The following methods perform that call internally:File#isDirectory File#isFile File#lastModified File#lengthFollowing methods can use either
stator separateaccesscall, but in practice that makes little difference (except forexists(), which might be slightly more efficient if implemented viaaccess):File#canRead File#canWrite File#canExecute File#existsAll these
Filemethods obtain full stat structure with all metadata about a file, then throw away unneeded fields. That information is never cached in java or native code. The metadata itself can sometimes be cached by filesystem cache, but that depends on access patterns, and you still pay overhead of system call.In practice that means, that calling File#isDirectory results in reading a chunk of data from filesystem. Calling it 2200 times results in reading from filesystem 2200 times...
If a file manager eagerly builds up some kind of
FileInfo[]to back up it's file listing, it is highly likely to perform all those 2200+statcalls in advance before displaying the directory. In practice, there is likely to be a lot more than 2200 calls (getting size, modification date etc.) If those calls aren't done lazily, you will observe heavy delays when opening huge directories.There are several ways to mitigate that issue. You can use a different API, that allows to obtain entire
statstructure in single system call, then keep that metadata around instead of callinglength(),isDirectory()etc. separately. One such API is available in API 21+: Os#stat.More importantly, it is possible to postpone getting detailed file info until the RecyclerView is forced to bind the viewholder for involved file. That is: lazily get file information inside
onBindViewHoldercallback. That way the long initial delay is avoided, and initially displaying a directory will amount to singlereaddirand severalstatcalls for items visible on screen.The difference between getting directory entries and calling
staton boatload of files is also the cause of difference between timings ofls -landls -af. Former has tostatall files in advance, then sort results. Later does not have tostatfiles and can display results immediately.