getDrawable()キャッシュの問題点
2022-03-18 04:24:23
我々はしばしばgetContext().getResources().getDrawable()によってDrawable()を取得し、ときにAndroidのメカニズムはキャッシュ機構を使用しているので、直接色を変更するにはsetColorFilter()、他のgetDrawable()の色も変えることができます。我々はしばしば私たち自身の画像は不可解に他の色に変更されていることを我々のプロジェクトで発生します。
getDrawable()のソースコードを見てみましょう。
public Drawable getDrawable(int id, @Nullable Theme theme) throws NotFoundException {
......
Load the drawable
final Drawable res = loadDrawable(value, id, theme);
synchronized (mAccessLock) {
if (mTmpValue == null) {
mTmpValue = value;
}
}
return res;
}
/*package*/ Drawable loadDrawable(TypedValue value, int id, Theme theme) throws NotFoundException {
if (TRACE_FOR_PRELOAD) {
// Log only framework resources
if ((id >>> > 24) == 0x1) {
final String name = getResourceName(id);
if (name ! = null) {
Log.d("PreloadDrawable", name);
}
}
}
final boolean isColorDrawable;
final ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>> caches;
final long key;
//Drawable is divided into 2 types, colorDrawable (such as R.color.xxx) and other Drawable, first calculate the cache index key
if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT
&& value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
isColorDrawable = true;
caches = mColorDrawableCache;
key = value.data;
} else {
isColorDrawable = false;
caches = mDrawableCache;
key = (((long) value.assetCookie) << 32) | value.data;
}
// first get from the cache where you want to set the theme
if (!mPreloading) {
final Drawable cachedDrawable = getCachedDrawable(caches, key, theme);
if (cachedDrawable ! = null) {
return cachedDrawable;
}
}
// Get ConstantState from cache, subclass BitmapState mainly caches Bitmap and Paint, so use the same ConstantState to affect each other
final ConstantState cs;
if (isColorDrawable) {
cs = sPreloadedColorDrawables.get(key);
} else {
cs = sPreloadedDrawables[mConfiguration.getLayoutDirection()].get(key);
}
//new out drawable
final Drawable dr;
if (cs ! = null) {
final Drawable clonedDr = cs.newDrawable(this);
if (theme ! = null) {
dr = clonedDr.mutate();// notice here, this will recreate a ConstantState
dr.applyTheme(theme);
dr.clearMutated();
} else {
dr = clonedDr;
}
} else if (isColorDrawable) {
// no cached color, create directly
dr = new ColorDrawable(value.data);
} else {
//go back and create the corresponding drawable type
dr = loadDrawableForCookie(value, id, theme);
}
//Cache the ConstantState
if (dr ! = null) {
dr.setChangingConfigurations(value.changingConfigurations);
cacheDrawable(value, theme, isColorDrawable, caches, key, dr);
}
return dr;
}
インターフェイス setColorFilter メソッドを見てみましょう。
BitmapDrawableの場合
@Override
public void setColorFilter(ColorFilter cf) {
// modifies the Oaint property of the State, which is naturally affected when the State is fetched through the cache
mBitmapState.mPaint.setColorFilter(cf);
invalidateSelf();
}
解決策は、上で述べたmutateメソッドで
@Override
public Drawable mutate() {
if (!mMutated && super.mutate() == this) {
// Create BitmapState
mBitmapState = new BitmapState(mBitmapState);
mMutated = true;
}
return this;
}
//
BitmapState(BitmapState bitmapState) {
mBitmap = bitmapState.mBitmap;
mTint = bitmapState.mTint;
mTintMode = bitmapState.mTintMode. mTintMode = bitmapState.mTintMode;
mThemeAttrs = bitmapState.mThemeAttrs;
mChangingConfigurations = bitmapState.mChangingConfigurations. mChangingConfigurations = bitmapState;
mGravity = bitmapState.mGravity. mTileModeX = bitmapState;
mTileModeX = bitmapState.mTileModeX. mTileModeY = bitmapState;
mTileModeY = bitmapState.mTileModeY. mTileModeY = bitmapState.mTileModeY;
mTargetDensity = bitmapState. mTargetDensity. mBaseAlpha = bitmapState;
mBaseAlpha = bitmapState.mBaseAlpha;
//Paint will be newly created, thus solving the problems caused by Paint
mPaint = new Paint(bitmapState.mPaint);
mRebuildShader = bitmapState.mRebuildShader;
mAutoMirrored = bitmapState.mAutoMirrored;
}
まとめ
BitmapDrawableはgetDrawable()で取得しますが、色を変更するなどの落とし穴があり、再度mutateを呼び出した方が良いです。もちろん、直接new BitmapDrawableでも良いですが、ビットマップが再利用されず、メモリ消費量が増えます。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
ハートビート・エフェクトのためのHTML+CSS
-
HTML ホテル フォームによるフィルタリング
-
HTML+cssのボックスモデル例(円、半円など)「border-radius」使いやすい
-
HTMLテーブルのテーブル分割とマージ(colspan, rowspan)
-
ランダム・ネームドロッパーを実装するためのhtmlサンプルコード
-
Html階層型ボックスシャドウ効果サンプルコード
-
QQの一時的なダイアログボックスをポップアップし、友人を追加せずにオンラインで話す効果を達成する方法
-
sublime / vscodeショートカットHTMLコード生成の実装
-
HTMLページを縮小した後にスクロールバーを表示するサンプルコード
-
html のリストボックス、テキストフィールド、ファイルフィールドのコード例