public abstract class

ConstraintTracker<T>

extends java.lang.Object

 java.lang.Object

↳androidx.work.impl.constraints.trackers.ConstraintTracker<T>

Subclasses:

BatteryNotLowTracker, StorageNotLowTracker, NetworkStateTracker, BroadcastReceiverConstraintTracker<T>, BatteryChargingTracker

Overview

A base for tracking constraints and notifying listeners of changes.

Summary

Fields
protected final ContextmAppContext

protected final TaskExecutormTaskExecutor

Methods
public voidaddListener(ConstraintListener<java.lang.Object> listener)

Add the given listener for tracking.

public abstract java.lang.ObjectgetInitialState()

Determines the initial state of the constraint being tracked.

public voidremoveListener(ConstraintListener<java.lang.Object> listener)

Remove the given listener from tracking.

public voidsetState(java.lang.Object newState)

Sets the state of the constraint.

public abstract voidstartTracking()

Start tracking for constraint state changes.

public abstract voidstopTracking()

Stop tracking for constraint state changes.

from java.lang.Objectclone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Fields

protected final TaskExecutor mTaskExecutor

protected final Context mAppContext

Methods

public void addListener(ConstraintListener<java.lang.Object> listener)

Add the given listener for tracking. This may cause ConstraintTracker.getInitialState() and ConstraintTracker.startTracking() to be invoked. If a state is set, this will immediately notify the given listener.

Parameters:

listener: The target listener to start notifying

public void removeListener(ConstraintListener<java.lang.Object> listener)

Remove the given listener from tracking.

Parameters:

listener: The listener to stop notifying.

public void setState(java.lang.Object newState)

Sets the state of the constraint. If state is has not changed, nothing happens.

Parameters:

newState: new state of constraint

public abstract java.lang.Object getInitialState()

Determines the initial state of the constraint being tracked.

public abstract void startTracking()

Start tracking for constraint state changes.

public abstract void stopTracking()

Stop tracking for constraint state changes.

Source

/*
 * Copyright (C) 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.work.impl.constraints.trackers;

import android.content.Context;

import androidx.annotation.NonNull;
import androidx.annotation.RestrictTo;
import androidx.work.Logger;
import androidx.work.impl.constraints.ConstraintListener;
import androidx.work.impl.utils.taskexecutor.TaskExecutor;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

/**
 * A base for tracking constraints and notifying listeners of changes.
 *
 * @param <T> the constraint data type observed by this tracker
 * @hide
 */
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public abstract class ConstraintTracker<T> {

    private static final String TAG = Logger.tagWithPrefix("ConstraintTracker");

    protected final TaskExecutor mTaskExecutor;
    protected final Context mAppContext;

    private final Object mLock = new Object();
    private final Set<ConstraintListener<T>> mListeners = new LinkedHashSet<>();

    // Synthetic access
    T mCurrentState;

    ConstraintTracker(@NonNull Context context, @NonNull TaskExecutor taskExecutor) {
        mAppContext = context.getApplicationContext();
        mTaskExecutor = taskExecutor;
    }

    /**
     * Add the given listener for tracking.
     * This may cause {@link #getInitialState()} and {@link #startTracking()} to be invoked.
     * If a state is set, this will immediately notify the given listener.
     *
     * @param listener The target listener to start notifying
     */
    public void addListener(ConstraintListener<T> listener) {
        synchronized (mLock) {
            if (mListeners.add(listener)) {
                if (mListeners.size() == 1) {
                    mCurrentState = getInitialState();
                    Logger.get().debug(TAG, String.format("%s: initial state = %s",
                            getClass().getSimpleName(),
                            mCurrentState));
                    startTracking();
                }
                listener.onConstraintChanged(mCurrentState);
            }
        }
    }

    /**
     * Remove the given listener from tracking.
     *
     * @param listener The listener to stop notifying.
     */
    public void removeListener(ConstraintListener<T> listener) {
        synchronized (mLock) {
            if (mListeners.remove(listener) && mListeners.isEmpty()) {
                stopTracking();
            }
        }
    }

    /**
     * Sets the state of the constraint.
     * If state is has not changed, nothing happens.
     *
     * @param newState new state of constraint
     */
    public void setState(T newState) {
        synchronized (mLock) {
            if (mCurrentState == newState
                    || (mCurrentState != null && mCurrentState.equals(newState))) {
                return;
            }
            mCurrentState = newState;

            // onConstraintChanged may lead to calls to addListener or removeListener.
            // This can potentially result in a modification to the set while it is being
            // iterated over, so we handle this by creating a copy and using that for
            // iteration.
            final List<ConstraintListener<T>> listenersList = new ArrayList<>(mListeners);
            mTaskExecutor.getMainThreadExecutor().execute(new Runnable() {
                @Override
                public void run() {
                    for (ConstraintListener<T> listener : listenersList) {
                        listener.onConstraintChanged(mCurrentState);
                    }
                }
            });
        }
    }

    /**
     * Determines the initial state of the constraint being tracked.
     */
    public abstract T getInitialState();

    /**
     * Start tracking for constraint state changes.
     */
    public abstract void startTracking();

    /**
     * Stop tracking for constraint state changes.
     */
    public abstract void stopTracking();
}