123 lines
5 KiB
Java
123 lines
5 KiB
Java
|
package androidx.appcompat.content.res;
|
||
|
|
||
|
import android.annotation.SuppressLint;
|
||
|
import android.content.Context;
|
||
|
import android.content.res.ColorStateList;
|
||
|
import android.content.res.Configuration;
|
||
|
import android.content.res.Resources;
|
||
|
import android.graphics.drawable.Drawable;
|
||
|
import android.os.Build;
|
||
|
import android.util.Log;
|
||
|
import android.util.SparseArray;
|
||
|
import android.util.TypedValue;
|
||
|
import androidx.annotation.ColorRes;
|
||
|
import androidx.annotation.DrawableRes;
|
||
|
import androidx.annotation.NonNull;
|
||
|
import androidx.annotation.Nullable;
|
||
|
import androidx.appcompat.widget.ResourceManagerInternal;
|
||
|
import androidx.core.content.ContextCompat;
|
||
|
import androidx.core.content.res.ColorStateListInflaterCompat;
|
||
|
import java.util.WeakHashMap;
|
||
|
@SuppressLint({"RestrictedAPI"})
|
||
|
public final class AppCompatResources {
|
||
|
private static final String LOG_TAG = "AppCompatResources";
|
||
|
private static final ThreadLocal<TypedValue> TL_TYPED_VALUE = new ThreadLocal<>();
|
||
|
private static final Object sColorStateCacheLock = new Object();
|
||
|
private static final WeakHashMap<Context, SparseArray<ColorStateListCacheEntry>> sColorStateCaches = new WeakHashMap<>(0);
|
||
|
|
||
|
public static class ColorStateListCacheEntry {
|
||
|
public final Configuration configuration;
|
||
|
public final ColorStateList value;
|
||
|
|
||
|
public ColorStateListCacheEntry(@NonNull ColorStateList colorStateList, @NonNull Configuration configuration) {
|
||
|
this.value = colorStateList;
|
||
|
this.configuration = configuration;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private AppCompatResources() {
|
||
|
}
|
||
|
|
||
|
private static void addColorStateListToCache(@NonNull Context context, @ColorRes int i, @NonNull ColorStateList colorStateList) {
|
||
|
synchronized (sColorStateCacheLock) {
|
||
|
WeakHashMap<Context, SparseArray<ColorStateListCacheEntry>> weakHashMap = sColorStateCaches;
|
||
|
SparseArray<ColorStateListCacheEntry> sparseArray = weakHashMap.get(context);
|
||
|
if (sparseArray == null) {
|
||
|
sparseArray = new SparseArray<>();
|
||
|
weakHashMap.put(context, sparseArray);
|
||
|
}
|
||
|
sparseArray.append(i, new ColorStateListCacheEntry(colorStateList, context.getResources().getConfiguration()));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Nullable
|
||
|
private static ColorStateList getCachedColorStateList(@NonNull Context context, @ColorRes int i) {
|
||
|
ColorStateListCacheEntry colorStateListCacheEntry;
|
||
|
synchronized (sColorStateCacheLock) {
|
||
|
SparseArray<ColorStateListCacheEntry> sparseArray = sColorStateCaches.get(context);
|
||
|
if (!(sparseArray == null || sparseArray.size() <= 0 || (colorStateListCacheEntry = sparseArray.get(i)) == null)) {
|
||
|
if (colorStateListCacheEntry.configuration.equals(context.getResources().getConfiguration())) {
|
||
|
return colorStateListCacheEntry.value;
|
||
|
}
|
||
|
sparseArray.remove(i);
|
||
|
}
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public static ColorStateList getColorStateList(@NonNull Context context, @ColorRes int i) {
|
||
|
if (Build.VERSION.SDK_INT >= 23) {
|
||
|
return context.getColorStateList(i);
|
||
|
}
|
||
|
ColorStateList cachedColorStateList = getCachedColorStateList(context, i);
|
||
|
if (cachedColorStateList != null) {
|
||
|
return cachedColorStateList;
|
||
|
}
|
||
|
ColorStateList inflateColorStateList = inflateColorStateList(context, i);
|
||
|
if (inflateColorStateList == null) {
|
||
|
return ContextCompat.getColorStateList(context, i);
|
||
|
}
|
||
|
addColorStateListToCache(context, i, inflateColorStateList);
|
||
|
return inflateColorStateList;
|
||
|
}
|
||
|
|
||
|
@Nullable
|
||
|
public static Drawable getDrawable(@NonNull Context context, @DrawableRes int i) {
|
||
|
return ResourceManagerInternal.get().getDrawable(context, i);
|
||
|
}
|
||
|
|
||
|
@NonNull
|
||
|
private static TypedValue getTypedValue() {
|
||
|
ThreadLocal<TypedValue> threadLocal = TL_TYPED_VALUE;
|
||
|
TypedValue typedValue = threadLocal.get();
|
||
|
if (typedValue != null) {
|
||
|
return typedValue;
|
||
|
}
|
||
|
TypedValue typedValue2 = new TypedValue();
|
||
|
threadLocal.set(typedValue2);
|
||
|
return typedValue2;
|
||
|
}
|
||
|
|
||
|
@Nullable
|
||
|
private static ColorStateList inflateColorStateList(Context context, int i) {
|
||
|
if (isColorInt(context, i)) {
|
||
|
return null;
|
||
|
}
|
||
|
Resources resources = context.getResources();
|
||
|
try {
|
||
|
return ColorStateListInflaterCompat.createFromXml(resources, resources.getXml(i), context.getTheme());
|
||
|
} catch (Exception e) {
|
||
|
Log.e("AppCompatResources", "Failed to inflate ColorStateList, leaving it to the framework", e);
|
||
|
return null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static boolean isColorInt(@NonNull Context context, @ColorRes int i) {
|
||
|
Resources resources = context.getResources();
|
||
|
TypedValue typedValue = getTypedValue();
|
||
|
resources.getValue(i, typedValue, true);
|
||
|
int i2 = typedValue.type;
|
||
|
return i2 >= 28 && i2 <= 31;
|
||
|
}
|
||
|
}
|