How to search for files elegantly on Android and solve the error of The content of the adapter has changed but ListView did not receive a notification

Codewords work hard! Please indicate the source!

We know that running JAVA on Android has strict memory limitations. You can't use recursion and multithreading like on PCs, otherwise~

OOM, not classic~

So, how to search files gracefully on Android?

The key points are:

1. Replace recursion

2. Terminate the previous search thread in due course

3. Update List and View in the main thread

4. Avoid memory leaks caused by Activity objects in threads

——Then we record the file directory that needs to be searched and loop through it, check the Activity life cycle when calling back, and perform thread switching, the problem will not be solved~

Not much to say, the code:


    //搜索文件线程
    private Thread t_searchFile;

    public interface SearchFileListener {
        void gotOne(File file);

        void onFinished(List<File> searchedFiles);
    }

    //搜索文件
    public List<File> searchFile(final Activity activity, final String filePath,
                                 final String fileName, final SearchFileListener searchFileListener) {

        //终止上一个搜索线程(如果有)
        stopSearching();

        final List<File> searchedFiles = new ArrayList<>();
        if (TextUtils.isEmpty(fileName) || TextUtils.isEmpty(filePath)) {
            return searchedFiles;
        }
        t_searchFile = new Thread() {
            @Override
            public void run() {
                super.run();

                //不使用递归,而是将需要扫描的文件目录记录下来
                List<File> waitForSearchFilePath = new ArrayList<>();
                waitForSearchFilePath.add(new File(filePath));

                while (waitForSearchFilePath.size() > 0 && !isInterrupted() &&
                        //所有循环均检测Activity生命周期,以防内存泄漏
                        !activityIsDestroyed(activity)) {
                    File[] files = waitForSearchFilePath.get(0).listFiles();
                    if (files != null) {
                        for (int i = 0; i < files.length; i++) {
                            if (isInterrupted() && activityIsDestroyed(activity)) {
                                break;
                            }
                            final File temp = files[i];

                            //过滤掉没有读写权限的文件,以防权限异常崩溃
                            if (temp.canRead() && temp.canWrite()) {

                                //全部转换为小写再匹配,以使搜索结果不区分大小写
                                if (temp.getName().toLowerCase().contains(fileName.toLowerCase())) {

                                    //当Activity生命周期已经结束时,终止搜索
                                    if (activityIsDestroyed(activity)) {
                                        break;
                                    }

                                    //将符合条件的项目添加到链表,并在主线程回调以便刷新页面
                                    activity.runOnUiThread(new Runnable() {
                                        @Override
                                        public void run() {
                                            searchedFiles.add(temp);
                                            if (searchFileListener != null) {
                                                searchFileListener.gotOne(temp);
                                            }
                                        }
                                    });
                                }
                                if (temp.isDirectory()) {

                                    //将子目录添加到待扫描链表,替代递归
                                    waitForSearchFilePath.add(temp);
                                }
                            }
                        }
                    }

                    //完成当前目录扫描,移除链表
                    waitForSearchFilePath.remove(0);
                }
                if (!activityIsDestroyed(activity) && !isInterrupted()) {
                    activity.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            if (searchFileListener != null) {
                                searchFileListener.onFinished(searchedFiles);
                            }
                        }
                    });
                }
            }
        };
        t_searchFile.start();
        return searchedFiles;
    }

    //终止搜索线程
    public void stopSearching() {
        if (t_searchFile != null) {
            t_searchFile.interrupt();
        }
    }

    //检测Activity生命周期
    private boolean activityIsDestroyed(Activity activity) {
        return activity == null || activity.isFinishing() || activity.isDestroyed();
    }

Using the above method, the measured memory of the thread (excluding the checked-out file List) is less than 3K, and the OOM problem is solved perfectly~

Finally, if you think the blogger’s article is helpful to you, you may wish to give the blogger a small red envelope~

Guess you like

Origin blog.csdn.net/u014653815/article/details/88988913