1

私はAndroidが初めてで、検索機能を含むファイルエクスプローラーを開発しようとしています。いくつかのサブフォルダーとファイルを含むフォルダーでは正常に機能する再帰検索機能を使用していますが、何らかの理由で非常に遅く、十分なメモリがないため、多くのサブフォルダーとファイルを含むフォルダーで「強制的に閉じる」ことができます。結果が配置される ArrayList を作成し、リストを埋める再帰関数を呼び出して検索を行います。"path" 引数は検索を開始するファイル、"query" は検索クエリです。

ArrayList<File> result = new ArrayList<File>();
fileSearch(path, query, result);

再帰関数は次のようになります。

private void fileSearch(File dir, String query, ArrayList<File> res) {
    if (dir.getName().toLowerCase().contains(query.toLowerCase()))
        res.add(dir);
    if (dir.isDirectory() && !dir.isHidden()) {
        if (dir.list() != null) {
            for (File item : dir.listFiles()) {
                fileSearch(item, query, res);
            }
        }
    }
}

誰かがより高速かつ/またはより効率的なファイル検索を実行する方法を教えていただければ、本当に感謝しています。

編集:

これは私がAsyncTaskで仕事をしようとした方法です:

private class Search extends AsyncTask<File, Integer, Void> {

    String query;
    ArrayList<File> result = new ArrayList<File>();

    public Search(String query){
        this.query = query;
        setTitle("Searching");
    }

    @Override
    protected Void doInBackground(File... item) {
        int count = item.length;
        for (int i = 0; i < count; i++) {
            fileSearch(item[i], query, result);
            publishProgress((int) ((i / (float) count) * 100));
            // Escape early if cancel() is called
            if (isCancelled()) break;
        }
        return null;
    }

    protected void onProgressUpdate(Integer... progress) {
        setProgress(progress[0]);
    }

    protected void onPostExecute() {
        searchResults = new ListItemDetails[result.size()];
        for (int i = 0; i < result.size(); i++) {
            File temp = result.get(i);
            if (temp.isDirectory())
                searchResults[i] = new ListItemDetails(temp.getAbsolutePath(),
                        R.drawable.folder, temp.lastModified(), temp.length());
            else {
                String ext;
                if (temp.getName().lastIndexOf('.') == -1)
                    ext = "";
                else
                    ext = temp.getName().substring(
                            temp.getName().lastIndexOf('.'));
                searchResults[i] = new ListItemDetails(temp.getAbsolutePath(),
                        getIcon(ext), temp.lastModified(), temp.length());
            }
        }
        finishSearch();
    }

}

public void finishSearch() {
    Intent intent = new Intent(this, SearchResults.class);
    startActivity(intent);
}

finishSearch() の呼び出しは、他のアクティビティで結果を表示するインテントを作成できるようにするためのものです。アイデア、提案、ヒントはありますか?前もって感謝します

4

4 に答える 4

4

シンボリック リンクにヒットし、検索機能で無限ループに入り、アプリケーションで利用可能なメモリを使い果たしている可能性があります。

アクセスしたディレクトリの標準パス ( File.getCanonicalPath() )を含む別のリストを保持し、何度もアクセスしないようにすることをお勧めします。

于 2013-09-11T11:11:02.453 に答える
2

Apache Commons IOを使用しないのはなぜですか? 検索に対処するためのいくつかの機能があります。

また、フォルダー、検索クエリ、およびディレクトリ フィルターをパラメーターとして受け取るメソッドFileUtils.listFilesを使用することもお勧めします。

次の例は、正規表現に従って一致したすべてのファイルのパスのリストを返します。AsyncTaskの doInBackground に追加してみてください。

Collection files = FileUtils.listFiles(new File(yourRootPath), 
                   new RegexFileFilter(searchQuery), 
                   DirectoryFileFilter.DIRECTORY);
于 2013-09-17T15:32:22.400 に答える
0

バックグラウンドで実行し、Android O (API 26) 以降ではFiles.find API を使用できます。例:

Files.find(
    Paths.get(startPath), Integer.MAX_VALUE,
    { path, _ -> path.fileName.toString() == file.name }
).forEach { foundPath ->
   Log.d("AppLog", "found file on:${foundPath.toFile().absolutePath}")
}
于 2021-09-08T20:42:54.010 に答える