javaandroidmobiledocumentfile

android DocumentFile.isDirectory() returns unexpected results


I'm embedding a file explorer in my app using DocumentFile but I faced this weird problem where the IsDirectory method returns unexpected results.

I'm using it inside my RecyclerView adapter class.

    @Override
    public void onBindViewHolder(@NonNull AddFilesAdapter.ViewHolder holder, int position) {
        DocumentFile file = files[position];
        holder.filename.setText(file.getName());
        String type = file.getType();
        holder.setFileIndex(position);

        if (file.isDirectory()) {
            holder.icon.setImageResource(R.drawable.folder);
        } else {
            // set icon to something else
        }

        // some unrelated code
    }

this is my implementation of ViewHolder

    public static class ViewHolder extends RecyclerView.ViewHolder {
        public ViewHolder(@NonNull View itemView) {
            super(itemView);
            icon = itemView.findViewById(R.id.IV_FileIcon);
            filename = itemView.findViewById(R.id.TV_FileName);
        }

        public void setFileIndex(int fileIndex) {
            this.fileIndex = fileIndex;
        }

        private int fileIndex;
        public ImageView icon;
        public TextView filename;
    }

Here are the results.

Notice payload.bin and .tmp

Actual results

Here how they are supposed to look like on real file explorer.

enter image description here

The View xml file is fine here I'm using tools:src so it only show in android studio

    <ImageView
        android:id="@+id/IV_FileIcon"
        android:layout_width="50dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginStart="12dp"
        tools:src="@drawable/folder" />

Sorry if images were too big I don't know How to resize them on stack overflow


Solution

  • It seems like Android for efficiency reasons does not generate a new AddFilesAdapter.ViewHolder instance for each time onBindViewHolder is called.

    Most likely isDirectory() returns the correct value but as at the moment you don't set an icon in the else path (the non-directory case) and Android reuses the holder (AddFilesAdapter.ViewHolder) you see the icon you have set for the last directory entry.

    In case you are unsure what a function returns I would recommend to add Log statements like

    Log.d("fn-dir", file.getName() + " " + file.isDirectory()); 
    

    That would allows you to see the actual folder entries and their isDirectory() attribute on logcat output.

    Alternatively use (conditional) breakpoints and start your app in debugging mode. Once the breakpoint hits you can inspect all values you want.