3

我有实现 Closeable 接口的对象,并且希望在我的 ViewModel 清晰时调用 close() 方法。我知道要实现 ViewModel 的 onCleared 方法,但我想在 ViewModel 中使用 mBagOfTags。mBagOfTags 处理可关闭对象(在 clear 方法中调用 close 方法)并且不想在 ViewModel 中创建新的地图对象。如何使用 ViewModel 的 mBagOfTags ?

ViewModel 中的 mBagOfTags 及其成员函数是包私有访问修饰符。

这是android团队开发的ViewModel类。

package androidx.lifecycle;

public abstract class ViewModel {
// Can't use ConcurrentHashMap, because it can lose values on old apis (see b/37042460)
@Nullable
private final Map<String, Object> mBagOfTags = new HashMap<>();
private volatile boolean mCleared = false;

/**
 * This method will be called when this ViewModel is no longer used and will be destroyed.
 * <p>
 * It is useful when ViewModel observes some data and you need to clear this subscription to
 * prevent a leak of this ViewModel.
 */
@SuppressWarnings("WeakerAccess")
protected void onCleared() {
}

@MainThread
final void clear() {
    mCleared = true;
    // Since clear() is final, this method is still called on mock objects
    // and in those cases, mBagOfTags is null. It'll always be empty though
    // because setTagIfAbsent and getTag are not final so we can skip
    // clearing it
    if (mBagOfTags != null) {
        synchronized (mBagOfTags) {
            for (Object value : mBagOfTags.values()) {
                // see comment for the similar call in setTagIfAbsent
                closeWithRuntimeException(value);
            }
        }
    }
    onCleared();
}

/**
 * Sets a tag associated with this viewmodel and a key.
 * If the given {@code newValue} is {@link Closeable},
 * it will be closed once {@link #clear()}.
 * <p>
 * If a value was already set for the given key, this call does nothing and
 * returns currently associated value, the given {@code newValue} would be ignored
 * <p>
 * If the ViewModel was already cleared then close() would be called on the returned object if
 * it implements {@link Closeable}. The same object may receive multiple close calls, so method
 * should be idempotent.
 */
@SuppressWarnings("unchecked")
<T> T setTagIfAbsent(String key, T newValue) {
    T previous;
    synchronized (mBagOfTags) {
        previous = (T) mBagOfTags.get(key);
        if (previous == null) {
            mBagOfTags.put(key, newValue);
        }
    }
    T result = previous == null ? newValue : previous;
    if (mCleared) {
        // It is possible that we'll call close() multiple times on the same object, but
        // Closeable interface requires close method to be idempotent:
        // "if the stream is already closed then invoking this method has no effect." (c)
        closeWithRuntimeException(result);
    }
    return result;
}

/**
 * Returns the tag associated with this viewmodel and the specified key.
 */
@SuppressWarnings({"TypeParameterUnusedInFormals", "unchecked"})
<T> T getTag(String key) {
    if (mBagOfTags == null) {
        return null;
    }
    synchronized (mBagOfTags) {
        return (T) mBagOfTags.get(key);
    }
}

private static void closeWithRuntimeException(Object obj) {
    if (obj instanceof Closeable) {
        try {
            ((Closeable) obj).close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
}

我的 ViewModel 在另一个包中。

4

1 回答 1

0

您可以将文件的包设置为与 ViewModel 包相同。写入文件的第一行:“package androidx.lifecycle”

于 2022-02-07T21:37:22.013 回答