Browse Source

优化视频恢复流程

zk 1 year ago
parent
commit
96965c218b

+ 71 - 48
app/src/main/java/com/datarecovery/master/module/videorecover/VideoRecoverViewModel.java

@@ -22,12 +22,14 @@ import com.datarecovery.master.utils.FilesSearch;
 import com.datarecovery.master.utils.Maps;
 import com.datarecovery.master.utils.MediaStoreHelper;
 import com.datarecovery.master.utils.ReportUtil;
+import com.datarecovery.master.utils.ReverseArrayList;
 import com.datarecovery.master.utils.ToastUtil;
 
 import org.reactivestreams.Subscriber;
 import org.reactivestreams.Subscription;
 
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 import java.util.concurrent.TimeUnit;
 
@@ -35,6 +37,8 @@ import javax.inject.Inject;
 
 import atmob.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
 import atmob.reactivex.rxjava3.annotations.NonNull;
+import atmob.reactivex.rxjava3.core.Single;
+import atmob.reactivex.rxjava3.core.SingleObserver;
 import atmob.reactivex.rxjava3.disposables.Disposable;
 import atmob.rxjava.utils.RxJavaUtil;
 import dagger.hilt.android.lifecycle.HiltViewModel;
@@ -50,8 +54,11 @@ public class VideoRecoverViewModel extends BaseViewModel {
     private final LiveData<String> selectedCountTxt;
     private final MutableLiveData<String> detectedLastFileName = new MutableLiveData<>();
     private final MutableLiveData<Boolean> checkAll = new MutableLiveData<>(false);
-    private final MutableLiveData<List<FilesSearch.DocumentFile>> detectedVideoList = new MutableLiveData<>(new ArrayList<>());
-    private final MutableLiveData<List<FilesSearch.DocumentFile>> selectedList = new MutableLiveData<>(new ArrayList<>());
+
+    private final List<FilesSearch.DocumentFile> videoList = new ReverseArrayList<>();
+    private final List<FilesSearch.DocumentFile> selectList = new ArrayList<>();
+    private final MutableLiveData<List<FilesSearch.DocumentFile>> detectedVideoList = new MutableLiveData<>();
+    private final MutableLiveData<List<FilesSearch.DocumentFile>> selectedList = new MutableLiveData<>();
     private final MutableLiveData<Boolean> showTrialView = new MutableLiveData<>();
     private final SingleLiveEvent<?> showTrialFinishDialog = new SingleLiveEvent<>();
     private final SingleLiveEvent<?> showTrialExportFailDialog = new SingleLiveEvent<>();
@@ -148,6 +155,7 @@ public class VideoRecoverViewModel extends BaseViewModel {
                         scanDisposable = Disposable.fromSubscription(s);
                         addDisposable(scanDisposable);
                         showScanDialogEvent.setValue(true);
+                        videoList.clear();
                     }
 
                     @Override
@@ -155,12 +163,11 @@ public class VideoRecoverViewModel extends BaseViewModel {
                         if (documentFiles == null) {
                             return;
                         }
-                        List<FilesSearch.DocumentFile> videoList = getList(detectedVideoList);
                         for (FilesSearch.DocumentFile documentFile : documentFiles) {
                             detectedLastFileName.setValue(documentFile.getName());
-                            videoList.add(0, documentFile);
-                            detectedVideoList.setValue(videoList);
                         }
+                        videoList.addAll(documentFiles);
+                        detectedVideoList.setValue(videoList);
                         scrollTop.call();
                     }
 
@@ -184,35 +191,24 @@ public class VideoRecoverViewModel extends BaseViewModel {
     private void setFreeExport() {
         if (isTrial) {
             showTrialView.setValue(true);
-            List<FilesSearch.DocumentFile> list = getList(detectedVideoList);
-            if (!list.isEmpty()) {
-                list.get(0).setTrial(true);
+            if (!videoList.isEmpty()) {
+                videoList.get(0).setTrial(true);
             }
         }
     }
 
     public void onCheckAllClick(boolean isCheck) {
         checkAll.setValue(isCheck);
-        List<FilesSearch.DocumentFile> detectedList = getList(detectedVideoList);
-        for (FilesSearch.DocumentFile videoFile : detectedList) {
+        for (FilesSearch.DocumentFile videoFile : videoList) {
             videoFile.setCheck(isCheck);
         }
-        List<FilesSearch.DocumentFile> selectedList = getList(this.selectedList);
         if (isCheck) {
-            selectedList.clear();
-            selectedList.addAll(detectedList);
+            selectList.clear();
+            selectList.addAll(videoList);
         } else {
-            selectedList.clear();
+            selectList.clear();
         }
-        this.selectedList.setValue(selectedList);
-    }
-
-    private List<FilesSearch.DocumentFile> getList(LiveData<List<FilesSearch.DocumentFile>> liveData) {
-        List<FilesSearch.DocumentFile> selectList = liveData.getValue();
-        if (selectList == null) {
-            selectList = new ArrayList<>();
-        }
-        return selectList;
+        this.selectedList.setValue(selectList);
     }
 
     public void cancelScan() {
@@ -222,12 +218,11 @@ public class VideoRecoverViewModel extends BaseViewModel {
     }
 
     public void onExportClick() {
-        List<FilesSearch.DocumentFile> list = selectedList.getValue();
-        if (list == null || list.isEmpty()) {
+        if (selectList.isEmpty()) {
             return;
         }
         if (isTrial) {
-            for (FilesSearch.DocumentFile file : list) {
+            for (FilesSearch.DocumentFile file : selectList) {
                 if (!file.isTrial()) {
                     showTrialExportFailDialog.call();
                     return;
@@ -238,35 +233,63 @@ public class VideoRecoverViewModel extends BaseViewModel {
                 return;
             }
         }
-        showLoadingEvent.setValue(true);
-        RxJavaUtil.doInBackground(() -> {
-            for (FilesSearch.DocumentFile item : list) {
-                MediaStoreHelper.saveToSharedStorage(MediaStoreHelper.TYPE_VIDEO, item.newInputStream(), FileUtil.getCreateFileName(MediaStoreHelper.TYPE_VIDEO, item.getName()));
-                item.setCheck(false);
-            }
-            return true;
-        }, o -> {
-            checkAll.setValue(false);
-            showLoadingEvent.setValue(false);
-            ToastUtil.show(R.string.export_success, ToastUtil.LENGTH_SHORT);
-            list.clear();
-            selectedList.setValue(list);
-        }, throwable -> {
-            showLoadingEvent.setValue(false);
-            ToastUtil.show(throwable.getMessage(), ToastUtil.LENGTH_SHORT);
-            BuglyHelper.postCatchedException(new Exception("视频导出:", throwable));
-        });
+        Single.just(selectList.size())
+                .map(oldSize -> {
+                    Iterator<FilesSearch.DocumentFile> iterator = selectList.iterator();
+                    int errorCount = 0;
+                    Exception exception = null;
+                    while (iterator.hasNext()) {
+                        FilesSearch.DocumentFile item = iterator.next();
+                        try {
+                            MediaStoreHelper.saveToSharedStorage(MediaStoreHelper.TYPE_VIDEO, item.newInputStream(), FileUtil.getCreateFileName(MediaStoreHelper.TYPE_VIDEO, item.getName()));
+                            item.setCheck(false);
+                            iterator.remove();
+                        } catch (Exception throwable) {
+                            errorCount++;
+                            exception = throwable;
+                            BuglyHelper.postCatchedException(new Exception("视频导出:", throwable));
+                        }
+                    }
+                    if (errorCount == oldSize) {
+                        throw new Exception("导出失败" + (exception == null ? "" : ":" + exception.getMessage()));
+                    } else if (errorCount > 0) {
+                        throw new Exception("部分导出失败" + ":" + exception.getMessage());
+                    }
+                    return errorCount;
+                })
+                .compose(RxJavaUtil.SingleSchedule.io2Main())
+                .subscribe(new SingleObserver<Integer>() {
+                    @Override
+                    public void onSubscribe(@NonNull Disposable d) {
+                        showLoadingEvent.setValue(true);
+                        addDisposable(d);
+                    }
+
+                    @Override
+                    public void onSuccess(@NonNull Integer integer) {
+                        showLoadingEvent.setValue(false);
+                        selectedList.setValue(selectList);
+                        checkAll.setValue(false);
+                        ToastUtil.show(R.string.export_success, ToastUtil.LENGTH_SHORT);
+                    }
+
+                    @Override
+                    public void onError(@NonNull Throwable throwable) {
+                        showLoadingEvent.setValue(false);
+                        selectedList.setValue(selectList);
+                        ToastUtil.show(throwable.getMessage(), ToastUtil.LENGTH_SHORT);
+                    }
+                });
     }
 
     public void setItemCheck(@NonNull FilesSearch.DocumentFile file) {
         file.setCheck(!file.isCheck());
-        List<FilesSearch.DocumentFile> list = getList(selectedList);
         if (file.isCheck()) {
-            list.add(file);
+            selectList.add(file);
         } else {
-            list.remove(file);
+            selectList.remove(file);
         }
-        selectedList.setValue(list);
+        selectedList.setValue(selectList);
     }
 
     public void closeHintClick() {