Package io.rong.imkit.config

## Class IMKitThemeManager

- All Implemented Interfaces:

      public class IMKitThemeManager

  融云主题管理器

  用于管理融云 IM SDK 的主题切换和资源适配，支持多主题动态切换。

  - 内置主题：提供传统主题和欢快主题，欢快主题自动跟随系统深浅色模式
  - 自定义主题：支持开发者扩展和注册自定义主题，支持深浅色模式和主题叠加
  - 系统跟随：自动跟随系统深浅色模式切换（欢快主题及自定义主题）
  - 动态资源：提供动态资源获取方法，根据当前主题和深浅色模式自动选择合适的资源
  - 自动应用：通过 Activity 生命周期回调自动应用主题到所有页面
  - 主题监听：支持监听主题切换事件，方便进行自定义处理

  关于系统深浅色模式切换：

  在部分机型上，系统设置切换深浅色模式后，返回 APP 可能无法及时切换到对应的模式。 这是由于系统原因导致，当前 APP 通过系统方法获取的深浅色状态仍然是旧值，需要重启 APP 才能生效。

  解决方案（推荐）：

  如果您的应用使用了 AppCompat 库，建议在 Application 中通过 `AppCompatDelegate.setDefaultNightMode(nightMode)` 来设置应用的深浅色模式， 这样可以保证深浅色模式的及时切换。

      // 在 Application 的 onCreate 中设置
      // 跟随系统
      AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);

      // 或强制使用浅色模式
      AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);

      // 或强制使用深色模式
      AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);

      // 1. 切换到欢快主题（自动跟随系统深浅色）
      IMKitThemeManager.changeInnerTheme(context, IMKitThemeManager.LIVELY_THEME);

      // 2. 切换到传统主题
      IMKitThemeManager.changeInnerTheme(context, IMKitThemeManager.TRADITION_THEME);

      // 3. 添加自定义主题（支持深浅色模式）
      IMKitThemeManager.addTheme("CUSTOM_THEME",
          R.style.MyCustomLightTheme,  // 浅色模式样式
          R.style.MyCustomDarkTheme    // 深色模式样式
      );

      // 4. 切换到自定义主题（基于欢快主题）
      IMKitThemeManager.changeCustomTheme(context, "CUSTOM_THEME", IMKitThemeManager.LIVELY_THEME);

      // 5. 在代码中动态获取主题资源
      int bgResId = IMKitThemeManager.dynamicResource(
          context,
          R.attr.rc_conversation_bg,  // 主题属性
          R.drawable.rc_old_bg        // 默认资源
      );
      view.setBackgroundResource(bgResId);

      // 6. 获取当前主题
      String currentTheme = IMKitThemeManager.getCurrentThemeName();

      // 7. 判断当前主题类型
      if (IMKitThemeManager.TRADITION_THEME.equals(currentTheme)) {
          // 传统主题
      }

