SoFunction
Updated on 2025-03-09

The practical battle of android H5 local cache loading optimization

In the last week of 2020, I was about to touch the fish and go home for the New Year, but I didn’t know that the “shocking conspiracy” had been brewing in the leadership. On the verge of day, the team leader walked towards me with a strange smile:

Team leader: "The New Year is coming soon. You have a long journey home. Do you want to take two days off?"

Me: "Team leader, you are really my confidant. You think about what I think, what I think. I will be polite if you say this. Then I will ask for it for two days."

Team leader: "Okay, it's definitely okay to ask for leave. I have always taken good care of my brothers!!" (At that moment, a warm feeling passed by, and he had already abandoned his "explosion" of me this year)

"But I have something to tell you. If you have a requirement before you go home, you have to complete it."

Me: "what??? ,,,, TMD..."

Team leader: "The requirement is as follows: Recently, the client reported that HTML loading is a bit slow, and it is necessary to optimize it. It is best to open it in seconds, come on, I believe you."

Me: "It's not this H5, it's because of your front-end loading slowly. Please look for me...I..." (The team leader has gone away)

With a heavy mood, I started to study optimization, started to do a work in the webView layer, turned on cache, preload, and the effect of a single operation was minimal.

Then start to typing front-end files. Generally, the loading speed of local Html files is much faster than that of Url. So I went to the front end and asked for a local file and put it in the project for local loading. Sure enough, the speed was so fast. At this time, an embarrassing thing happened. The front-end functions were often updated. If they were placed in the project, wouldn’t it be H5 updates? I had to upgrade the version. Not to mention that I have to be exhausted, I guess this plan will come to see the team leader with a knife. So I took a different approach and downloaded the HTML file through the interface and stored it in the mobile phone locally, so that the webView can load the local file in the mobile phone. A strange smile spread out on his face.

Start: 1. I was lazy and used filedownloader to download the Html compressed file

  implementation ':library:1.7.7'
  

Package download tool class:

public class FileDownloadUtils {
public static FileDownloadUtils instance = null;

public FileDownloadUtils() {
}

public static FileDownloadUtils getInstance() {
  if (null == instance) {
    instance = new FileDownloadUtils();
  }
  return instance;
}

/**
  * Single task download
  *
  * @param downLoadUri File download network address
  * @param destinationUri The storage absolute path of the download file
  */
public void startDownLoadFileSingle(String downLoadUri, String destinationUri,FileDownLoaderCallBack callBack) {
  
  ().create(downLoadUri).setPath(destinationUri).setListener(fileDownloadListener(callBack)).start();
}

// Download methodprivate FileDownloadListener fileDownloadListener(final FileDownLoaderCallBack callBack) {
  return new FileDownloadListener() {
    @Override
    protected void pending(BaseDownloadTask task, int soFarBytes, int totalBytes) {
      //Waiting, it has entered the download queue    }

    @Override
    protected void progress(BaseDownloadTask task, int soFarBytes, int totalBytes) {
      //Download progress callback      if (callBack != null){
        (task,soFarBytes,totalBytes);
      }

    }

    @Override
    protected void completed(BaseDownloadTask task) {
      // Complete the entire download process      if (callBack != null){
        (task);
      }
    }

    @Override
    protected void paused(BaseDownloadTask task, int soFarBytes, int totalBytes) {
      //Pause download    }

    @Override
    protected void error(BaseDownloadTask task, Throwable e) {
      //The download error occurred      if (callBack != null){
        (task,e);
      }
    }

    @Override
    protected void warn(BaseDownloadTask task) {
      //In the download queue (waiting/downloading) there is already a task with the same download connection and the same storage path.    }
  };
}

  public interface FileDownLoaderCallBack {
  //Is the file download completed?  void downLoadCompleted(BaseDownloadTask task);

  //Download the file failed  void downLoadError(BaseDownloadTask task, Throwable e);

  //File download progress  void downLoadProgress(BaseDownloadTask task, int soFarBytes, int totalBytes);
 }
}
 

Unzip Zip file

public class ZipUtils {
  public static final String TAG = "ZIP";

  public ZipUtils() {

   }

/**
  * Unzip zip to the specified path
  *
  * @param zipFileString The name of ZIP
  * @param outPathString To decompress the path
  * @throws Exception
  */
public static void UnZipFolder(String zipFileString, String outPathString) throws Exception {
  ZipInputStream inZip = new ZipInputStream(new FileInputStream(zipFileString));
  ZipEntry zipEntry;
  String szName = "";
  while ((zipEntry = ()) != null) {
    szName = ();
    if (()) {
      
      szName = (0, () - 1);
      File folder = new File(outPathString +  + szName);
      ();
    } else {
      (TAG, outPathString +  + szName);
      File file = new File(outPathString +  + szName);
      if (!()) {
        (TAG, "Create the file:" + outPathString +  + szName);
        ().mkdirs();
        ();
      }
      // Get the output stream of the file      FileOutputStream out = new FileOutputStream(file);
      int len;
      byte[] buffer = new byte[1024];
      // Read (byte) bytes to the buffer      while ((len = (buffer)) != -1) {
        // Write (byte) bytes from buffer (0) position        (buffer, 0, len);
        ();
      }
      ();
    }
  }
  ();
}

