Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix crash(es) caused by failing to dispose Rx observables #2669

Merged
merged 24 commits into from
Mar 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
3657487
Add missing global error handler.
dbrant Mar 19, 2019
4d0db8d
Remove unnecessary disposable container.
dbrant Mar 19, 2019
d6e630f
Add missing disposal logic.
dbrant Mar 19, 2019
df37a07
Add convenience CompoundDisposable to BaseActivity.
dbrant Mar 19, 2019
78c85c4
Add missing disposable logic.
dbrant Mar 19, 2019
b1ad7a2
Add missing dispose logic.
dbrant Mar 19, 2019
9033acc
Add missing dispose logic.
dbrant Mar 19, 2019
e1fbb02
Fix additional missing Rx disposal logic.
dbrant Mar 19, 2019
d4f3fa7
Fix even more Rx dispose logic.
dbrant Mar 19, 2019
d6ab30f
Simplify dispose logic.
dbrant Mar 19, 2019
d1c83a6
Remove redundant CompositeDisposable.
dbrant Mar 19, 2019
c2a20ce
Properly contain and dispose of additional observables.
dbrant Mar 19, 2019
5ab731d
Remove unnecessary disposable container.
dbrant Mar 19, 2019
69b4326
Add missing disposal logic.
dbrant Mar 19, 2019
0e261d8
Add convenience CompoundDisposable to BaseActivity.
dbrant Mar 19, 2019
f15972c
Add missing disposable logic.
dbrant Mar 19, 2019
078234b
Add missing dispose logic.
dbrant Mar 19, 2019
f812f37
Add missing dispose logic.
dbrant Mar 19, 2019
90a0548
Fix additional missing Rx disposal logic.
dbrant Mar 19, 2019
94bf47b
Fix even more Rx dispose logic.
dbrant Mar 19, 2019
51e119e
Simplify dispose logic.
dbrant Mar 19, 2019
3c8dc09
Remove redundant CompositeDisposable.
dbrant Mar 19, 2019
cfeed69
Merge branch 'RxFixes2' of github.com:dbrant/apps-android-commons int…
dbrant Mar 19, 2019
14a2975
Merge branch 'RxFixes3' into RxFixes2
dbrant Mar 19, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions app/src/main/java/fr/free/nrw/commons/CommonsApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
import fr.free.nrw.commons.upload.FileUtils;
import fr.free.nrw.commons.utils.ConfigUtils;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.internal.functions.Functions;
import io.reactivex.plugins.RxJavaPlugins;
import io.reactivex.schedulers.Schedulers;
import timber.log.Timber;

Expand Down Expand Up @@ -128,6 +130,9 @@ public void onCreate() {

createNotificationChannel(this);

// This handler will catch exceptions thrown from Observables after they are disposed,
// or from Observables that are (deliberately or not) missing an onError handler.
RxJavaPlugins.setErrorHandler(Functions.emptyConsumer());

if (setupLeakCanary() == RefWatcher.DISABLED) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,12 @@ protected void onCreate(Bundle savedInstanceState) {
initDrawer();
}

@Override
public void onDestroy() {
super.onDestroy();
compositeDisposable.clear();
}

/**
* To invoke the AlertDialog on clicking info button
*/
Expand Down Expand Up @@ -239,12 +245,12 @@ private void setWikidataEditCount() {
if (StringUtils.isNullOrWhiteSpace(userName)) {
return;
}
okHttpJsonApiClient.getWikidataEdits(userName)
compositeDisposable.add(okHttpJsonApiClient.getWikidataEdits(userName)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(edits -> wikidataEditsText.setText(String.valueOf(edits)), e -> {
Timber.e("Error:" + e);
});
}));
}

private void showSnackBarWithRetry() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,12 @@ protected void onSaveInstanceState(Bundle outState) {
* Makes API call to check if user is blocked from Commons. If the user is blocked, a snackbar
* is created to notify the user
*/
protected void showBlockStatus()
{
Observable.fromCallable(() -> mediaWikiApi.isUserBlockedFromCommons())
protected void showBlockStatus() {
compositeDisposable.add(Observable.fromCallable(() -> mediaWikiApi.isUserBlockedFromCommons())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.filter(result -> result)
.subscribe(result -> ViewUtil.showShortSnackbar(findViewById(android.R.id.content), R.string.block_notification)
);
));
}
}
7 changes: 5 additions & 2 deletions app/src/main/java/fr/free/nrw/commons/auth/LoginActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
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;

