Selaa lähdekoodia

LocalFileList: load local files asynchronously

Loading a large list of files (especially the sorting part) is S L O W.
This ensures it doesn't block the UI while loading.

Signed-off-by: Álvaro Brey Vilas <alvaro.brey@nextcloud.com>
Álvaro Brey Vilas 3 vuotta sitten
vanhempi
commit
462da35fdb

+ 37 - 21
src/main/java/com/owncloud/android/ui/adapter/LocalFileListAdapter.java

@@ -23,6 +23,9 @@ package com.owncloud.android.ui.adapter;
 import android.content.Context;
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Bitmap;
+import android.os.AsyncTask;
+import android.os.Handler;
+import android.os.Looper;
 import android.view.LayoutInflater;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewGroup;
@@ -49,6 +52,7 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.List;
 import java.util.Locale;
 import java.util.Locale;
 import java.util.Set;
 import java.util.Set;
+import java.util.concurrent.Executors;
 
 
 import androidx.annotation.NonNull;
 import androidx.annotation.NonNull;
 import androidx.recyclerview.widget.RecyclerView;
 import androidx.recyclerview.widget.RecyclerView;
@@ -79,9 +83,10 @@ public class LocalFileListAdapter extends RecyclerView.Adapter<RecyclerView.View
         this.preferences = preferences;
         this.preferences = preferences;
         mContext = context;
         mContext = context;
         mLocalFolderPicker = localFolderPickerMode;
         mLocalFolderPicker = localFolderPickerMode;
-        swapDirectory(directory);
         this.localFileListFragmentInterface = localFileListFragmentInterface;
         this.localFileListFragmentInterface = localFileListFragmentInterface;
         checkedFiles = new HashSet<>();
         checkedFiles = new HashSet<>();
+
+        swapDirectory(directory);
     }
     }
 
 
     @Override
     @Override
@@ -313,33 +318,44 @@ public class LocalFileListAdapter extends RecyclerView.Adapter<RecyclerView.View
      * @param directory New file to adapt. Can be NULL, meaning "no content to adapt".
      * @param directory New file to adapt. Can be NULL, meaning "no content to adapt".
      */
      */
     public void swapDirectory(final File directory) {
     public void swapDirectory(final File directory) {
-        if (mLocalFolderPicker) {
-            if (directory == null) {
-                mFiles.clear();
+        localFileListFragmentInterface.setLoading(true);
+        final Handler uiHandler = new Handler(Looper.getMainLooper());
+        Executors.newSingleThreadExecutor().execute(() -> {
+            List<File> fileList;
+            if (mLocalFolderPicker) {
+                if (directory == null) {
+                    fileList = null;
+                } else {
+                    fileList = getFolders(directory);
+                }
             } else {
             } else {
-                mFiles = getFolders(directory);
+                if (directory == null) {
+                    fileList = null;
+                } else {
+                    fileList = getFiles(directory);
+                }
             }
             }
-        } else {
-            if (directory == null) {
-                mFiles.clear();
-            } else {
-                mFiles = getFiles(directory);
+
+            FileSortOrder sortOrder = preferences.getSortOrderByType(FileSortOrder.Type.localFileListView);
+            fileList = sortOrder.sortLocalFiles(fileList);
+
+            // Fetch preferences for showing hidden files
+            boolean showHiddenFiles = preferences.isShowHiddenFilesEnabled();
+            if (!showHiddenFiles) {
+                fileList = filterHiddenFiles(fileList);
             }
             }
-        }
 
 
-        FileSortOrder sortOrder = preferences.getSortOrderByType(FileSortOrder.Type.localFileListView);
-        mFiles = sortOrder.sortLocalFiles(mFiles);
+            final List<File> newFiles = fileList;
 
 
-        // Fetch preferences for showing hidden files
-        boolean showHiddenFiles = preferences.isShowHiddenFilesEnabled();
-        if (!showHiddenFiles) {
-            mFiles = filterHiddenFiles(mFiles);
-        }
+            uiHandler.post(() -> {
+                mFiles = newFiles;
+                mFilesAll = new ArrayList<>();
+                mFilesAll.addAll(mFiles);
 
 
-        mFilesAll.clear();
-        mFilesAll.addAll(mFiles);
+                localFileListFragmentInterface.setLoading(false);
+            });
+        });
 
 
-        notifyDataSetChanged();
     }
     }
 
 
     public void setSortOrder(FileSortOrder sortOrder) {
     public void setSortOrder(FileSortOrder sortOrder) {

+ 17 - 0
src/main/java/com/owncloud/android/ui/fragment/LocalFileListFragment.java

@@ -24,6 +24,7 @@ import android.app.Activity;
 import android.content.Context;
 import android.content.Context;
 import android.os.Bundle;
 import android.os.Bundle;
 import android.os.Environment;
 import android.os.Environment;
+import android.os.Handler;
 import android.view.LayoutInflater;
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.Menu;
 import android.view.MenuInflater;
 import android.view.MenuInflater;
@@ -367,6 +368,22 @@ public class LocalFileListFragment extends ExtendedListFragment implements
         super.switchToListView();
         super.switchToListView();
     }
     }
 
 
+    @Override
+    public void setLoading(boolean enabled) {
+        super.setLoading(enabled);
+        if (enabled) {
+            setEmptyListLoadingMessage();
+        } else {
+            // ugly hack because setEmptyListLoadingMessage also uses a handler and there's a race condition otherwise
+            new Handler().post(() -> {
+                mAdapter.notifyDataSetChanged();
+                if(mAdapter.getFilesCount() == 0){
+                    setEmptyListMessage(SearchType.NO_SEARCH);
+                }
+            });
+        }
+    }
+
     /**
     /**
      * Interface to implement by any Activity that includes some instance of LocalFileListFragment
      * Interface to implement by any Activity that includes some instance of LocalFileListFragment
      */
      */

+ 1 - 0
src/main/java/com/owncloud/android/ui/interfaces/LocalFileListFragmentInterface.java

@@ -32,4 +32,5 @@ public interface LocalFileListFragmentInterface {
     int getColumnsCount();
     int getColumnsCount();
     void onItemClicked(File file);
     void onItemClicked(File file);
     void onItemCheckboxClicked(File file);
     void onItemCheckboxClicked(File file);
+    void setLoading(boolean loading);
 }
 }