Skip to content

Commit

Permalink
fix: #293
Browse files Browse the repository at this point in the history
  • Loading branch information
liyujiang-gzu committed Mar 16, 2022
1 parent 36bc516 commit 4cee783
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ProgressBar;
import android.widget.TextView;

import androidx.annotation.NonNull;
Expand All @@ -34,6 +35,7 @@
import com.github.gzuliyujiang.filepicker.adapter.ViewHolder;
import com.github.gzuliyujiang.filepicker.annotation.ExplorerMode;
import com.github.gzuliyujiang.filepicker.contract.OnFileClickedListener;
import com.github.gzuliyujiang.filepicker.contract.OnFileLoadedListener;
import com.github.gzuliyujiang.filepicker.contract.OnPathClickedListener;

import java.io.File;
Expand All @@ -46,12 +48,13 @@
* @since 2021/6/10 18:50
*/
@SuppressWarnings("unused")
public class FileExplorer extends FrameLayout implements OnPathClickedListener {
public class FileExplorer extends FrameLayout implements OnFileLoadedListener, OnPathClickedListener {
private int explorerMode = ExplorerMode.FILE;
private File initDir;
private CharSequence emptyHint;
private FileAdapter fileAdapter;
private PathAdapter pathAdapter;
private ProgressBar loadingView;
private RecyclerView fileListView;
private TextView emptyHintView;
private RecyclerView pathListView;
Expand Down Expand Up @@ -85,7 +88,9 @@ private void init(Context context) {
pathAdapter.setOnPathClickedListener(this);
pathListView = contentView.findViewById(R.id.file_picker_path_list);
pathListView.setAdapter(pathAdapter);
loadingView = contentView.findViewById(R.id.file_picker_loading);
fileAdapter = new FileAdapter(context);
fileAdapter.setOnFileLoadedListener(this);
fileAdapter.setOnPathClickedListener(this);
fileAdapter.setOnlyListDir(false);
fileAdapter.setShowHideDir(true);
Expand All @@ -99,6 +104,32 @@ private void init(Context context) {
emptyHintView.setText(emptyHint);
}

@Override
public void onFileLoaded(@NonNull File file) {
loadingView.setVisibility(INVISIBLE);
int itemCount = fileAdapter.getItemCount();
if (fileAdapter.isShowHomeDir()) {
itemCount--;
}
if (fileAdapter.isShowUpDir()) {
itemCount--;
}
if (itemCount < 1) {
DialogLog.print("no files, or dir is empty");
emptyHintView.setVisibility(View.VISIBLE);
emptyHintView.setText(emptyHint);
} else {
DialogLog.print("files or dirs count: " + itemCount);
emptyHintView.setVisibility(View.INVISIBLE);
}
pathListView.post(new Runnable() {
@Override
public void run() {
pathListView.scrollToPosition(pathAdapter.getItemCount() - 1);
}
});
}

@Override
public void onPathClicked(RecyclerView.Adapter<ViewHolder> adapter, int position, @NonNull String path) {
DialogLog.print("clicked path name: " + path);
Expand Down Expand Up @@ -129,11 +160,22 @@ public final File getDefaultDir() {
}
}

/**
* 设置浏览模式及初始目录
*/
public void setInitDir(@ExplorerMode int explorerMode, File initDir) {
setInitDir(explorerMode, initDir, true);
}

/**
* 设置浏览模式、初始目录及是否异步加载
*/
public void setInitDir(@ExplorerMode int explorerMode, File initDir, boolean loadAsync) {
if (this.explorerMode != explorerMode) {
this.explorerMode = explorerMode;
fileAdapter.setOnlyListDir(explorerMode == ExplorerMode.DIRECTORY);
}
fileAdapter.setLoadAsync(loadAsync);
if (initDir == null) {
initDir = getDefaultDir();
}
Expand All @@ -158,29 +200,13 @@ public final void refreshCurrent(File current) {
if (current == null) {
return;
}
loadingView.setVisibility(VISIBLE);
emptyHintView.setVisibility(View.INVISIBLE);
long millis = System.currentTimeMillis();
pathAdapter.updatePath(current);
fileAdapter.loadData(current);
int itemCount = fileAdapter.getItemCount();
if (fileAdapter.isShowHomeDir()) {
itemCount--;
}
if (fileAdapter.isShowUpDir()) {
itemCount--;
}
if (itemCount < 1) {
DialogLog.print("no files, or dir is empty");
emptyHintView.setVisibility(View.VISIBLE);
emptyHintView.setText(emptyHint);
} else {
DialogLog.print("files or dirs count: " + itemCount);
emptyHintView.setVisibility(View.GONE);
}
pathListView.post(new Runnable() {
@Override
public void run() {
pathListView.scrollToPosition(pathAdapter.getItemCount() - 1);
}
});
long spent = System.currentTimeMillis() - millis;
DialogLog.print("spent: " + spent + " ms" + ", async=" + fileAdapter.isLoadAsync() + ", thread=" + Thread.currentThread());
}

public void setOnFileClickedListener(OnFileClickedListener listener) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
public class FilePicker extends ModalDialog {
private int explorerMode = ExplorerMode.FILE;
private File initDir;
private boolean loadAsync = true;
private FileExplorer fileExplorer;
private OnFilePickedListener onFilePickedListener;
private boolean initialized = false;
Expand Down Expand Up @@ -71,7 +72,7 @@ protected void initView() {
protected void initData() {
super.initData();
initialized = true;
setInitDir(explorerMode, initDir);
setInitDir(explorerMode, initDir, loadAsync);
}

@Override
Expand All @@ -89,10 +90,15 @@ protected void onOk() {
}

public void setInitDir(@ExplorerMode int explorerMode, File initDir) {
setInitDir(explorerMode, initDir, true);
}

public void setInitDir(@ExplorerMode int explorerMode, File initDir, boolean loadAsync) {
this.explorerMode = explorerMode;
this.initDir = initDir;
this.loadAsync = loadAsync;
if (initialized) {
fileExplorer.setInitDir(explorerMode, initDir);
fileExplorer.setInitDir(explorerMode, initDir, loadAsync);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
Expand All @@ -33,6 +35,7 @@
import com.github.gzuliyujiang.dialog.DialogLog;
import com.github.gzuliyujiang.filepicker.R;
import com.github.gzuliyujiang.filepicker.annotation.FileSort;
import com.github.gzuliyujiang.filepicker.contract.OnFileLoadedListener;
import com.github.gzuliyujiang.filepicker.contract.OnPathClickedListener;
import com.github.gzuliyujiang.filepicker.filter.SimpleFilter;
import com.github.gzuliyujiang.filepicker.sort.SortByExtension;
Expand All @@ -45,7 +48,12 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;

/**
* 文件目录数据适配
Expand All @@ -55,13 +63,17 @@
*/
@SuppressWarnings("unused")
public class FileAdapter extends RecyclerView.Adapter<ViewHolder> {
private static final ExecutorService THREAD_POOL = Executors.newCachedThreadPool();
private static final Handler UI_HANDLER = new Handler(Looper.getMainLooper());
private final Context context;
public static final String DIR_ROOT = ".";
public static final String DIR_PARENT = "..";
private final List<FileEntity> data = new ArrayList<>();
private File rootDir = null;
private File currentFile = null;
private String[] allowExtensions = null;
private boolean loadAsync = true;
private final LinkedList<FutureTask<?>> futureTasks = new LinkedList<>();
private boolean onlyListDir = false;
private boolean showHomeDir = true;
private boolean showUpDir = true;
Expand All @@ -72,6 +84,7 @@ public class FileAdapter extends RecyclerView.Adapter<ViewHolder> {
private Drawable upIcon;
private Drawable folderIcon;
private Drawable fileIcon;
private OnFileLoadedListener onFileLoadedListener;
private OnPathClickedListener onPathClickedListener;

public FileAdapter(@NonNull Context context) {
Expand Down Expand Up @@ -181,6 +194,20 @@ public void setAllowExtensions(String[] allowExtensions) {
this.allowExtensions = allowExtensions;
}

/**
* 是否异步加载文件夹或文件
*/
public void setLoadAsync(boolean loadAsync) {
if (this.loadAsync == loadAsync) {
return;
}
this.loadAsync = loadAsync;
}

public boolean isLoadAsync() {
return loadAsync;
}

/**
* 是否仅仅读取目录
*/
Expand Down Expand Up @@ -261,12 +288,58 @@ public void refreshData() {
loadData(currentFile);
}

public void loadData(final File dir) {
if (!loadAsync) {
reallyRefresh(loadDataSync(dir));
return;
}
if (!futureTasks.isEmpty()) {
FutureTask<?> futureTask = futureTasks.getFirst();
if (futureTask != null && !futureTask.isDone()) {
futureTask.cancel(true);
}
}
FutureTask<?> futureTask = new FutureTask<>(new Callable<Void>() {
@Override
public Void call() {
final List<FileEntity> temp = loadDataSync(dir);
if (!futureTasks.isEmpty()) {
FutureTask<?> futureTask = futureTasks.removeFirst();
if (futureTask != null && futureTask.isCancelled()) {
DialogLog.print("data load is canceled: " + currentFile);
return null;
}
}
UI_HANDLER.post(new Runnable() {
@Override
public void run() {
reallyRefresh(temp);
}
});
return null;
}
});
futureTasks.addLast(futureTask);
THREAD_POOL.execute(futureTask);
}

@SuppressLint("NotifyDataSetChanged")
public void loadData(File dir) {
private void reallyRefresh(List<FileEntity> temp) {
data.clear();
data.addAll(temp);
notifyDataSetChanged();
if (onFileLoadedListener != null) {
onFileLoadedListener.onFileLoaded(currentFile);
}
DialogLog.print("notify changed when data loaded: " + currentFile);
}

private List<FileEntity> loadDataSync(File dir) {
if (dir == null) {
DialogLog.print("current directory is null");
return;
return new ArrayList<>();
}
long millis = System.currentTimeMillis();
List<FileEntity> entities = new ArrayList<>();
if (rootDir == null) {
rootDir = dir;
Expand Down Expand Up @@ -305,9 +378,9 @@ public void loadData(File dir) {
FileEntity.setFile(file);
entities.add(FileEntity);
}
data.clear();
data.addAll(entities);
notifyDataSetChanged();
long spent = System.currentTimeMillis() - millis;
DialogLog.print("spent: " + spent + " ms" + ", async=" + loadAsync + ", thread=" + Thread.currentThread());
return entities;
}

public final void recycleData() {
Expand Down Expand Up @@ -338,6 +411,10 @@ public final void recycleData() {
}
}

public void setOnFileLoadedListener(OnFileLoadedListener listener) {
onFileLoadedListener = listener;
}

public void setOnPathClickedListener(OnPathClickedListener listener) {
onPathClickedListener = listener;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (c) 2016-present 贵州纳雍穿青人李裕江<[email protected]>
*
* The software is licensed under the Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
* PURPOSE.
* See the Mulan PSL v2 for more details.
*/

package com.github.gzuliyujiang.filepicker.contract;

import androidx.annotation.NonNull;

import java.io.File;

/**
* @author 贵州山野羡民([email protected]
* @since 2022/3/16 14:29
*/
public interface OnFileLoadedListener {

void onFileLoaded(@NonNull File file);

}
8 changes: 8 additions & 0 deletions FilePicker/src/main/res/layout/file_picker_content.xml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@
tools:text="&lt;Empty&gt;"
tools:visibility="visible" />

<ProgressBar
android:id="@+id/file_picker_loading"
style="@android:style/Widget.ProgressBar.Small"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="invisible" />

</FrameLayout>

</LinearLayout>

0 comments on commit 4cee783

Please sign in to comment.