Search code examples
androidandroid-fragmentsandroid-filefile-browser

Slow files loading in file browser app


I am working on a android filebrowser project, in which there will be four fragments under TabLayout. Four fragments are for Images, videos,audio and docs respectively. After laoding files, get displayed in associated fragment recyclerviews. Like Image files get loaded into recyclerview of Images Fragment(tab).

Code :

private class loader extends AsyncTask<Void,Void,Void> {

    private Context ctx;
    private loader(Context ctx){
        this.ctx=ctx;
    }


    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        progress.setMessage("Loading..");
        progress.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        progress.setIndeterminate(true);
        progress.show();


    }

    @Override
    protected Void doInBackground(Void... params) {

        getfile(root);


        return null;
    }
    @Override
    protected void onPostExecute(Void aVoid) {
        super.onPostExecute(aVoid);

        try{
        if(progress!=null&&progress.isShowing()){
            //progress.cancel();
            progress.dismiss();
        }} catch (final IllegalArgumentException e) {
    } catch (final Exception e) {
    } finally {
        progress = null;
    }

    pager.setAdapter(adapter);
        tabLayout.setupWithViewPager(pager);

    }

}

private void getfile(File dir) {
    File listFile[] = dir.listFiles();
    if (listFile != null && listFile.length > 0) {
        for (int i = 0; i < listFile.length; i++) {

            if (listFile[i].isDirectory()) {
                //                    fileList.add(listFile[i]);
                getfile(listFile[i]);

            } else {
                if (listFile[i].getName().endsWith(".jpg")||listFile[i].getName().endsWith(".png")||listFile[i].getName().endsWith(".jpeg"))
                {
                    imageset.add(listFile[i].toString());
                }
                if (listFile[i].getName().endsWith(".mp4")||listFile[i].getName().endsWith(".avi")||listFile[i].getName().endsWith(".3gp"))
                {
                           videoset.add(listFile[i].toString());

                }
                if (listFile[i].getName().endsWith(".mp3"))
                {
                         audioset.add(listFile[i].toString());

                }
                if (listFile[i].getName().endsWith(".pdf")
                        || listFile[i].getName().endsWith(".doc")
                        || listFile[i].getName().endsWith(".docx")
                        || listFile[i].getName().endsWith(".txt"))

                {
                       fileset.add(listFile[i].toString());

                }


            }

        }
    }
}

Code is working Fine. but the performance in loading files slow in few devices and fast in few devices. each time activity starts it loads, and whenever screen rotates it loads. I don't want it to load everytime activity starts. I thought of putting files in DB so that I can load files fast. but whenever a new file added there is no way DB get updated automatically. So what is the best way to achieve this?

UPDATE:

        private void getFile(File dir) {

    File[] listFile = dir.listFiles(new FilenameFilter() {
        @Override
        public boolean accept(File dir, String filename) {

            Log.d("FILENAME", filename);

            if (dir.isDirectory()) {
                getFile(dir);
                return false;
            }
            String name = dir.getName();
            if (name.endsWith(".jpg") || name.endsWith(".png") || name.endsWith(".jpeg"))
            {
                imageset.add(name);
            }
            if (name.endsWith(".3gp") || name.endsWith(".avi") || name.endsWith(".mp4"))
            {
                videoset.add(name);
            }
            if (name.endsWith(".mp3"))
            {
                audioset.add(name);
            }
            if (name.endsWith(".txt") || name.endsWith(".doc") || name.endsWith(".docx")||name.endsWith(".pdf"))
            {
                fileset.add(name);
            }

            return false;
        }
    });

    for(File f : listFile){ System.out.println(f.getName()); }
}

Solution

  • Your code is very inefficient at multiple points:

    1. You don't use local variables. Calling listFile[i] and listFile[i].getName() dozens of time is very inefficient.

    2. Your are retrieving the complete fils of files and then filter it instead of filtering it directly when retrieving it. You can do that by implementing an FileFilter. We don't use the return value of listFiles therefore the accept() method only returns false.

      dir.listFiles(new FileFilter() {
      
          @Override
          public boolean accept(File pathname) {
              if (pathname.isDirectory()) {
                  getfile(pathname);
                  return false;
              }
              String name = pathname.getName();
              if (name.endsWith(".jpg") || name.endsWith(".png") || name.endsWith(".jpeg") || name.endsWith(".mp4")
                      || name.endsWith(".avi") || name.endsWith(".3gp") || ...) {
                  fileset.add(pathname);
              }
              return false;
          }
      });