blob: 239bf7a6608a115a221c2e183e5d1f10af5807fd [file] [log] [blame]
Riddle Hsu0c375982018-06-21 22:06:43 +08001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.android.documentsui;
17
shawnlinbac1b4e2019-03-26 15:19:46 +080018import static com.android.documentsui.base.SharedMinimal.DEBUG;
19
20import android.util.Log;
21
Riddle Hsu0c375982018-06-21 22:06:43 +080022import androidx.annotation.GuardedBy;
Leon Liaoefcd5112018-11-02 10:57:56 +080023import androidx.annotation.Nullable;
Riddle Hsu0c375982018-06-21 22:06:43 +080024import androidx.recyclerview.selection.OperationMonitor;
25
26/**
27 * ContentLock provides a mechanism to block content from reloading while selection
28 * activities like gesture and band selection are active. Clients using live data
29 * (data loaded, for example by a {@link Loader}), should route calls to load
30 * content through this lock using {@link ContentLock#runWhenUnlocked(Runnable)}.
31 */
32public final class ContentLock {
33
shawnlinbac1b4e2019-03-26 15:19:46 +080034 private static final String TAG = "ContentLock";
35
Riddle Hsu0c375982018-06-21 22:06:43 +080036 private final OperationMonitor mMonitor = new OperationMonitor();
37
38 @GuardedBy("this")
39 private @Nullable Runnable mCallback;
40
41 public ContentLock() {
42 mMonitor.addListener(() -> {
shawnlinbac1b4e2019-03-26 15:19:46 +080043 if (DEBUG) {
44 Log.d(TAG, "monitor listener, is locked : " + isLocked());
45 }
Riddle Hsu0c375982018-06-21 22:06:43 +080046 if (!isLocked()) {
47 synchronized (this) {
48 final Runnable callback = mCallback;
49 if (callback != null) {
50 callback.run();
51 mCallback = null;
52 }
53 }
54 }
55 });
56 }
57
58 public OperationMonitor getMonitor() {
59 return mMonitor;
60 }
61
62 /**
63 * Returns true if locked.
64 */
65 private boolean isLocked() {
66 return mMonitor.isStarted();
67 }
68
69 /**
70 * Attempts to run the given Runnable if not-locked, or else the Runnable is set to be ran next
71 * (replacing any previous set Runnables).
72 */
73 public synchronized void runWhenUnlocked(Runnable runnable) {
shawnlinbac1b4e2019-03-26 15:19:46 +080074 if (DEBUG) {
75 Log.d(TAG, "run when unlock, is locked : " + isLocked());
76 }
Riddle Hsu0c375982018-06-21 22:06:43 +080077 if (!isLocked()) {
78 runnable.run();
79 } else {
80 mCallback = runnable;
81 }
82 }
83}