1/* 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 androidx.work.impl.constraints.trackers; 17 18import android.content.Context; 19import android.support.annotation.RestrictTo; 20import android.util.Log; 21 22import androidx.work.impl.constraints.ConstraintListener; 23 24import java.util.LinkedHashSet; 25import java.util.Set; 26 27/** 28 * A base for tracking constraints and notifying listeners of changes. 29 * 30 * @param <T> the constraint data type observed by this tracker 31 * @hide 32 */ 33@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) 34public abstract class ConstraintTracker<T> { 35 36 private static final String TAG = "ConstraintTracker"; 37 38 protected final Context mAppContext; 39 private final Set<ConstraintListener<T>> mListeners = new LinkedHashSet<>(); 40 private T mCurrentState; 41 42 ConstraintTracker(Context context) { 43 mAppContext = context.getApplicationContext(); 44 } 45 46 /** 47 * Add the given listener for tracking. 48 * This may cause {@link #getInitialState()} and {@link #startTracking()} to be invoked. 49 * If a state is set, this will immediately notify the given listener. 50 * 51 * @param listener The target listener to start notifying 52 */ 53 public void addListener(ConstraintListener<T> listener) { 54 if (mListeners.add(listener)) { 55 if (mListeners.size() == 1) { 56 mCurrentState = getInitialState(); 57 Log.d(TAG, String.format("%s: initial state = %s", getClass().getSimpleName(), 58 mCurrentState)); 59 startTracking(); 60 } 61 listener.onConstraintChanged(mCurrentState); 62 } 63 } 64 65 /** 66 * Remove the given listener from tracking. 67 * 68 * @param listener The listener to stop notifying. 69 */ 70 public void removeListener(ConstraintListener<T> listener) { 71 if (mListeners.remove(listener) && mListeners.isEmpty()) { 72 stopTracking(); 73 } 74 } 75 76 /** 77 * Sets the state of the constraint. 78 * If state is has not changed, nothing happens. 79 * 80 * @param newState new state of constraint 81 */ 82 public void setState(T newState) { 83 if (mCurrentState == newState 84 || (mCurrentState != null && mCurrentState.equals(newState))) { 85 return; 86 } 87 mCurrentState = newState; 88 for (ConstraintListener<T> listener : mListeners) { 89 listener.onConstraintChanged(mCurrentState); 90 } 91 } 92 93 /** 94 * Determines the initial state of the constraint being tracked. 95 */ 96 public abstract T getInitialState(); 97 98 /** 99 * Start tracking for constraint state changes. 100 */ 101 public abstract void startTracking(); 102 103 /** 104 * Stop tracking for constraint state changes. 105 */ 106 public abstract void stopTracking(); 107} 108