From 371312ef650c652c3c522e5cb5ccd17a7a88ab97 Mon Sep 17 00:00:00 2001 From: Peter Serwylo Date: Thu, 2 Jun 2016 14:24:04 +1000 Subject: [PATCH] Replace rate limiting code with RX. Now that we have RX as a dependency, it can be used as a nice concise way to achieve certain tasks. Rate limiting is one thing it does well - via the `debounce` mechanism: http://reactivex.io/documentation/operators/debounce.html The semantics of this code is the same as before, limiting content change notifications to one per second. --- .../data/InstalledAppProviderService.java | 61 +++++++++---------- 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java b/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java index 3dc103bac..1a9ff48b8 100644 --- a/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java +++ b/app/src/main/java/org/fdroid/fdroid/data/InstalledAppProviderService.java @@ -14,10 +14,12 @@ import org.fdroid.fdroid.Utils; import java.io.File; import java.util.List; import java.util.Map; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; +import rx.functions.Action1; +import rx.schedulers.Schedulers; +import rx.subjects.PublishSubject; + /** * Handles all updates to {@link InstalledAppProvider}, whether checking the contents * versus what Android says is installed, or processing {@link Intent}s that come @@ -39,13 +41,34 @@ public class InstalledAppProviderService extends IntentService { private static final String EXTRA_PACKAGE_INFO = "org.fdroid.fdroid.data.extra.PACKAGE_INFO"; - private ScheduledExecutorService worker; - private boolean notifyChangeNeedsSending; + /** + * This is for notifing the users of this {@link android.content.ContentProvider} + * that the contents has changed. Since {@link Intent}s can come in slow + * or fast, and this can trigger a lot of UI updates, the actual + * notifications are rate limited to one per second. + */ + private PublishSubject notifyEvents; public InstalledAppProviderService() { super("InstalledAppProviderService"); } + @Override + public void onCreate() { + super.onCreate(); + notifyEvents = PublishSubject.create(); + notifyEvents.debounce(1, TimeUnit.SECONDS) + .subscribeOn(Schedulers.newThread()) + .subscribe(new Action1() { + @Override + public void call(Void voidArg) { + Utils.debugLog(TAG, "Notifying content providers (so they can update the relevant views)."); + getContentResolver().notifyChange(AppProvider.getContentUri(), null); + getContentResolver().notifyChange(ApkProvider.getContentUri(), null); + } + }); + } + /** * Inserts an app into {@link InstalledAppProvider} based on a {@code package:} {@link Uri}. * This has no checks for whether it is inserting an exact duplicate, whatever is provided @@ -134,7 +157,7 @@ public class InstalledAppProviderService extends IntentService { } else if (ACTION_DELETE.equals(action)) { deleteAppFromDb(this, packageName); } - notifyChange(); + notifyEvents.onNext(null); } } @@ -172,32 +195,4 @@ public class InstalledAppProviderService extends IntentService { Uri uri = InstalledAppProvider.getAppUri(packageName); context.getContentResolver().delete(uri, null, null); } - - /** - * This notifies the users of this {@link android.content.ContentProvider} - * that the contents has changed. Since {@link Intent}s can come in slow - * or fast, and this can trigger a lot of UI updates, the actual - * notifications are rate limited to one per second. - */ - private void notifyChange() { - notifyChangeNeedsSending = true; - Runnable task = new Runnable() { - @Override - public void run() { - if (notifyChangeNeedsSending) { - Utils.debugLog(TAG, "Notifying content providers (so they can update the relevant views)."); - getContentResolver().notifyChange(AppProvider.getContentUri(), null); - getContentResolver().notifyChange(ApkProvider.getContentUri(), null); - notifyChangeNeedsSending = false; - } else { - worker.shutdown(); - worker = null; - } - } - }; - if (worker == null || worker.isShutdown()) { - worker = Executors.newSingleThreadScheduledExecutor(); - worker.scheduleAtFixedRate(task, 0, 1, TimeUnit.SECONDS); - } - } } \ No newline at end of file