Expand Down Expand Up @@ -83,6 +84,7 @@ public class LoginActivity extends AccountAuthenticatorActivity {
ProgressDialog progressDialog;
private AppCompatDelegate delegate;
private LoginTextWatcher textWatcher = new LoginTextWatcher();
private CompositeDisposable compositeDisposable = new CompositeDisposable();

private Boolean loginCurrentlyInProgress = false;
private Boolean errorMessageShown = false;
Expand Down Expand Up @@ -195,6 +197,7 @@ protected void onResume() {

@Override
protected void onDestroy() {
compositeDisposable.clear();
try {
// To prevent leaked window when finish() is called, see http://stackoverflow.com/questions/32065854/activity-has-leaked-window-at-alertdialog-show-method
if (progressDialog != null && progressDialog.isShowing()) {
Expand All @@ -219,10 +222,10 @@ private void performLogin() {
String twoFactorCode = twoFactorEdit.getText().toString();

showLoggingProgressBar();
Observable.fromCallable(() -> login(username, password, twoFactorCode))
compositeDisposable.add(Observable.fromCallable(() -> login(username, password, twoFactorCode))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(result -> handleLogin(username, rawUsername, password, result));
.subscribe(result -> handleLogin(username, rawUsername, password, result)));
}

private String login(String username, String password, String twoFactorCode) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
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;

Expand All @@ -41,6 +42,7 @@ public class BookmarkPicturesFragment extends DaggerFragment {
private static final int TIMEOUT_SECONDS = 15;

private GridViewAdapter gridAdapter;
private CompositeDisposable compositeDisposable = new CompositeDisposable();

@BindView(R.id.statusMessage) TextView statusTextView;
@BindView(R.id.loadingImagesProgressBar) ProgressBar progressBar;
Expand Down Expand Up @@ -82,6 +84,12 @@ public void onStop() {
controller.stop();
}

@Override
public void onDestroy() {
super.onDestroy();
compositeDisposable.clear();
}

@Override
public void onResume() {
super.onResume();
Expand Down Expand Up @@ -113,11 +121,11 @@ private void initList() {
progressBar.setVisibility(VISIBLE);
statusTextView.setVisibility(GONE);

Observable.fromCallable(() -> controller.loadBookmarkedPictures())
compositeDisposable.add(Observable.fromCallable(() -> controller.loadBookmarkedPictures())
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.timeout(TIMEOUT_SECONDS, TimeUnit.SECONDS)
.subscribe(this::handleSuccess, this::handleError);
.subscribe(this::handleSuccess, this::handleError));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
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;

Expand All @@ -51,6 +52,7 @@ public class CategoryImagesListFragment extends DaggerFragment {
@BindView(R.id.loadingImagesProgressBar) ProgressBar progressBar;
@BindView(R.id.categoryImagesList) GridView gridView;
@BindView(R.id.parentLayout) RelativeLayout parentLayout;
private CompositeDisposable compositeDisposable = new CompositeDisposable();
private boolean hasMoreImages = true;
private boolean isLoading = true;
private String categoryName = null;
Expand All @@ -74,6 +76,12 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
initViews();
}

@Override
public void onDestroy() {
super.onDestroy();
compositeDisposable.clear();
}

/**
* Initializes the UI elements for the fragment
* Setup the grid view to and scroll listener for it
Expand Down Expand Up @@ -109,11 +117,11 @@ private void initList() {

isLoading = true;
progressBar.setVisibility(VISIBLE);
Observable.fromCallable(() -> controller.getCategoryImages(categoryName))
compositeDisposable.add(Observable.fromCallable(() -> controller.getCategoryImages(categoryName))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.timeout(TIMEOUT_SECONDS, TimeUnit.SECONDS)
.subscribe(this::handleSuccess, this::handleError);
.subscribe(this::handleSuccess, this::handleError));
}

/**
Expand Down Expand Up @@ -215,11 +223,11 @@ private void fetchMoreImages() {
}

progressBar.setVisibility(VISIBLE);
Observable.fromCallable(() -> controller.getCategoryImages(categoryName))
compositeDisposable.add(Observable.fromCallable(() -> controller.getCategoryImages(categoryName))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.timeout(TIMEOUT_SECONDS, TimeUnit.SECONDS)
.subscribe(this::handleSuccess, this::handleError);
.subscribe(this::handleSuccess, this::handleError));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,17 +97,17 @@ public void initSubCategoryList() {
}
progressBar.setVisibility(View.VISIBLE);
if (!isParentCategory){
Observable.fromCallable(() -> mwApi.getSubCategoryList(categoryName))
compositeDisposable.add(Observable.fromCallable(() -> mwApi.getSubCategoryList(categoryName))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.timeout(TIMEOUT_SECONDS, TimeUnit.SECONDS)
.subscribe(this::handleSuccess, this::handleError);
.subscribe(this::handleSuccess, this::handleError));
}else {
Observable.fromCallable(() -> mwApi.getParentCategoryList(categoryName))
compositeDisposable.add(Observable.fromCallable(() -> mwApi.getParentCategoryList(categoryName))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.timeout(TIMEOUT_SECONDS, TimeUnit.SECONDS)
.subscribe(this::handleSuccess, this::handleError);
.subscribe(this::handleSuccess, this::handleError));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import timber.log.Timber;

Expand Down Expand Up @@ -101,7 +100,6 @@ public class ContributionsFragment
@BindView(R.id.card_view_nearby) public NearbyNotificationCardView nearbyNotificationCardView;
@BindView(R.id.campaigns_view) CampaignView campaignView;

private Disposable placesDisposable;
private LatLng curLatLng;

private boolean firstLocationUpdate = true;
Expand Down Expand Up @@ -603,15 +601,15 @@ private void displayYouWontSeeNearbyMessage() {
private void updateClosestNearbyCardViewInfo() {
curLatLng = locationManager.getLastLocation();

placesDisposable = Observable.fromCallable(() -> nearbyController
compositeDisposable.add(Observable.fromCallable(() -> nearbyController
.loadAttractionsFromLocation(curLatLng, curLatLng, true, false)) // thanks to boolean, it will only return closest result
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::updateNearbyNotification,
throwable -> {
Timber.d(throwable);
updateNearbyNotification(null);
});
}));
}

private void updateNearbyNotification(@Nullable NearbyController.NearbyPlacesInfo nearbyPlacesInfo) {
Expand Down Expand Up @@ -648,10 +646,6 @@ public void onDestroy() {
isUploadServiceConnected = false;
}
}

if (placesDisposable != null) {
placesDisposable.dispose();
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -307,11 +307,11 @@ public boolean onCreateOptionsMenu(Menu menu) {

@SuppressLint("CheckResult")
private void setNotificationCount() {
Observable.fromCallable(() -> notificationController.getNotifications(false))
compositeDisposable.add(Observable.fromCallable(() -> notificationController.getNotifications(false))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(this::initNotificationViews,
throwable -> Timber.e(throwable, "Error occurred while loading notifications"));
throwable -> Timber.e(throwable, "Error occurred while loading notifications")));
}

private void initNotificationViews(List<Notification> notificationList) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,27 @@
import dagger.android.AndroidInjector;
import dagger.android.DispatchingAndroidInjector;
import dagger.android.support.HasSupportFragmentInjector;
import io.reactivex.disposables.CompositeDisposable;

public abstract class CommonsDaggerSupportFragment extends Fragment implements HasSupportFragmentInjector {

@Inject
DispatchingAndroidInjector<Fragment> childFragmentInjector;

protected CompositeDisposable compositeDisposable = new CompositeDisposable();

@Override
public void onAttach(Context context) {
inject();
super.onAttach(context);
}

@Override
public void onDestroy() {
super.onDestroy();
compositeDisposable.clear();
}

@Override
public AndroidInjector<Fragment> supportFragmentInjector() {
return childFragmentInjector;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public void setTabs() {

viewPagerAdapter.setTabData(fragmentList, titleList);
viewPagerAdapter.notifyDataSetChanged();
RxSearchView.queryTextChanges(searchView)
compositeDisposable.add(RxSearchView.queryTextChanges(searchView)
.takeUntil(RxView.detaches(searchView))
.debounce(500, TimeUnit.MILLISECONDS)
.observeOn(AndroidSchedulers.mainThread())
Expand All @@ -120,7 +120,7 @@ public void setTabs() {
searchHistoryContainer.setVisibility(View.VISIBLE);
}
}
);
));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
Expand Down Expand Up @@ -136,12 +135,12 @@ public void updateCategoryList(String query) {
progressBar.setVisibility(GONE);
queryList.clear();
categoriesAdapter.clear();
Observable.fromCallable(() -> mwApi.searchCategory(query,queryList.size()))
compositeDisposable.add(Observable.fromCallable(() -> mwApi.searchCategory(query,queryList.size()))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.timeout(TIMEOUT_SECONDS, TimeUnit.SECONDS)
.doOnSubscribe(disposable -> saveQuery(query))
.subscribe(this::handleSuccess, this::handleError);
.subscribe(this::handleSuccess, this::handleError));
}


Expand All @@ -152,11 +151,11 @@ public void addCategoriesToList(String query) {
this.query = query;
bottomProgressBar.setVisibility(View.VISIBLE);
progressBar.setVisibility(GONE);
Observable.fromCallable(() -> mwApi.searchCategory(query,queryList.size()))
compositeDisposable.add(Observable.fromCallable(() -> mwApi.searchCategory(query,queryList.size()))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.timeout(TIMEOUT_SECONDS, TimeUnit.SECONDS)
.subscribe(this::handlePaginationSuccess, this::handleError);
.subscribe(this::handlePaginationSuccess, this::handleError));
}

/**
Expand Down
Loading