public static void UnZipFolder(String zipFileString, String outPathString, String szName) throws Exception {
  ZipInputStream inZip = new ZipInputStream(new FileInputStream(zipFileString));
  ZipEntry zipEntry;
  while ((zipEntry = ()) != null) {
    //szName = ();
    if (()) {
      //Get the folder name of the component      szName = (0, () - 1);
      File folder = new File(outPathString +  + szName);
      ();
    } else {
      (TAG, outPathString +  + szName);
      File file = new File(outPathString +  + szName);
      if (!()) {
        (TAG, "Create the file:" + outPathString +  + szName);
        ().mkdirs();
        ();
      }
      // Get the output stream of the file      FileOutputStream out = new FileOutputStream(file);
      int len;
      byte[] buffer = new byte[1024];
      // Read (byte) bytes to the buffer      while ((len = (buffer)) != -1) {
        // Write (byte) bytes from buffer (0) position        (buffer, 0, len);
        ();
      }
      ();
    }
  }
  ();
}

/**
  * Compressed files and folders
  *
  * @param srcFileString file or folder to be compressed
  * @param zipFileString The decompressed Zip path
  * @throws Exception
  */
public static void ZipFolder(String srcFileString, String zipFileString) throws Exception {
  //Create a ZIP  ZipOutputStream outZip = new ZipOutputStream(new FileOutputStream(zipFileString));
  //Create a file  File file = new File(srcFileString);
  //compression // ("---->"+()+"==="+());
  ZipFiles(()+ , (), outZip);
  //Complete and close  ();
  ();
}

/**
  * Compressed file
  *
  * @param folderString
  * @param fileString
  * @param zipOutputSteam
  * @throws Exception
  */
private static void ZipFiles(String folderString, String fileString, ZipOutputStream zipOutputSteam) throws Exception {
  // ("folderString:" + folderString + "\n" +"fileString:" + fileString + "\n==========================");
  if (zipOutputSteam == null)
    return;
  File file = new File(folderString + fileString);
  if (()) {
    ZipEntry zipEntry = new ZipEntry(fileString);
    FileInputStream inputStream = new FileInputStream(file);
    (zipEntry);
    int len;
    byte[] buffer = new byte[4096];
    while ((len = (buffer)) != -1) {
      (buffer, 0, len);
    }
    ();
  } else {
    //Folder    String fileList[] = ();
    //No subfiles and compression    if ( <= 0) {
      ZipEntry zipEntry = new ZipEntry(fileString + );
      (zipEntry);
      ();
    }
    //Subfiles and recursion    for (int i = 0; i < ; i++) {
      ZipFiles(folderString+fileString+"/", fileList[i], zipOutputSteam);
    }
  }
}

/**
  * Returns the file input stream of zip
  *
  * @param zipFileString The name of zip
  * @param fileString ZIP filename
  * @return InputStream
  * @throws Exception
  */
public static InputStream UpZip(String zipFileString, String fileString) throws Exception {
  ZipFile zipFile = new ZipFile(zipFileString);
  ZipEntry zipEntry = (fileString);
  return (zipEntry);
}

/**
  * Returns the list of files (files and folders) in ZIP
  *
  * @param zipFileString The name of ZIP
  * @param bContainFolder Does it contain folders
  * @param bContainFile does it contain a file
  * @return
  * @throws Exception
  */
public static List<File> GetFileList(String zipFileString, boolean bContainFolder, boolean bContainFile) throws Exception {
  List<File> fileList = new ArrayList<File>();
  ZipInputStream inZip = new ZipInputStream(new FileInputStream(zipFileString));
  ZipEntry zipEntry;
  String szName = "";
  while ((zipEntry = ()) != null) {
    szName = ();
    if (()) {
      // Get the folder name of the component      szName = (0, () - 1);
      File folder = new File(szName);
      if (bContainFolder) {
        (folder);
      }
    } else {
      File file = new File(szName);
      if (bContainFile) {
        (file);
      }
    }
  }
  ();
  return fileList;
}
}

download:

    File file = new File(Constants.saveH5FilePath);
    if (()) {
      ();
    }
    //Start download the ZIP compression package    ().startDownLoadFileSingle((), Constants.saveH5FilePath,
        new () {
          @Override
          public void downLoadCompleted(BaseDownloadTask task) {
            try {
              //Decompress ZIP compression package              (Constants.saveH5FilePath, Constants.unH5ZipPath);
              ().saveParam("H5VersionName", H5VersionName);

            } catch (Exception e) {
              ();
            }

          }

          @Override
          public void downLoadError(BaseDownloadTask task, Throwable e) {
          }

          @Override
          public void downLoadProgress(BaseDownloadTask task, int soFarBytes, int totalBytes) {
          }
        });

webView loading:

 ("file:"+ Constants.unH5ZipPath+"/");

At this time, my heart is as calm as water, go home and search. . . .

The above is the detailed content of the actual combat of Android H5 local cache loading optimization. For more information about Android H5 local cache loading optimization, please follow my other related articles!