- - ### Nested Class Summary

    Nested Classes
    Modifier and Type | Class | Description
    --- | --- | ---
    `public interface` | `IMKitThemeManager.OnThemeListener` | 主题变化监听器接口 用于监听主题切换事件，当主题发生变化时会收到回调通知。 使用示例：
        // 创建监听器
        OnThemeListener listener = new OnThemeListener() {
            @Override
            public void onThemeChanged(Context context, String oldTheme, String newTheme) {
                Log.d("Theme", "主题从 " + oldTheme + " 切换到 " + newTheme);
                // 可以直接使用传入的 context，无需自己持有引用
                if (context instanceof Activity) {
                    ((Activity) context).recreate(); // 重建 Activity 应用新主题
                }
            }
        };

        // 添加监听器
        IMKitThemeManager.addThemeListener(listener);

        // 不需要时移除监听器（避免内存泄漏）
        IMKitThemeManager.removeThemeListener(listener);

  - ### Field Summary

    Fields
    Modifier and Type | Field | Description
    --- | --- | ---
    `public final static String` | `TRADITION_THEME` |
    `public final static String` | `LIVELY_THEME` |

  - ### Constructor Summary

    Constructors
    Constructor | Description
    --- | ---

  - ### Enum Constant Summary

    Enum Constants
    Enum Constant | Description
    --- | ---

  - ### Method Summary

    Modifier and Type | Method | Description
    --- | --- | ---
    `static void` | `addTheme(String themeType, int lightStyleResId, int darkStyleResId)` | 添加主题（支持浅色和深色样式） 此方法用于添加自定义主题，支持为主题指定浅色和深色两种样式。系统会根据当前的深浅色模式自动应用对应的样式。 使用场景：
        // 添加自定义主题（支持深浅色模式）
        IMKitThemeManager.addTheme(
            "CUSTOM_THEME",
            R.style.MyCustomLightTheme,  // 浅色模式样式
            R.style.MyCustomDarkTheme    // 深色模式样式
        );

        // 添加单一样式主题（浅色和深色使用相同样式）
        IMKitThemeManager.addTheme(
            "SIMPLE_THEME",
            R.style.MyTheme,  // 浅色模式样式
            R.style.MyTheme   // 深色模式样式（相同）
        );

        // 为已有主题追加额外样式（样式叠加）
        IMKitThemeManager.addTheme(
            IMKitThemeManager.LIVELY_THEME,
            R.style.MyCustomOverrideLight,  // 浅色模式扩展样式
            R.style.MyCustomOverrideDark    // 深色模式扩展样式
        );

        // 切换到自定义主题（基于欢快主题）
        IMKitThemeManager.changeCustomTheme(context, "CUSTOM_THEME", IMKitThemeManager.LIVELY_THEME);
    注意事项： 多次调用此方法添加同一主题时，样式会按顺序叠加应用 后添加的样式属性会覆盖先前的同名属性 lightStyleResId 和 darkStyleResId 不能为 0 主题会自动跟随系统深浅色模式切换
    `static void` | `changeInnerTheme(Context context, String themeType)` | 切换应用内置主题 切换到指定的内置主题并立即应用到当前上下文。该方法会自动处理以下操作： 验证并设置新的主题类型 根据系统深浅色模式自动选择对应的样式 应用主题到 Application Context（全局生效） 应用主题到当前 Context（立即生效） 通过 ActivityLifecycleCallbacks 自动应用到后续创建的所有 Activity 使用示例：
        // 切换到欢快主题（自动跟随系统深浅色）
        IMKitThemeManager.changeInnerTheme(context, IMKitThemeManager.LIVELY_THEME);

        // 切换到传统主题
        IMKitThemeManager.changeInnerTheme(context, IMKitThemeManager.TRADITION_THEME);
    注意：主题切换是全局性的，会影响所有融云 SDK 的 UI 组件。如果当前已经是目标主题，方法会自动跳过，避免不必要的重复应用。
    `static void` | `changeCustomTheme(Context context, String customThemeType, String baseOnTheme)` | 切换自定义主题（基于内置主题扩展） 此方法用于切换到自定义主题，并指定一个基础主题。会先应用基础主题的配置，然后再应用自定义主题的配置，从而实现主题的叠加和扩展。 应用顺序： 先应用 baseOnTheme 对应的所有主题配置 再应用 customThemeType 对应的所有主题配置 后应用的配置会覆盖先前的同名属性 使用示例：
        // 先添加自定义主题
        IMKitThemeManager.addTheme(
            "MY_BLUE_THEME",
            R.style.MyBlueLightTheme,
            R.style.MyBlueDarkTheme
        );

        // 基于欢快主题，应用自定义主题（先应用欢快主题，再应用自定义主题）
        IMKitThemeManager.changeCustomTheme(context, "MY_BLUE_THEME", IMKitThemeManager.LIVELY_THEME);

        // 基于传统主题，应用自定义主题
        IMKitThemeManager.changeCustomTheme(context, "MY_BLUE_THEME", IMKitThemeManager.TRADITION_THEME);
    注意事项： baseOnTheme 只能传递 TRADITION_THEME 或 LIVELY_THEME customThemeType 必须是已通过 addTheme 方法添加的主题 主题切换是全局性的，会影响所有融云 SDK 的 UI 组件
    `static String` | `getCurrentThemeName()` | 获取当前激活的主题类型 使用示例：
        String theme = IMKitThemeManager.getCurrentThemeName();
        if (IMKitThemeManager.LIVELY_THEME.equals(theme)) {
            // 当前是欢快主题
        }
    `static void` | `addThemeListener(IMKitThemeManager.OnThemeListener listener)` | 添加主题变化监听器 注册一个监听器以接收主题切换事件通知。当调用 changeInnerTheme 或 changeCustomTheme 方法且主题实际发生变化时，所有已注册的监听器都会收到 onThemeChanged 回调。 使用场景： 需要在主题切换时更新自定义 UI 组件 需要在主题变化时重新加载资源或刷新界面 需要同步主题状态到其他模块 Context 参数的优势： 监听器无需自己持有 Context 引用，避免潜在的内存泄漏 可以直接使用传入的 Context 进行 UI 操作（如 Activity.recreate()） 通过 Context 获取资源或调用其他需要 Context 的方法 使用示例：
        public class MyActivity extends AppCompatActivity {
            private OnThemeListener themeListener;

            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);

                // 创建监听器
                themeListener = new OnThemeListener() {
                    @Override
                    public void onThemeChanged(Context context, String oldTheme, String newTheme) {
                        // 使用传入的 context 重新创建 Activity
                        if (context instanceof Activity) {
                            ((Activity) context).recreate();
                        }
                    }
                };

                // 添加监听器
                IMKitThemeManager.addThemeListener(themeListener);
            }

            @Override
            protected void onDestroy() {
                super.onDestroy();
                // 移除监听器，避免内存泄漏
                IMKitThemeManager.removeThemeListener(themeListener);
            }
        }
    注意事项： 同一个监听器对象不会被重复添加 请在合适的时机（如 Activity/Fragment 的 onDestroy）移除监听器，避免内存泄漏 监听器回调在主题切换所在的线程执行，通常是主线程
    `static void` | `removeThemeListener(IMKitThemeManager.OnThemeListener listener)` | 移除主题变化监听器 移除之前通过 addThemeListener 添加的监听器。 建议在 Activity/Fragment 的生命周期结束时（如 onDestroy）调用此方法，避免内存泄漏。 使用示例：
        @Override
        protected void onDestroy() {
            super.onDestroy();
            IMKitThemeManager.removeThemeListener(themeListener);
        }
    `static boolean` | `isTraditionTheme()` | 判断当前是否为传统主题（内部使用，不推荐外部调用） ⚠️ 注意：此方法仅供 SDK 内部使用，外部不推荐直接调用。 推荐做法：外部应用请使用 getCurrentThemeName 获取当前主题名称，然后自行判断：
        String theme = IMKitThemeManager.getCurrentThemeName();
        if (IMKitThemeManager.TRADITION_THEME.equals(theme)) {
            // 传统主题逻辑
        } else if (IMKitThemeManager.LIVELY_THEME.equals(theme)) {
            // 欢快主题逻辑
        } else {
            // 自定义主题逻辑
        }
    `static int` | `dynamicResource(Context context, int newVersionAttrId, int oldVersionResId)` | 动态获取主题资源（基于 Context 解析） 此方法根据当前激活的主题自动选择对应的资源： 现代化主题：从主题属性（Theme Attribute）中动态解析资源 ID，支持多主题切换 传统主题：直接返回指定的固定资源 ID，保持向后兼容 适用场景： 在 Java/Kotlin 代码中动态获取需要主题适配的资源 需要在运行时根据当前主题选择不同资源的场景 自定义 View 或 Adapter 中需要加载主题相关的图片、颜色等资源 使用示例：
        // 获取背景资源：现代化主题使用主题属性，传统主题使用固定资源
        int bgResId = IMKitThemeManager.dynamicResource(
            context,
            R.attr.rc_conversation_bg,      // 主题属性
            R.drawable.rc_old_bg            // 固定资源（用于传统主题）
        );
        view.setBackgroundResource(bgResId);

        // 获取颜色资源
        int colorResId = IMKitThemeManager.dynamicResource(
            context,
            R.attr.rc_text_primary,         // 主题属性
            R.color.rc_old_text_color       // 固定颜色（用于传统主题）
        );
        textView.setTextColor(getResources().getColor(colorResId));
    `static int` | `dynamicResource(int newVersionResId, int oldVersionResId)` | 动态获取主题资源（无需 Context 的快速版本） 此方法是 dynamicResource 的轻量级版本，适用于 XML 布局文件或无需立即解析的场景。 现代化主题：直接返回主题属性 ID，由系统在渲染时自动解析 传统主题：返回固定资源 ID 适用场景： XML 布局文件中需要根据主题类型选择资源的场景（如 android:background） 延迟解析场景，资源 ID 会在后续使用时由 Android 系统自动解析 无法获取 Context 但需要资源 ID 的场景 使用示例：
        // 在代码中使用（系统会自动解析属性）
        view.setBackgroundResource(
            IMKitThemeManager.dynamicResource(R.attr.rc_bg, R.drawable.rc_old_bg)
        );

        // 注意：返回的可能是属性 ID，需要系统自动解析
        // 如果需要立即获取解析后的资源，请使用带 Context 参数的版本
    注意：此方法返回的是属性 ID（现代化主题）或资源 ID（传统主题），如果需要立即使用解析后的实际资源 ID，请使用 dynamicResource 方法。
    `static int` | `getAttrResId(Context context, int attrId)` | 从主题属性中解析实际的资源 ID 此方法用于将主题属性（Theme Attribute）解析为实际的资源 ID。 使用场景：需要从主题属性中获取实际资源 ID 时使用。
        // 解析主题属性得到实际的资源 ID
        int drawableResId = IMKitThemeManager.getAttrResId(context, R.attr.rc_conversation_bg);
        // drawableResId 现在是实际的 R.drawable.xxx 值
    `static int` | `getColorFromAttrId(Context context, int attrId)` | 从主题属性中直接获取颜色值 此方法是获取颜色的便捷方法，会自动完成"属性→资源ID→颜色值"的完整解析过程。 使用场景：需要从主题属性中直接获取可用的颜色 int 值。
        // 直接获取主题颜色值
        int textColor = IMKitThemeManager.getColorFromAttrId(context, R.attr.rc_text_primary);
        textView.setTextColor(textColor);

        // 等价于以下两步操作：
        // int colorResId = IMKitThemeManager.getAttrResId(context, R.attr.rc_text_primary);
        // int textColor = context.getResources().getColor(colorResId);
    `static boolean` | `isSystemInDarkMode(Context context)` | 判断系统是否处于深色模式
    `static void` | `ensureThemeApplied(Context context)` | 确保主题已应用到指定的 Context。 在 Activity 的 `onCreate` 中、`setContentView` 调用之前使用， 以确保布局中的 `?attr/rc_*` 属性引用能够被正确解析。 此方法在内部会检查主题系统是否已初始化，如未初始化则先执行初始化。
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            IMKitThemeManager.ensureThemeApplied(this);
            super.onCreate(savedInstanceState);
            setContentView(R.layout.my_layout);
        }

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Constructor Detail

  - ### Method Detail

    - #### addTheme

           static void addTheme(String themeType, int lightStyleResId, int darkStyleResId)

      添加主题（支持浅色和深色样式）

      此方法用于添加自定义主题，支持为主题指定浅色和深色两种样式。系统会根据当前的深浅色模式自动应用对应的样式。

      使用场景：

          // 添加自定义主题（支持深浅色模式）
          IMKitThemeManager.addTheme(
              "CUSTOM_THEME",
              R.style.MyCustomLightTheme,  // 浅色模式样式
              R.style.MyCustomDarkTheme    // 深色模式样式
          );

          // 添加单一样式主题（浅色和深色使用相同样式）
          IMKitThemeManager.addTheme(
              "SIMPLE_THEME",
              R.style.MyTheme,  // 浅色模式样式
              R.style.MyTheme   // 深色模式样式（相同）
          );

          // 为已有主题追加额外样式（样式叠加）
          IMKitThemeManager.addTheme(
              IMKitThemeManager.LIVELY_THEME,
              R.style.MyCustomOverrideLight,  // 浅色模式扩展样式
              R.style.MyCustomOverrideDark    // 深色模式扩展样式
          );

          // 切换到自定义主题（基于欢快主题）
          IMKitThemeManager.changeCustomTheme(context, "CUSTOM_THEME", IMKitThemeManager.LIVELY_THEME);

      注意事项：

      - 多次调用此方法添加同一主题时，样式会按顺序叠加应用
      - 后添加的样式属性会覆盖先前的同名属性
      - lightStyleResId 和 darkStyleResId 不能为 0
      - 主题会自动跟随系统深浅色模式切换
      Parameters:
        `themeType` - 主题类型标识（建议使用全大写下划线格式，如 "CUSTOM_BLUE_THEME"）
        `lightStyleResId` - 浅色模式的主题样式资源 ID（如 R.style.
        `darkStyleResId` - 深色模式的主题样式资源 ID（如 R.style.

    - #### changeInnerTheme

           static void changeInnerTheme(Context context, String themeType)

      切换应用内置主题

      切换到指定的内置主题并立即应用到当前上下文。该方法会自动处理以下操作：

      - 验证并设置新的主题类型
      - 根据系统深浅色模式自动选择对应的样式
      - 应用主题到 Application Context（全局生效）
      - 应用主题到当前 Context（立即生效）
      - 通过 ActivityLifecycleCallbacks 自动应用到后续创建的所有 Activity

      使用示例：

          // 切换到欢快主题（自动跟随系统深浅色）
          IMKitThemeManager.changeInnerTheme(context, IMKitThemeManager.LIVELY_THEME);

          // 切换到传统主题
          IMKitThemeManager.changeInnerTheme(context, IMKitThemeManager.TRADITION_THEME);

      注意：主题切换是全局性的，会影响所有融云 SDK 的 UI 组件。如果当前已经是目标主题，方法会自动跳过，避免不必要的重复应用。

      Parameters:
        `context` - 上下文（建议传入 Activity 或 Application Context）
        `themeType` - 主题类型标识（使用 TRADITION_THEME 或 LIVELY_THEME）

    - #### changeCustomTheme

           static void changeCustomTheme(Context context, String customThemeType, String baseOnTheme)

      切换自定义主题（基于内置主题扩展）

      此方法用于切换到自定义主题，并指定一个基础主题。会先应用基础主题的配置，然后再应用自定义主题的配置，从而实现主题的叠加和扩展。

      应用顺序：

      - 先应用 baseOnTheme 对应的所有主题配置
      - 再应用 customThemeType 对应的所有主题配置
      - 后应用的配置会覆盖先前的同名属性

      使用示例：

          // 先添加自定义主题
          IMKitThemeManager.addTheme(
              "MY_BLUE_THEME",
              R.style.MyBlueLightTheme,
              R.style.MyBlueDarkTheme
          );

          // 基于欢快主题，应用自定义主题（先应用欢快主题，再应用自定义主题）
          IMKitThemeManager.changeCustomTheme(context, "MY_BLUE_THEME", IMKitThemeManager.LIVELY_THEME);

          // 基于传统主题，应用自定义主题
          IMKitThemeManager.changeCustomTheme(context, "MY_BLUE_THEME", IMKitThemeManager.TRADITION_THEME);

      注意事项：

      - baseOnTheme 只能传递 TRADITION_THEME 或 LIVELY_THEME
      - customThemeType 必须是已通过 addTheme 方法添加的主题
      - 主题切换是全局性的，会影响所有融云 SDK 的 UI 组件
      Parameters:
        `context` - 上下文（建议传入 Activity 或 Application Context）
        `customThemeType` - 自定义主题类型标识（必须已通过 addTheme 添加）
        `baseOnTheme` - 基础主题类型（只能是 TRADITION_THEME 或 LIVELY_THEME）

    - #### getCurrentThemeName

           static String getCurrentThemeName()

      获取当前激活的主题类型

      使用示例：

          String theme = IMKitThemeManager.getCurrentThemeName();
          if (IMKitThemeManager.LIVELY_THEME.equals(theme)) {
              // 当前是欢快主题
          }

      Returns:

        当前主题类型标识字符串（如 TRADITION_THEME、LIVELY_THEME 或自定义主题名称）

    - #### addThemeListener

           static void addThemeListener(IMKitThemeManager.OnThemeListener listener)

      添加主题变化监听器

      注册一个监听器以接收主题切换事件通知。当调用 changeInnerTheme 或 changeCustomTheme 方法且主题实际发生变化时，所有已注册的监听器都会收到 onThemeChanged 回调。

      使用场景：

      - 需要在主题切换时更新自定义 UI 组件
      - 需要在主题变化时重新加载资源或刷新界面
      - 需要同步主题状态到其他模块

      Context 参数的优势：

      - 监听器无需自己持有 Context 引用，避免潜在的内存泄漏
      - 可以直接使用传入的 Context 进行 UI 操作（如 Activity.recreate()）
      - 通过 Context 获取资源或调用其他需要 Context 的方法

      使用示例：

          public class MyActivity extends AppCompatActivity {
              private OnThemeListener themeListener;

              @Override
              protected void onCreate(Bundle savedInstanceState) {
                  super.onCreate(savedInstanceState);

                  // 创建监听器
                  themeListener = new OnThemeListener() {
                      @Override
                      public void onThemeChanged(Context context, String oldTheme, String newTheme) {
                          // 使用传入的 context 重新创建 Activity
                          if (context instanceof Activity) {
                              ((Activity) context).recreate();
                          }
                      }
                  };

                  // 添加监听器
                  IMKitThemeManager.addThemeListener(themeListener);
              }

              @Override
              protected void onDestroy() {
                  super.onDestroy();
                  // 移除监听器，避免内存泄漏
                  IMKitThemeManager.removeThemeListener(themeListener);
              }
          }

      注意事项：

      - 同一个监听器对象不会被重复添加
      - 请在合适的时机（如 Activity/Fragment 的 onDestroy）移除监听器，避免内存泄漏
      - 监听器回调在主题切换所在的线程执行，通常是主线程
      Parameters:
        `listener` - 主题变化监听器，不能为 null

    - #### removeThemeListener

           static void removeThemeListener(IMKitThemeManager.OnThemeListener listener)

      移除主题变化监听器

      移除之前通过 addThemeListener 添加的监听器。 建议在 Activity/Fragment 的生命周期结束时（如 onDestroy）调用此方法，避免内存泄漏。

      使用示例：

          @Override
          protected void onDestroy() {
              super.onDestroy();
              IMKitThemeManager.removeThemeListener(themeListener);
          }

      Parameters:
        `listener` - 要移除的监听器，不能为 null

    - #### isTraditionTheme

           static boolean isTraditionTheme()

      判断当前是否为传统主题（内部使用，不推荐外部调用）

      ⚠️ 注意：此方法仅供 SDK 内部使用，外部不推荐直接调用。

      推荐做法：外部应用请使用 getCurrentThemeName 获取当前主题名称，然后自行判断：

          String theme = IMKitThemeManager.getCurrentThemeName();
          if (IMKitThemeManager.TRADITION_THEME.equals(theme)) {
              // 传统主题逻辑
          } else if (IMKitThemeManager.LIVELY_THEME.equals(theme)) {
              // 欢快主题逻辑
          } else {
              // 自定义主题逻辑
          }

      Returns:

        true 表示当前是传统主题；false 表示当前是欢快主题或自定义主题

    - #### dynamicResource

           static int dynamicResource(Context context, int newVersionAttrId, int oldVersionResId)

      动态获取主题资源（基于 Context 解析）

      此方法根据当前激活的主题自动选择对应的资源：

      - 现代化主题：从主题属性（Theme Attribute）中动态解析资源 ID，支持多主题切换
      - 传统主题：直接返回指定的固定资源 ID，保持向后兼容

      适用场景：

      - 在 Java/Kotlin 代码中动态获取需要主题适配的资源
      - 需要在运行时根据当前主题选择不同资源的场景
      - 自定义 View 或 Adapter 中需要加载主题相关的图片、颜色等资源

      使用示例：

          // 获取背景资源：现代化主题使用主题属性，传统主题使用固定资源
          int bgResId = IMKitThemeManager.dynamicResource(
              context,
              R.attr.rc_conversation_bg,      // 主题属性
              R.drawable.rc_old_bg            // 固定资源（用于传统主题）
          );
          view.setBackgroundResource(bgResId);

          // 获取颜色资源
          int colorResId = IMKitThemeManager.dynamicResource(
              context,
              R.attr.rc_text_primary,         // 主题属性
              R.color.rc_old_text_color       // 固定颜色（用于传统主题）
          );
          textView.setTextColor(getResources().getColor(colorResId));

      Parameters:
        `context` - 上下文（用于解析主题属性，不能为 null）
        `newVersionAttrId` - 主题属性 ID（如 R.attr.
        `oldVersionResId` - 固定资源 ID（如 R.drawable.xxx 或 R.color.
      Returns:

        解析后的资源 ID

    - #### dynamicResource

           static int dynamicResource(int newVersionResId, int oldVersionResId)

      动态获取主题资源（无需 Context 的快速版本）

      此方法是 dynamicResource 的轻量级版本，适用于 XML 布局文件或无需立即解析的场景。

      - 现代化主题：直接返回主题属性 ID，由系统在渲染时自动解析
      - 传统主题：返回固定资源 ID

      适用场景：

      - XML 布局文件中需要根据主题类型选择资源的场景（如 android:background）
      - 延迟解析场景，资源 ID 会在后续使用时由 Android 系统自动解析
      - 无法获取 Context 但需要资源 ID 的场景

      使用示例：

          // 在代码中使用（系统会自动解析属性）
          view.setBackgroundResource(
              IMKitThemeManager.dynamicResource(R.attr.rc_bg, R.drawable.rc_old_bg)
          );

          // 注意：返回的可能是属性 ID，需要系统自动解析
          // 如果需要立即获取解析后的资源，请使用带 Context 参数的版本

      注意：此方法返回的是属性 ID（现代化主题）或资源 ID（传统主题），如果需要立即使用解析后的实际资源 ID，请使用 dynamicResource 方法。

      Parameters:
        `newVersionResId` - 主题资源 ID（如 R.drawable.rc_xxx 或 R.color.
        `oldVersionResId` - 固定资源 ID（如 R.drawable.xxx 或 R.color.
      Returns:

        现代化主题返回资源 ID；传统主题返回资源 ID

    - #### getAttrResId

           static int getAttrResId(Context context, int attrId)

      从主题属性中解析实际的资源 ID

      此方法用于将主题属性（Theme Attribute）解析为实际的资源 ID。

      使用场景：需要从主题属性中获取实际资源 ID 时使用。

          // 解析主题属性得到实际的资源 ID
          int drawableResId = IMKitThemeManager.getAttrResId(context, R.attr.rc_conversation_bg);
          // drawableResId 现在是实际的 R.drawable.xxx 值

      Parameters:
        `context` - 上下文（不能为 null）
        `attrId` - 主题属性 ID（如 R.attr.
      Returns:

        解析后的实际资源 ID，解析失败返回 0

    - #### getColorFromAttrId

           static int getColorFromAttrId(Context context, int attrId)

      从主题属性中直接获取颜色值

      此方法是获取颜色的便捷方法，会自动完成"属性→资源ID→颜色值"的完整解析过程。

      使用场景：需要从主题属性中直接获取可用的颜色 int 值。

          // 直接获取主题颜色值
          int textColor = IMKitThemeManager.getColorFromAttrId(context, R.attr.rc_text_primary);
          textView.setTextColor(textColor);

          // 等价于以下两步操作：
          // int colorResId = IMKitThemeManager.getAttrResId(context, R.attr.rc_text_primary);
          // int textColor = context.getResources().getColor(colorResId);

      Parameters:
        `context` - 上下文（不能为 null）
        `attrId` - 颜色属性 ID（如 R.attr.
      Returns:

        解析后的颜色值（ARGB int），解析失败返回 0

    - #### isSystemInDarkMode

           static boolean isSystemInDarkMode(Context context)

      判断系统是否处于深色模式

    - #### ensureThemeApplied

           static void ensureThemeApplied(Context context)

      确保主题已应用到指定的 Context。

      在 Activity 的 `onCreate` 中、`setContentView` 调用之前使用， 以确保布局中的 `?attr/rc_*` 属性引用能够被正确解析。

      此方法在内部会检查主题系统是否已初始化，如未初始化则先执行初始化。

          @Override
          protected void onCreate(Bundle savedInstanceState) {
              IMKitThemeManager.ensureThemeApplied(this);
              super.onCreate(savedInstanceState);
              setContentView(R.layout.my_layout);
          }

      Parameters:
        `context` - 上下文（通常是 Activity）