浏览代码

FilesUploadHelper: insert all uploads in single transaction to avoid too many listener calls

Signed-off-by: Álvaro Brey <alvaro.brey@nextcloud.com>
Álvaro Brey 2 年之前
父节点
当前提交
044a321678

+ 54 - 12
app/src/main/java/com/owncloud/android/datamodel/UploadsStorageManager.java

@@ -23,13 +23,18 @@
  */
 package com.owncloud.android.datamodel;
 
+import android.content.ContentProviderOperation;
+import android.content.ContentProviderResult;
 import android.content.ContentResolver;
 import android.content.ContentValues;
+import android.content.OperationApplicationException;
 import android.database.Cursor;
 import android.net.Uri;
+import android.os.RemoteException;
 
 import com.nextcloud.client.account.CurrentAccountProvider;
 import com.nextcloud.client.account.User;
+import com.owncloud.android.MainApp;
 import com.owncloud.android.db.OCUpload;
 import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
 import com.owncloud.android.db.UploadResult;
@@ -42,6 +47,7 @@ import com.owncloud.android.operations.UploadFileOperation;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Calendar;
+import java.util.List;
 import java.util.Locale;
 import java.util.Observable;
 
@@ -82,6 +88,52 @@ public class UploadsStorageManager extends Observable {
     public long storeUpload(OCUpload ocUpload) {
         Log_OC.v(TAG, "Inserting " + ocUpload.getLocalPath() + " with status=" + ocUpload.getUploadStatus());
 
+        ContentValues cv = getContentValues(ocUpload);
+        Uri result = getDB().insert(ProviderTableMeta.CONTENT_URI_UPLOADS, cv);
+
+        Log_OC.d(TAG, "storeUpload returns with: " + result + " for file: " + ocUpload.getLocalPath());
+        if (result == null) {
+            Log_OC.e(TAG, "Failed to insert item " + ocUpload.getLocalPath() + " into upload db.");
+            return -1;
+        } else {
+            long new_id = Long.parseLong(result.getPathSegments().get(1));
+            ocUpload.setUploadId(new_id);
+            notifyObserversNow();
+            return new_id;
+        }
+    }
+
+    public long[] storeUploads(final List<OCUpload> ocUploads) {
+        Log_OC.v(TAG, "Inserting " + ocUploads.size() + " uploads");
+        ArrayList<ContentProviderOperation> operations = new ArrayList<>(ocUploads.size());
+        for (OCUpload ocUpload : ocUploads) {
+            final ContentProviderOperation operation = ContentProviderOperation
+                .newInsert(ProviderTableMeta.CONTENT_URI_UPLOADS)
+                .withValues(getContentValues(ocUpload))
+                .build();
+            operations.add(operation);
+        }
+
+        try {
+            final ContentProviderResult[] contentProviderResults = getDB().applyBatch(MainApp.getAuthority(), operations);
+            final long[] newIds = new long[ocUploads.size()];
+            for (int i = 0; i < contentProviderResults.length; i++) {
+                final ContentProviderResult result = contentProviderResults[i];
+                final long new_id = Long.parseLong(result.uri.getPathSegments().get(1));
+                ocUploads.get(i).setUploadId(new_id);
+                newIds[i] = new_id;
+            }
+            notifyObserversNow();
+            return newIds;
+        } catch (OperationApplicationException | RemoteException e) {
+            Log_OC.e(TAG, "Error inserting uploads", e);
+        }
+
+        return null;
+    }
+
+    @NonNull
+    private ContentValues getContentValues(OCUpload ocUpload) {
         ContentValues cv = new ContentValues();
         cv.put(ProviderTableMeta.UPLOADS_LOCAL_PATH, ocUpload.getLocalPath());
         cv.put(ProviderTableMeta.UPLOADS_REMOTE_PATH, ocUpload.getRemotePath());
@@ -96,20 +148,10 @@ public class UploadsStorageManager extends Observable {
         cv.put(ProviderTableMeta.UPLOADS_IS_WHILE_CHARGING_ONLY, ocUpload.isWhileChargingOnly() ? 1 : 0);
         cv.put(ProviderTableMeta.UPLOADS_IS_WIFI_ONLY, ocUpload.isUseWifiOnly() ? 1 : 0);
         cv.put(ProviderTableMeta.UPLOADS_FOLDER_UNLOCK_TOKEN, ocUpload.getFolderUnlockToken());
-        Uri result = getDB().insert(ProviderTableMeta.CONTENT_URI_UPLOADS, cv);
-
-        Log_OC.d(TAG, "storeUpload returns with: " + result + " for file: " + ocUpload.getLocalPath());
-        if (result == null) {
-            Log_OC.e(TAG, "Failed to insert item " + ocUpload.getLocalPath() + " into upload db.");
-            return -1;
-        } else {
-            long new_id = Long.parseLong(result.getPathSegments().get(1));
-            ocUpload.setUploadId(new_id);
-            notifyObserversNow();
-            return new_id;
-        }
+        return cv;
     }
 
+
     /**
      * Update an upload object in DB.
      *

+ 5 - 7
app/src/main/java/com/owncloud/android/utils/FilesUploadHelper.kt

@@ -55,8 +55,8 @@ class FilesUploadHelper {
         nameCollisionPolicy: NameCollisionPolicy,
         localBehavior: Int
     ) {
-        for (i in localPaths.indices) {
-            OCUpload(localPaths[i], remotePaths[i], user.accountName).apply {
+        val uploads = localPaths.mapIndexed { index, localPath ->
+            OCUpload(localPath, remotePaths[index], user.accountName).apply {
                 this.nameCollisionPolicy = nameCollisionPolicy
                 isUseWifiOnly = requiresWifi
                 isWhileChargingOnly = requiresCharging
@@ -64,10 +64,9 @@ class FilesUploadHelper {
                 this.createdBy = createdBy
                 isCreateRemoteFolder = createRemoteFolder
                 localAction = localBehavior
-            }.also {
-                uploadsStorageManager.storeUpload(it)
             }
         }
+        uploadsStorageManager.storeUploads(uploads)
         backgroundJobManager.startFilesUploadJob(user)
     }
 
@@ -79,7 +78,7 @@ class FilesUploadHelper {
     ) {
         Log_OC.d(this, "upload updated file")
 
-        for (file in existingFiles) {
+        val uploads = existingFiles.map { file ->
             OCUpload(file, user).apply {
                 fileSize = file.fileLength
                 this.nameCollisionPolicy = nameCollisionPolicy
@@ -88,10 +87,9 @@ class FilesUploadHelper {
                 isUseWifiOnly = false
                 isWhileChargingOnly = false
                 uploadStatus = UploadsStorageManager.UploadStatus.UPLOAD_IN_PROGRESS
-            }.also {
-                uploadsStorageManager.storeUpload(it)
             }
         }
+        uploadsStorageManager.storeUploads(uploads)
         backgroundJobManager.startFilesUploadJob(user)
     }