web-dev-qa-db-ja.com

ResourcesCompat.getDrawable()vs AppCompatResources.getDrawable()

私はこれらの2つのAPIと少し混同しています。

ResourcesCompat.getDrawable(Resources res、int id、Resources.Theme theme)

特定のリソースIDに関連付けられ、指定されたテーマのスタイルが設定された描画可能なオブジェクトを返します。基になるリソースに応じて、さまざまなタイプのオブジェクトが返されます。たとえば、単色、PNG画像、スケーラブル画像などです。

APIレベル21より前は、テーマは適用されず、このメソッドは単にgetDrawable(int)を呼び出します。

AppCompatResources.getDrawable(Context context、int resId)

特定のリソースIDに関連付けられた描画可能なオブジェクトを返します。

このメソッドは、デバイス上のvectorおよびanimated-vectorリソースのインフレーションをサポートします。プラットフォームのサポートは利用できません。

質問

  1. これら2つのクラスの大きな違いは何ですか(vectorインフレ以外)?
  2. どちらを優先するべきか、またその理由は何ですか?
24
azizbekian

2つのメソッドのソースコードを見ると、非常に似ているように見えます。ベクトルがない場合は、おそらくどちらか一方を使用して逃げることができます。

ResourcesCompat.getDrawable() は、API 21以降でResources#getDrawable(int, theme)を呼び出します。また、Android API 4+。をサポートしています。これ以上の機能はありません。

_public Drawable getDrawable(Resources res, int id, Theme theme)
        throws NotFoundException {
    final int version = Build.VERSION.SDK_INT;
    if (version >= 21) {
        return ResourcesCompatApi21.getDrawable(res, id, theme);
    } else {
        return res.getDrawable(id);
    }
}
_

Where-in _ResourcesCompatApi21_は、単にres.getDrawable(id, theme)を呼び出します。これは、デバイスがベクトルドロアブルをサポートしていない場合、ベクトルドロアブルを描画できるようにするnotを意味します。ただし、テーマを渡すことはできます。

一方、 AppCompatResources.getDrawable(Context context, int resId) のコード変更は、最終的に次のようになります。

_    Drawable getDrawable(@NonNull Context context, @DrawableRes int resId, boolean failIfNotKnown) {
      checkVectorDrawableSetup(context);

      Drawable drawable = loadDrawableFromDelegates(context, resId);
      if (drawable == null) {
        drawable = createDrawableIfNeeded(context, resId);
      }
      if (drawable == null) {
        drawable = ContextCompat.getDrawable(context, resId);
      }

      if (drawable != null) {
        // Tint it if needed
        drawable = tintDrawable(context, resId, failIfNotKnown, drawable);
      }
      if (drawable != null) {
        // See if we need to 'fix' the drawable
        DrawableUtils.fixDrawable(drawable);
      }
    return drawable;
   }
_

したがって、このインスタンスは、可能な場合はリソースを描画しようとします。そうでない場合は、ContextCompatバージョンを検索してリソースを取得します。その後、必要に応じて色合いを調整します。ただし、このメソッドはAPI 7+のみをサポートします。

だから、どちらを使うべきかを決めると思います。

  1. API 4、5、または6をサポートする必要がありますか?

    • はい:ResourcesCompatまたはContextCompatを使用する以外に選択肢はありません。
    • いいえ:#2に進みます。
  2. カスタムテーマを提供する必要がありますか?

    • はい:ResourcesCompatを使用する以外に選択肢はありません
    • いいえ:AppCompatResourcesを使用します
24
DeeV

ここにいくつかのテストの後、私の理解があります

_ContextCompat.getDrawable(@NonNull Context context, @DrawableRes int resId)

ResourcesCompat.getDrawable(@NonNull Resources res, @DrawableRes int id, @Nullable Theme theme)

AppCompatResources.getDrawable(@NonNull Context context, @DrawableRes int resId)

VectorDrawableCompat.create(@NonNull Resources res, @DrawableRes int resId, @Nullable Theme theme
_

最初に表示されるのは、VectorDrawableCompatおよびResourcesCompatが特定のテーマに対応していることです

I)使用せずに

ApplicationクラスのonCreatedAppCompatDelegate.setCompatVectorFromResourcesEnabled(true);

1)ベクター画像の場合

  • API> = 21

    • ContextCompatはうまく機能します
    • ResourcesCompatはうまく機能します
    • AppCompatResourcesはうまく機能します
    • VectorDrawableCompatはうまく機能します
  • API <21

    • ContextCompatクラッシュ
    • ResourcesCompatクラッシュ
    • AppCompatResourcesはうまく機能します
    • VectorDrawableCompatはうまく機能します

2)通常の画像の場合

  • すべてのレベルで
    • ContextCompatはうまく機能します
    • ResourcesCompatはうまく機能します
    • AppCompatResourcesはうまく機能します
    • VectorDrawableCompatクラッシュ

II)使用

ApplicationクラスのonCreatedAppCompatDelegate.setCompatVectorFromResourcesEnabled(true);

1)ベクター画像の場合

  • すべてのレベルで
    • ContextCompatはうまく機能します
    • ResourcesCompatはうまく機能します
    • AppCompatResourcesはうまく機能します
    • VectorDrawableCompatはうまく機能します

2)通常の画像の場合

  • すべてのレベルで
    • ContextCompatはうまく機能します
    • ResourcesCompatはうまく機能します
    • AppCompatResourcesはうまく機能します
    • VectorDrawableCompatクラッシュ
33
Phan Van Linh

ContextCompat

ResourcesCompatContextCompat、およびCompatで終わるsupport-v4のほとんどすべてのクラスにより、if (Build.VERSION.SDK_INT >= X)チェックをどこからでも作成できます。それでおしまい。たとえば

final Drawable d;
if (Build.VERSION.SDK_INT < 21) {
    // Old method, drawables cannot contain theme references.
    d = context.getResources().getDrawable(R.drawable.some_image);
} else {
    // Drawables on API 21 can contain theme attribute references.
    // Context#getDrawable only exists since API 21.
    d = context.getDrawable(R.drawable.some_image);
}

あなたは書ける

final Drawable d = ContextCompat.getDrawable(context, R.drawable.some_image);

たとえば、コメントで説明されている制限が適用されます

// This line is effectively equivalent to the above.
ResourcesCompat.getDrawable(context.getResources(), R.drawable.some_image, context.getTheme());

lollipopの前にテーマ属性を実際に適用することはありません(これはドキュメントで説明されています)。ただし、実際に新しいAPIを使用していないので、古いデバイスでチェックとコードがクラッシュしない場合は、書く必要はありません。

AppCompatResources

一方、AppCompatResourcesは、実際に古いプラットフォームに新しい機能を追加するのに役立ちます(サポートベクター、カラー状態リストのテーマ参照)。

どちらを優先するべきか、またその理由は何ですか?

AppCompatResourcesを使用して、残りのappcompat-v7ライブラリと一貫した結果を取得します。あなたが取得します:

  • テーマ属性参照(Android:alpha="?android:disabledAlpha"など)で色を解決できるgetColorStateList
  • getDrawableは、すべてのプラットフォームでベクトルの膨張をサポートし、これらのベクトルドロウアブルはテーマ属性参照も理解します(例:Android:tint="?colorControlNormal")、
  • appcompat-v7のドローアブルとチェックマークやラジオボタンなどの色は、提供されたコンテキストテーマによって定義された適切な色を持ち、
  • 上記が当てはまらない場合は、とにかくContextCompatにフォールバックします。
8
Eugen Pechanec