blob: 6891eab61f7db4b713769c1fbe42fb5b42f6b281 [file] [log] [blame]
/*
* Copyright 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.recyclerview.selection;
import static android.support.annotation.RestrictTo.Scope.LIBRARY_GROUP;
import static android.support.v4.util.Preconditions.checkState;
import static androidx.recyclerview.selection.Shared.DEBUG;
import android.content.Loader;
import android.support.annotation.MainThread;
import android.support.annotation.Nullable;
import android.support.annotation.RestrictTo;
import android.util.Log;
/**
* ContentLock provides a mechanism to block content from reloading while selection
* activities like gesture and band selection are active. Clients using live data
* (data loaded, for example by a {@link Loader}), should route calls to load
* content through this lock using {@link ContentLock#runWhenUnlocked(Runnable)}.
*
* @hide
*/
@RestrictTo(LIBRARY_GROUP)
public final class ContentLock {
private static final String TAG = "ContentLock";
private int mLocks = 0;
private @Nullable Runnable mCallback;
/**
* Increment the block count by 1
*/
@MainThread
synchronized void block() {
mLocks++;
if (DEBUG) Log.v(TAG, "Incremented content lock count to " + mLocks + ".");
}
/**
* Decrement the block count by 1; If no other object is trying to block and there exists some
* callback, that callback will be run
*/
@MainThread
synchronized void unblock() {
checkState(mLocks > 0);
mLocks--;
if (DEBUG) Log.v(TAG, "Decremented content lock count to " + mLocks + ".");
if (mLocks == 0 && mCallback != null) {
mCallback.run();
mCallback = null;
}
}
/**
* Attempts to run the given Runnable if not-locked, or else the Runnable is set to be ran next
* (replacing any previous set Runnables).
*/
@SuppressWarnings("unused")
public synchronized void runWhenUnlocked(Runnable runnable) {
if (mLocks == 0) {
runnable.run();
} else {
mCallback = runnable;
}
}
/**
* Allows other selection code to perform a precondition check asserting the state is locked.
*/
void checkLocked() {
checkState(mLocks > 0);
}
/**
* Allows other selection code to perform a precondition check asserting the state is unlocked.
*/
void checkUnlocked() {
checkState(mLocks == 0);
}
}