fromTreeUri(context, treeUri)
Tree URIs
Open a folder from ACTION_OPEN_DOCUMENT_TREE. Names, sizes and types arrive with the listing.
A drop-in for AndroidX DocumentFile on Storage Access Framework trees. It reads metadata while listing,
so getName(), length() and findFile() stop costing a provider query each.
implementation "com.lazygeniouz:dfc:<version>"
implementation("com.lazygeniouz:dfc:<version>")
Benchmark
The sample app lists the same SAF tree with both libraries. The bars below race at the real ratio from one run:
about 48 seconds for DocumentFile, about 3.5 for DocumentFileCompat.
48 ÷ 3.5 on that listing
Numbers depend on the provider, device and folder size. DFC isn't competing with java.io.File; it makes SAF-backed access less painful.
How it works
With DocumentFile, each getter on each child goes back to the provider. DFC asks for those
columns in the listing cursor, so the data is already there when you read it.
1 listing query, then name, size, modified and type per file.
1 listing query that returns those columns together.
Migrate
The API mirrors AndroidX. The main change is how you create the first instance.
fromTreeUri, fromSingleUri and fromFile entry pointslistFiles, findFile, lengthcount(), copyTo(), copyFrom()-import androidx.documentfile.provider.DocumentFile+import com.lazygeniouz.dfc.file.DocumentFileCompat -val dir = DocumentFile.fromTreeUri(context, treeUri) ?: return+val dir = DocumentFileCompat.fromTreeUri(context, treeUri) ?: return val files = dir.listFiles() val report = dir.findFile("report.pdf") // lighter queries when you only need a few columns val slim = dir.listFiles(projection)
What it supports
Everything in one small Kotlin library, no extra dependencies to wire up.
fromTreeUri(context, treeUri)
Open a folder from ACTION_OPEN_DOCUMENT_TREE. Names, sizes and types arrive with the listing.
fromSingleUri(context, uri)
Wrap one picked file and read its metadata without extra lookups.
fromFile(context, file)
The same interface over java.io.File, so callers don't care what backs it.
observe { event, doc -> }
Event-driven watching of a tree's direct children, no polling loop.
listFiles(projection)
Ask only for the columns you need and keep queries lighter still.
count() · copyTo(destination) · copyFrom(source)
Count a folder's children, or copy a document to or from another one in a single call.
observe()
Create, delete, move and change events for a SAF tree's direct children, driven by provider change notifications.
val observer = directory.observe { event, document -> println("$event: ${document.name}") } observer.startWatching( onError = { error -> /* why watching stopped */ }, onReady = { /* initial snapshot is ready */ }, ) // later, from the owning lifecycle observer.close()
onReady runs once it finishes.