You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by ag...@apache.org on 2015/03/13 15:51:18 UTC
cordova-plugin-file git commit: Add a cache to speed up
AssetFilesystem directory listings
Repository: cordova-plugin-file
Updated Branches:
refs/heads/master eaaaa4803 -> 29804228a
Add a cache to speed up AssetFilesystem directory listings
Adds a gradle step to pre-populate the cache as well, but does not
enable it in this commit.
Project: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file/commit/29804228
Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file/tree/29804228
Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file/diff/29804228
Branch: refs/heads/master
Commit: 29804228a6b53f7b8f0598e495143ffacecb65b0
Parents: eaaaa48
Author: Andrew Grieve <ag...@chromium.org>
Authored: Thu Mar 12 23:12:30 2015 -0400
Committer: Andrew Grieve <ag...@chromium.org>
Committed: Fri Mar 13 10:48:39 2015 -0400
----------------------------------------------------------------------
src/android/AssetFilesystem.java | 53 ++++++++++++++++++++++++++++++++---
src/android/FileUtils.java | 12 ++++----
src/android/LocalFilesystem.java | 9 ++----
src/android/build-extras.gradle | 50 +++++++++++++++++++++++++++++++++
4 files changed, 109 insertions(+), 15 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cordova-plugin-file/blob/29804228/src/android/AssetFilesystem.java
----------------------------------------------------------------------
diff --git a/src/android/AssetFilesystem.java b/src/android/AssetFilesystem.java
index c1c0d6f..525d188 100644
--- a/src/android/AssetFilesystem.java
+++ b/src/android/AssetFilesystem.java
@@ -20,6 +20,7 @@ package org.apache.cordova.file;
import android.content.res.AssetManager;
import android.net.Uri;
+import android.util.Log;
import org.apache.cordova.CordovaResourceApi;
import org.json.JSONArray;
@@ -29,11 +30,55 @@ import org.json.JSONObject;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.util.HashMap;
+import java.util.Map;
public class AssetFilesystem extends Filesystem {
private final AssetManager assetManager;
+ // A custom gradle hook creates the cdvasset.manifest file, which speeds up asset listing a tonne.
+ // See: http://stackoverflow.com/questions/16911558/android-assetmanager-list-incredibly-slow
+ private static Object listCacheLock = new Object();
+ private static boolean listCacheFromFile;
+ private static Map<String, String[]> listCache;
+
+ private String[] listAssets(String assetPath) throws IOException {
+ synchronized (listCacheLock) {
+ if (listCache == null) {
+ ObjectInputStream ois = null;
+ try {
+ ois = new ObjectInputStream(assetManager.open("cdvasset.manifest"));
+ listCache = (Map<String, String[]>) ois.readObject();
+ listCacheFromFile = true;
+ } catch (FileNotFoundException e) {
+ // Asset manifest won't exist if the gradle hook isn't set up correctly.
+ } catch (ClassNotFoundException e) {
+ e.printStackTrace();
+ } finally {
+ if (ois != null) {
+ ois.close();
+ }
+ }
+ if (listCache == null) {
+ Log.w("AssetFilesystem", "Asset manifest not found. Recursive copies and directory listing will be slow.");
+ listCache = new HashMap<String, String[]>();
+ }
+ }
+ }
+ String[] ret = listCache.get(assetPath);
+ if (ret == null) {
+ if (listCacheFromFile) {
+ ret = new String[0];
+ } else {
+ ret = assetManager.list(assetPath);
+ listCache.put(assetPath, ret);
+ }
+ }
+ return ret;
+ }
+
public AssetFilesystem(AssetManager assetManager, CordovaResourceApi resourceApi) {
super(Uri.parse("file:///android_asset/"), "assets", resourceApi);
this.assetManager = assetManager;
@@ -76,15 +121,15 @@ public class AssetFilesystem extends Filesystem {
return LocalFilesystemURL.parse(b.build());
}
- private Boolean isDirectory(String assetPath) {
+ private boolean isDirectory(String assetPath) {
if (assetPath.startsWith("/")) {
assetPath = assetPath.substring(1);
}
try {
- return assetManager.list(assetPath).length != 0;
+ return listAssets(assetPath).length != 0;
} catch (IOException e) {
+ return false;
}
- return false;
}
private LocalFilesystemURL URLforFullPath(String fullPath) {
@@ -105,7 +150,7 @@ public class AssetFilesystem extends Filesystem {
String[] files;
try {
- files = assetManager.list(pathNoSlashes);
+ files = listAssets(pathNoSlashes);
} catch (IOException e) {
throw new FileNotFoundException();
}
http://git-wip-us.apache.org/repos/asf/cordova-plugin-file/blob/29804228/src/android/FileUtils.java
----------------------------------------------------------------------
diff --git a/src/android/FileUtils.java b/src/android/FileUtils.java
index 80d281b..ba096ad 100644
--- a/src/android/FileUtils.java
+++ b/src/android/FileUtils.java
@@ -111,7 +111,7 @@ public class FileUtils extends CordovaPlugin {
if (fsRoot != null) {
File newRoot = new File(fsRoot);
if (newRoot.mkdirs() || newRoot.isDirectory()) {
- registerFilesystem(new LocalFilesystem(fsName, webView.getContext(), webView.getResourceApi(), Uri.fromFile(newRoot)));
+ registerFilesystem(new LocalFilesystem(fsName, webView.getContext(), webView.getResourceApi(), newRoot));
installedFileSystems.add(fsName);
} else {
Log.d(LOG_TAG, "Unable to create root dir for filesystem \"" + fsName + "\", skipping");
@@ -184,15 +184,17 @@ public class FileUtils extends CordovaPlugin {
if (this.configured) {
// Create the directories if they don't exist.
- new File(tempRoot).mkdirs();
- new File(persistentRoot).mkdirs();
+ File tmpRootFile = new File(tempRoot);
+ File persistentRootFile = new File(persistentRoot);
+ tmpRootFile.mkdirs();
+ persistentRootFile.mkdirs();
// Register initial filesystems
// Note: The temporary and persistent filesystems need to be the first two
// registered, so that they will match window.TEMPORARY and window.PERSISTENT,
// per spec.
- this.registerFilesystem(new LocalFilesystem("temporary", webView.getContext(), webView.getResourceApi(), tempRoot));
- this.registerFilesystem(new LocalFilesystem("persistent", webView.getContext(), webView.getResourceApi(), persistentRoot));
+ this.registerFilesystem(new LocalFilesystem("temporary", webView.getContext(), webView.getResourceApi(), tmpRootFile));
+ this.registerFilesystem(new LocalFilesystem("persistent", webView.getContext(), webView.getResourceApi(), persistentRootFile));
this.registerFilesystem(new ContentFilesystem(webView.getContext(), webView.getResourceApi()));
this.registerFilesystem(new AssetFilesystem(webView.getContext().getAssets(), webView.getResourceApi()));
http://git-wip-us.apache.org/repos/asf/cordova-plugin-file/blob/29804228/src/android/LocalFilesystem.java
----------------------------------------------------------------------
diff --git a/src/android/LocalFilesystem.java b/src/android/LocalFilesystem.java
index 35a8668..355cccf 100644
--- a/src/android/LocalFilesystem.java
+++ b/src/android/LocalFilesystem.java
@@ -39,13 +39,10 @@ import android.content.Intent;
public class LocalFilesystem extends Filesystem {
private final Context context;
- public LocalFilesystem(String name, Context context, CordovaResourceApi resourceApi, String rootPath) {
- this(name, context, resourceApi, Uri.fromFile(new File(rootPath)).buildUpon().appendPath("").build());
+ public LocalFilesystem(String name, Context context, CordovaResourceApi resourceApi, File fsRoot) {
+ super(Uri.fromFile(fsRoot).buildUpon().appendEncodedPath("").build(), name, resourceApi);
+ this.context = context;
}
- public LocalFilesystem(String name, Context context, CordovaResourceApi resourceApi, Uri rootUri) {
- super(rootUri, name, resourceApi);
- this.context = context;
- }
public String filesystemPathForFullPath(String fullPath) {
return new File(rootUri.getPath(), fullPath).toString();
http://git-wip-us.apache.org/repos/asf/cordova-plugin-file/blob/29804228/src/android/build-extras.gradle
----------------------------------------------------------------------
diff --git a/src/android/build-extras.gradle b/src/android/build-extras.gradle
new file mode 100644
index 0000000..cf4ad92
--- /dev/null
+++ b/src/android/build-extras.gradle
@@ -0,0 +1,50 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+ext.postBuildExtras = {
+ android.applicationVariants.all { variant ->
+ def variantName = variant.name.capitalize()
+ def processResourcesTask = tasks["process${variantName}Resources"]
+ def inAssetsDir = variant.mergeAssets.rawInputFolders.iterator().next()
+ def outAssetsDir = inAssetsDir
+ def outFile = new File(outAssetsDir, "cdvasset.manifest")
+
+ def newTask = task("cdvCreateAssetManifest$variantName") << {
+ println("Reading from ${inAssetsDir}")
+ println("Writing to ${outFile}")
+
+ def contents = new HashMap()
+ contents[""] = inAssetsDir.list()
+ def tree = fileTree(dir: inAssetsDir)
+ tree.visit { fileDetails ->
+ if (fileDetails.isDirectory()) {
+ contents[fileDetails.relativePath.toString()] = fileDetails.file.list()
+ }
+ }
+
+ outAssetsDir.mkdirs()
+ outFile.withObjectOutputStream { oos ->
+ oos.writeObject(contents)
+ }
+ }
+ newTask.dependsOn(tasks["prepare${variantName}Dependencies"])
+ newTask.inputs.dir inAssetsDir
+ newTask.outputs.file outFile
+ processResourcesTask.dependsOn(newTask)
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org