package com.example.search;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @Description: java类作用描述
* @Author: lugx
* @Date: 2021/9/13 11:07
*/
public abstract class FileFind {
private final static String TAG = "lugx";
private List<String> mSearchPathList;
private List<String> mSearchResultPathList;
private AtomicInteger mTaskNum;
private boolean mStartFlag = false;
private long mStartTime;
/**
* 搜索到一个就结束
*/
private boolean mSearchOneEnd = true;
private boolean mCancelFlag = false;
private IFileFindListener mListener;
private Handler mMainHandler = new Handler(Looper.getMainLooper());
public static ThreadPoolExecutor EXECUTOR;
static{
EXECUTOR = new ThreadPoolExecutor(3, 3, 60, TimeUnit.SECONDS,
new LinkedBlockingQueue<>());
EXECUTOR.allowCoreThreadTimeOut(true);
}
public interface IFileFindListener{
void onFindFile(String filePath);
void onFindEnd(List<String> filePathList);
}
public FileFind(List<String> searchPathList){
String[] pathArr = searchPathList.toArray(new String[0]);
Log.e(TAG, "VideoFind , rootPath = " + Arrays.toString(pathArr));
mSearchPathList = new ArrayList<>(searchPathList);
mSearchResultPathList = new ArrayList<>();
}
public void setFileFindListener(IFileFindListener listener){
mListener = listener;
}
public void setSearchOneEnd(boolean endFlag){
mSearchOneEnd = endFlag;
}
public synchronized void cancel(){
mCancelFlag = true;
}
public synchronized boolean isCancel(){
return mCancelFlag;
}
public void startSearch(){
if (mSearchPathList == null || mSearchPathList.isEmpty()){
return;
}
synchronized (this) {
if (mStartFlag) {
return;
}
mStartFlag = true;
}
mTaskNum = new AtomicInteger(mSearchPathList.size());
mStartTime = System.currentTimeMillis();
for(String path : mSearchPathList) {
EXECUTOR.execute(new Runnable() {
@Override
public void run() {
Log.e(TAG, "start Search path : " + path);
try {
search(path);
}finally {
Log.e(TAG, "end end Search path : " + path);
int num = mTaskNum.decrementAndGet();
if (num <= 0) {
searchEnd();
}
}
}
});
}
}
private synchronized void addSearchResultPath(String path){
mSearchResultPathList.add(path);
}
private synchronized void printSearchResultPath(){
Log.e(TAG, "printSearchPath size = " + mSearchResultPathList.size());
for(String path : mSearchResultPathList){
Log.i(TAG, "printSearchPath : " + path);
}
}
private void onFindFileNotify(String path){
if (isCancel()){
return;
}
mMainHandler.post(new Runnable() {
@Override
public void run() {
if(mListener != null && !isCancel()){
mListener.onFindFile(path);
}
}
});
}
private void onFindEndNotify(){
if (isCancel()){
return;
}
mMainHandler.post(new Runnable() {
@Override
public void run() {
if(mListener != null && !isCancel()){
mListener.onFindEnd(mSearchResultPathList);
}
}
});
}
private synchronized void searchEnd(){
long useTime = System.currentTimeMillis() - mStartTime;
Log.e(TAG, "VideoFind ,search end........useTime = " + useTime);
printSearchResultPath();
onFindEndNotify();
}
private synchronized boolean isSearchOne(){
if(mSearchOneEnd){
return mSearchResultPathList.size() > 0;
}
return false;
}
private void search(String absolutePath){
if (isCancel()){
Log.e(TAG, "search is cancel, ignore : " + absolutePath);
return;
}
if (isSearchOne()){
Log.e(TAG, "isSearchOne is true, ignore : " + absolutePath);
return;
}
if (absolutePath == null){
return;
}
File file = new File(absolutePath);
if (file == null || !file.exists()){
return;
}
// Log.i(TAG, "search dir : " + absolutePath);
if (file.isFile()){
if (isTargetFile(file)){
addSearchResultPath(file.getAbsolutePath());
onFindFileNotify(file.getAbsolutePath());
}
} else if (file.isDirectory()){
String[] filePathArr = file.list(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return FileFind.this.accept(dir, name);
}
});
if (filePathArr != null && filePathArr.length > 0){
String dir = file.getAbsolutePath() + File.separator;
for(String path : filePathArr){
search(dir + path);
}
}
}
}
/**
* File.list
* public String[] list(FilenameFilter filter)
* 用来过滤文件 或 文件夹是否参与 搜索
*
* @param dir 文件夹
* @param name 文件夹下的文件名
* @return true:参与搜索;false : 不参与
*/
public abstract boolean accept(File dir, String name);
/**
* 是否是 目标文件
* @param file
* @return
*/
public abstract boolean isTargetFile(File file);
}
[点击并拖拽以移动]
子类需要实现 2个抽象方法就可以使用了。