mirror of
				https://github.com/commons-app/apps-android-commons.git
				synced 2025-10-31 14:53:59 +01:00 
			
		
		
		
	Fix crash(es) caused by failing to dispose Rx observables (#2669)
This commit is contained in:
		
							parent
							
								
									38d39e08ac
								
							
						
					
					
						commit
						8474c04c64
					
				
					 21 changed files with 121 additions and 86 deletions
				
			
		|  | @ -17,6 +17,7 @@ import androidx.exifinterface.media.ExifInterface; | |||
| import fr.free.nrw.commons.caching.CacheController; | ||||
| import fr.free.nrw.commons.kvstore.JsonKvStore; | ||||
| import fr.free.nrw.commons.mwapi.CategoryApi; | ||||
| import io.reactivex.disposables.CompositeDisposable; | ||||
| import io.reactivex.schedulers.Schedulers; | ||||
| import timber.log.Timber; | ||||
| 
 | ||||
|  | @ -42,11 +43,16 @@ public class FileProcessor implements SimilarImageDialogFragment.onResponse { | |||
|     private ExifInterface exifInterface; | ||||
|     private boolean haveCheckedForOtherImages = false; | ||||
|     private GPSExtractor tempImageObj; | ||||
|     private CompositeDisposable compositeDisposable = new CompositeDisposable(); | ||||
| 
 | ||||
|     @Inject | ||||
|     FileProcessor() { | ||||
|     } | ||||
| 
 | ||||
|     public void cleanup() { | ||||
|         compositeDisposable.clear(); | ||||
|     } | ||||
| 
 | ||||
|     void initFileDetails(@NonNull String filePath, ContentResolver contentResolver) { | ||||
|         this.filePath = filePath; | ||||
|         this.contentResolver = contentResolver; | ||||
|  | @ -138,7 +144,7 @@ public class FileProcessor implements SimilarImageDialogFragment.onResponse { | |||
| 
 | ||||
|             // If no categories found in cache, call MediaWiki API to match image coords with nearby Commons categories | ||||
|             if (catListEmpty) { | ||||
|                 apiCall.request(decimalCoords) | ||||
|                 compositeDisposable.add(apiCall.request(decimalCoords) | ||||
|                         .subscribeOn(Schedulers.io()) | ||||
|                         .observeOn(Schedulers.io()) | ||||
|                         .subscribe( | ||||
|  | @ -147,7 +153,7 @@ public class FileProcessor implements SimilarImageDialogFragment.onResponse { | |||
|                                     Timber.e(throwable); | ||||
|                                     gpsCategoryModel.clear(); | ||||
|                                 } | ||||
|                         ); | ||||
|                         )); | ||||
|                 Timber.d("displayCatList size 0, calling MWAPI %s", displayCatList); | ||||
|             } else { | ||||
|                 Timber.d("Cache found, setting categoryList in model to %s", displayCatList); | ||||
|  |  | |||
|  | @ -33,16 +33,19 @@ public class ImageProcessingService { | |||
|     private final MediaWikiApi mwApi; | ||||
|     private final ReadFBMD readFBMD; | ||||
|     private final EXIFReader EXIFReader; | ||||
|     private final Context context; | ||||
| 
 | ||||
|     @Inject | ||||
|     public ImageProcessingService(FileUtilsWrapper fileUtilsWrapper, | ||||
|                                   ImageUtilsWrapper imageUtilsWrapper, | ||||
|                                   MediaWikiApi mwApi, ReadFBMD readFBMD, EXIFReader EXIFReader) { | ||||
|                                   MediaWikiApi mwApi, ReadFBMD readFBMD, EXIFReader EXIFReader, | ||||
|                                   Context context) { | ||||
|         this.fileUtilsWrapper = fileUtilsWrapper; | ||||
|         this.imageUtilsWrapper = imageUtilsWrapper; | ||||
|         this.mwApi = mwApi; | ||||
|         this.readFBMD = readFBMD; | ||||
|         this.EXIFReader = EXIFReader; | ||||
|         this.context = context; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | @ -61,13 +64,13 @@ public class ImageProcessingService { | |||
|         Timber.d("Checking the validity of image"); | ||||
|         String filePath = uploadItem.getMediaUri().getPath(); | ||||
|         Uri contentUri=uploadItem.getContentUri(); | ||||
|         Context context=uploadItem.getContext(); | ||||
|         Single<Integer> duplicateImage = checkDuplicateImage(filePath); | ||||
|         Single<Integer> wrongGeoLocation = checkImageGeoLocation(uploadItem.getPlace(), filePath); | ||||
|         Single<Integer> darkImage = checkDarkImage(filePath); | ||||
|         Single<Integer> itemTitle = checkTitle ? validateItemTitle(uploadItem) : Single.just(ImageUtils.IMAGE_OK); | ||||
|         Single<Integer> checkFBMD = checkFBMD(context,contentUri); | ||||
|         Single<Integer> checkEXIF = checkEXIF(filePath); | ||||
| 
 | ||||
|         Single<Integer> zipResult = Single.zip(duplicateImage, wrongGeoLocation, darkImage, itemTitle, | ||||
|                 (duplicate, wrongGeo, dark, title) -> { | ||||
|                     Timber.d("Result for duplicate: %d, geo: %d, dark: %d, title: %d", duplicate, wrongGeo, dark, title); | ||||
|  |  | |||
|  | @ -5,7 +5,6 @@ import android.annotation.SuppressLint; | |||
| import android.app.ProgressDialog; | ||||
| import android.content.Intent; | ||||
| import android.net.Uri; | ||||
| import android.os.Build; | ||||
| import android.os.Bundle; | ||||
| import com.google.android.material.textfield.TextInputLayout; | ||||
| import androidx.appcompat.app.AlertDialog; | ||||
|  | @ -67,7 +66,6 @@ import fr.free.nrw.commons.utils.PermissionUtils; | |||
| import fr.free.nrw.commons.utils.ViewUtil; | ||||
| import io.reactivex.Observable; | ||||
| import io.reactivex.android.schedulers.AndroidSchedulers; | ||||
| import io.reactivex.disposables.CompositeDisposable; | ||||
| import io.reactivex.schedulers.Schedulers; | ||||
| import timber.log.Timber; | ||||
| 
 | ||||
|  | @ -134,7 +132,6 @@ public class UploadActivity extends BaseActivity implements UploadView, SimilarI | |||
| 
 | ||||
|     private DescriptionsAdapter descriptionsAdapter; | ||||
|     private RVRendererAdapter<CategoryItem> categoriesAdapter; | ||||
|     private CompositeDisposable compositeDisposable; | ||||
|     private ProgressDialog progressDialog; | ||||
| 
 | ||||
| 
 | ||||
|  | @ -145,7 +142,6 @@ public class UploadActivity extends BaseActivity implements UploadView, SimilarI | |||
| 
 | ||||
|         setContentView(R.layout.activity_upload); | ||||
|         ButterKnife.bind(this); | ||||
|         compositeDisposable = new CompositeDisposable(); | ||||
| 
 | ||||
|         configureLayout(); | ||||
|         configureTopCard(); | ||||
|  | @ -211,8 +207,6 @@ public class UploadActivity extends BaseActivity implements UploadView, SimilarI | |||
|     @Override | ||||
|     protected void onPause() { | ||||
|         presenter.removeView(); | ||||
|         compositeDisposable.dispose(); | ||||
|         compositeDisposable = new CompositeDisposable(); | ||||
|         super.onPause(); | ||||
|     } | ||||
| 
 | ||||
|  | @ -571,7 +565,7 @@ public class UploadActivity extends BaseActivity implements UploadView, SimilarI | |||
|     @SuppressLint("CheckResult") | ||||
|     private void updateCategoryList(String filter) { | ||||
|         List<String> imageTitleList = presenter.getImageTitleList(); | ||||
|         Observable.fromIterable(categoriesModel.getSelectedCategories()) | ||||
|         compositeDisposable.add(Observable.fromIterable(categoriesModel.getSelectedCategories()) | ||||
|                 .subscribeOn(Schedulers.io()) | ||||
|                 .observeOn(AndroidSchedulers.mainThread()) | ||||
|                 .doOnSubscribe(disposable -> { | ||||
|  | @ -602,7 +596,7 @@ public class UploadActivity extends BaseActivity implements UploadView, SimilarI | |||
|                                 categoriesSearchContainer.setError("No categories found"); | ||||
|                             } | ||||
|                         } | ||||
|                 ); | ||||
|                 )); | ||||
|     } | ||||
| 
 | ||||
|     private void receiveSharedItems() { | ||||
|  |  | |||
|  | @ -26,7 +26,7 @@ import fr.free.nrw.commons.utils.ImageUtils; | |||
| import io.reactivex.Observable; | ||||
| import io.reactivex.Single; | ||||
| import io.reactivex.android.schedulers.AndroidSchedulers; | ||||
| import io.reactivex.disposables.Disposable; | ||||
| import io.reactivex.disposables.CompositeDisposable; | ||||
| import io.reactivex.functions.Consumer; | ||||
| import io.reactivex.schedulers.Schedulers; | ||||
| import io.reactivex.subjects.BehaviorSubject; | ||||
|  | @ -45,6 +45,7 @@ public class UploadModel { | |||
|     }; | ||||
|     private final JsonKvStore store; | ||||
|     private final List<String> licenses; | ||||
|     private final Context context; | ||||
|     private String license; | ||||
|     private final Map<String, String> licensesByName; | ||||
|     private List<UploadItem> items = new ArrayList<>(); | ||||
|  | @ -52,8 +53,7 @@ public class UploadModel { | |||
|     private boolean bottomCardState = true; | ||||
|     private boolean rightCardState = true; | ||||
|     private int currentStepIndex = 0; | ||||
|     public static Context context; | ||||
|     private Disposable badImageSubscription; | ||||
|     private CompositeDisposable compositeDisposable = new CompositeDisposable(); | ||||
| 
 | ||||
|     private SessionManager sessionManager; | ||||
|     private FileProcessor fileProcessor; | ||||
|  | @ -77,6 +77,11 @@ public class UploadModel { | |||
|         this.imageProcessingService = imageProcessingService; | ||||
|     } | ||||
| 
 | ||||
|     void cleanup() { | ||||
|         compositeDisposable.clear(); | ||||
|         fileProcessor.cleanup(); | ||||
|     } | ||||
| 
 | ||||
|     @SuppressLint("CheckResult") | ||||
|     Observable<UploadItem> preProcessImages(List<UploadableFile> uploadableFiles, | ||||
|                                             Place place, | ||||
|  | @ -219,8 +224,7 @@ public class UploadModel { | |||
|     } | ||||
| 
 | ||||
|     public void previous() { | ||||
|         if (badImageSubscription != null) | ||||
|             badImageSubscription.dispose(); | ||||
|         cleanup(); | ||||
|         markCurrentUploadVisited(); | ||||
|         if (currentStepIndex > 0) { | ||||
|             currentStepIndex--; | ||||
|  | @ -305,16 +309,16 @@ public class UploadModel { | |||
|     } | ||||
| 
 | ||||
|     void deletePicture() { | ||||
|         badImageSubscription.dispose(); | ||||
|         cleanup(); | ||||
|         updateItemState(); | ||||
|     } | ||||
| 
 | ||||
|     void subscribeBadPicture(Consumer<Integer> consumer, boolean checkTitle) { | ||||
|         if (isShowingItem()) { | ||||
|             badImageSubscription = getImageQuality(getCurrentItem(), checkTitle) | ||||
|             compositeDisposable.add(getImageQuality(getCurrentItem(), checkTitle) | ||||
|                     .subscribeOn(Schedulers.io()) | ||||
|                     .observeOn(AndroidSchedulers.mainThread()) | ||||
|                     .subscribe(consumer, Timber::e); | ||||
|                     .subscribe(consumer, Timber::e)); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | @ -432,10 +436,6 @@ public class UploadModel { | |||
|         public Uri getContentUri() { | ||||
|             return originalContentUri; | ||||
|         } | ||||
| 
 | ||||
|         public Context getContext(){ | ||||
|             return UploadModel.context; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | @ -21,6 +21,7 @@ import fr.free.nrw.commons.settings.Prefs; | |||
| import fr.free.nrw.commons.utils.StringUtils; | ||||
| import io.reactivex.Observable; | ||||
| import io.reactivex.android.schedulers.AndroidSchedulers; | ||||
| import io.reactivex.disposables.CompositeDisposable; | ||||
| import io.reactivex.schedulers.Schedulers; | ||||
| import timber.log.Timber; | ||||
| 
 | ||||
|  | @ -52,6 +53,7 @@ public class UploadPresenter { | |||
|     private final UploadController uploadController; | ||||
|     private final Context context; | ||||
|     private final JsonKvStore directKvStore; | ||||
|     private CompositeDisposable compositeDisposable = new CompositeDisposable(); | ||||
| 
 | ||||
|     @Inject | ||||
|     UploadPresenter(UploadModel uploadModel, | ||||
|  | @ -77,12 +79,12 @@ public class UploadPresenter { | |||
|         Observable<UploadItem> uploadItemObservable = uploadModel | ||||
|                 .preProcessImages(media, place, source, similarImageInterface); | ||||
| 
 | ||||
|         uploadItemObservable | ||||
|         compositeDisposable.add(uploadItemObservable | ||||
|                 .toList() | ||||
|                 .subscribeOn(Schedulers.io()) | ||||
|                 .observeOn(AndroidSchedulers.mainThread()) | ||||
|                 .subscribe(uploadItems -> onImagesProcessed(uploadItems, place), | ||||
|                         throwable -> Timber.e(throwable, "Error occurred in processing images")); | ||||
|                         throwable -> Timber.e(throwable, "Error occurred in processing images"))); | ||||
|     } | ||||
| 
 | ||||
|     private void onImagesProcessed(List<UploadItem> uploadItems, Place place) { | ||||
|  | @ -211,9 +213,9 @@ public class UploadPresenter { | |||
|     @SuppressLint("CheckResult") | ||||
|     void handleSubmit(CategoriesModel categoriesModel) { | ||||
|         if (view.checkIfLoggedIn()) | ||||
|             uploadModel.buildContributions(categoriesModel.getCategoryStringList()) | ||||
|             compositeDisposable.add(uploadModel.buildContributions(categoriesModel.getCategoryStringList()) | ||||
|                     .observeOn(Schedulers.io()) | ||||
|                     .subscribe(uploadController::startUpload); | ||||
|                     .subscribe(uploadController::startUpload)); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | @ -286,6 +288,8 @@ public class UploadPresenter { | |||
|     } | ||||
| 
 | ||||
|     void cleanup() { | ||||
|         compositeDisposable.clear(); | ||||
|         uploadModel.cleanup(); | ||||
|         uploadController.cleanup(); | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dmitry Brant
						Dmitry Brant