【问题标题】:How to use switch case with string resources如何使用带有字符串资源的 switch case
【发布时间】:2015-07-31 22:32:18
【问题描述】:

如何使用带有字符串资源而不是硬编码名称的 switch case 场景?我的字符串与它们的拼写名称完全相同。

        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            MainListAdapter adapter = (MainListAdapter) parent.getAdapter();
            Main continent = adapter.getItem(position);
               if (mTwoPane) {
                    View rowView = view;
                    setItemSelected(continent, rowView);

                    Fragment newFragment;
                    switch (stringRes) {
                        case R.id.africa:
                            newFragment = new FragmentAfrica();
                            break;
                        case R.id.asia:
                            newFragment = new FragmentAsia();
                            break;
                        case R.id.europe:
                            newFragment = new FragmentEurope();
                            break;
                        default:
                            newFragment = new FragmentAfrica();
                    }

                    MainActivity activity = (MainActivity) view.getContext();
                    FragmentTransaction transaction = activity.getSupportFragmentManager().beginTransaction();
                    transaction.replace(R.id.detail_container, newFragment);
                    transaction.commit();
                } else {
              }

【问题讨论】:

  • 请注意,这种开关最好用反射和/或工厂代替。

标签: java android android-fragments switch-statement


【解决方案1】:

根据JLS § 14.12,开关标签(即case "africa": 中的"africa")必须为constant expressions。所以如果你想使用switch,你必须将字符串资源值存储在一个常量变量中,然后将该常量用作开关标签。

示例(使用类常量或局部常量):

class Example {
  public static final String CONTINENT_EUROPE =
      getResources().getString(R.string.europe);  // Option 1: class constants
  public static final String CONTINENT_NORTHERN_AMERICA =
      getResources().getString(R.string.northernAmerica);

  public void foo() {
    final String continentAfrica =
        getResources().getString(R.string.africa);  // Option 2: local constants
    final String continentAsia =
        getResources().getString(R.string.asia);
    switch (continent) {
    // Option 1:
    case continentAfrica:
      newFragment = new FragmentAfrica();
      break;
    case continentAsia:
      newFragment = new FragmentAsia();
      break;
    // Option 2:
    case CONTINENT_EUROPE:
      newFragment = new FragmentEurope();
      break;
    case CONTINENT_NORTHERN_AMERICA:
      newFragment = new FragmentNorthernAmerica();
      break;
    // ...
  }
}

【讨论】:

    【解决方案2】:

    看起来这可以工作..使用整数。

    public void switchFragments(int stringRes){
        if (mTwoPane) {
                    View rowView = view;
                    setItemSelected(continent, rowView);
    
                    Fragment newFragment;
                    switch (stringRes) {
                        case R.id.africa:
                            newFragment = new FragmentAfrica();
                            break;
                        case R.id.asia:
                            newFragment = new FragmentAsia();
                            break;
                        case R.id.europe:
                            newFragment = new FragmentEurope();
                            break;
                        default:
                            newFragment = new FragmentAfrica();
                    }
    
                    MainActivity activity = (MainActivity) view.getContext();
                    FragmentTransaction transaction = activity.getSupportFragmentManager().beginTransaction();
                    transaction.replace(R.id.detail_container, newFragment);
                    transaction.commit();
                }
    }
    

    现在你要做的就是这样称呼它

    switchFragments(R.id.africa);
    

    这将转到标记为 R.id.africa 的案例并切换片段。 它也适用于不同的语言,因为它只是资源的 ID。

    【讨论】:

    • @hitch.united 使用您的建议后,我收到此错误:Variable 'id' is already defined in this scope
    【解决方案3】:

    我认为在这种情况下,最简单的方法是您可以使用“简单的 if else 语句”来避免声明额外的静态变量。并且还添加了对语言环境更改的支持。

    private String[] titles;
    
    void initialize(){
        titles = new String[]{getString(R.string.europe),getString(R.string.africa)};
    }
    
    @Override
    public Fragment getItem(int position) {
    
        String title = titles[position];
    
        if (title.equals(getString(R.string.europe))) {
            return new EuropeFragment();
        } else if (title.equals(getString(R.string.africa))) {
            return new AfricaFragment();
        } else {
            return new DefaultFragment();
        }
    }
    

    【讨论】:

      【解决方案4】:

      只需像这样将它们声明为常量:

      public static final String COUNTRY_AFRICA = "africa";
      public static final String COUNTRY_ASIA = "asia";
      
      switch (country.toLowerCase()) {
          case COUNTRY_AFRICA:
               newFragment = new FragmentAfrica();
               break;
          // etc..
      

      这比硬编码要好,因为您可以在整个应用程序中重复使用这些常量。

      如果这些是 UI 字符串,您可以在 strings.xml 中声明它们

      【讨论】:

      • 请记住,我的应用程序将使用不同的语言。您已经硬编码了“非洲”和“亚洲”。我不能改用getResources().getString(R.string.africa)getResources().getString(R.string.asia) 吗?
      • 我还没有测试过这个,但也许你可以使用字符串资源ID?那么你可以使用整数的开关。
      • “非洲”是 UI 字符串吗?我的意思是,它是否显示给用户?如果是,那么逻辑是错误的。您不应该根据随语言环境变化的字符串来构建条件
      • 所以,不要在 switch-case 中使用getResources().getString()。继续使用@ChrisKo 提出的解决方案。或者我的解决方案:)他们实际上都做同样的事情。
      【解决方案5】:

      你应该将它声明为一个枚举:

      public enum Continent{
          africa, asia, europe
      }
      
      public Fragment getFragment(String continentKey){
          Continent continent = Continent.valueOf(continentKey);
          return getFragment(continent);
      }
      
      public Fragment getFragment(Continent aContinent){
          Fragment newFragment;
          switch(aContinent){
              case asia:
                  newFragment = new FragmentAsia();
                  break;
              case europe:
                  newFragment = new FragmentEurope();
                  break;
              case africa: default:
                  newFragment = new FragmentAfrica();
                  break;
          }
          return newFragment;
      }
      

      【讨论】:

      • 请记住,我的应用程序将使用不同的语言。例如。法国人不说“非洲”,他们说“非洲”我不能用getResources().getString(R.string.africa)getResources().getString(R.string.asia) 代替吗?
      • 您需要为此使用资源密钥(例如“africa”)。使用资源值(例如“Afrique”)没有意义。
      • 请根据需要编辑您的答案,我想使用 strings.xml 文件中指定的字符串资源
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-12-09
      • 1970-01-01
      • 1970-01-01
      • 2023-04-07
      • 2012-02-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多