【问题标题】:use a string for R.color."string"为 R.color."string" 使用字符串
【发布时间】:2013-12-18 21:16:01
【问题描述】:

有没有办法让下面的脚本更有效率? 我想让这段代码易于维护,这就是为什么我想摆脱 if else if 的原因。 我希望你们能在这里帮助我。在底部是我想看到的东西,当然如果可能的话。

     if (category.equals("infusion")){
        layout.setBackgroundResource(R.color.infusion);
            title.setText(R.string.title_infusion);             
     } else if (category.equals("pills")){
            layout.setBackgroundResource(R.color.pills);
            title.setText(R.string.title_pills);
     } else if (category.equals("pumps")){
            layout.setBackgroundResource(R.color.pumps);
            title.setText(R.string.title_pumps);
     } else if (category.equals("oxygen")){
            layout.setBackgroundResource(R.color.oxygen);
            title.setText(R.string.title_oxygen);
     } else if (category.equals("scores")){
            layout.setBackgroundResource(R.color.scores);
            title.setText(R.string.title_scores);
     } else if (category.equals("converters")){
            layout.setBackgroundResource(R.color.converters);
            title.setText(R.string.title_converters);
     }

这样的?

layout.setBackgroundResource(R.color.*category*);
title.setText(R.string.title_*category*);

【问题讨论】:

    标签: java android theming


    【解决方案1】:

    我很确定你会做的所有“简化”事情都会涉及到反射,最终可能会让你的代码变得更慢、更难理解。您所拥有的是一种完全有效的设置方式,对读者来说非常清楚,并且不涉及任何奇怪的技术。

    I.E.这行得通,为什么要修复它?

    好的,编辑:

    在启动时,您可以通过哈希映射将您的字符串值映射到资源 ID。

    类似:

    HashMap map = new HashMap();
    map.put("infusion",R.id.infusion);
    

    然后是:

    layout.setBackgroundResource(map.get(category));
    title.setText(category);   
    

    可能有效,但同样不是真正的改进。

    【讨论】:

      【解决方案2】:

      查看Resources.getIndentifier() 可能有一个辅助函数,例如:

      public static int resourceNameToId(Context context, String name, String resType) {
          if (name != null && name.length() > 0) {
              return context.getResources().getIdentifier(name, resType, context.getPackageName());
          }
      
          return 0;
      }
      

      然后使用它:

      layout.setBackgroundResource(resourceNameToId(getContext(), category, "color"));
      

      【讨论】:

      • 我还要说这个内部使用反射,应该轻用
      • 来自文档:注意:不鼓励使用此功能。按标识符检索资源比按名称检索资源效率更高。
      • 是的,我不建议安装适配器,但它对于动态生成的内容非常有用。同样通过高效,我认为 OP 对可维护性更感兴趣
      • 我实际上根本不确定 OP 的效率是什么意思,我认为他想要非条件代码。也就是说,所提到的枚举方法是一种很好的方法。
      【解决方案3】:

      您可以使用这样的枚举来保存您的值和颜色:

      public enum ColorValue {
      
      InFusion(android.R.color.black),
      Pills(android.R.color.white);
      
      int color;
      
      ColorValue(int Value) {
          color = Value;
      }
      
      public int getColorResource() {
          return color;
      }
      
      } 
      

      然后访问类似这样的枚举值

       ColorValue x=ColorValue.InFusion;
       x.getColorResource();
      

      【讨论】:

        【解决方案4】:

        您无法通过代码构造来实现这一点。

        使用类似的东西:

        layout.setBackgroundResource(getColorByCategory(category));
        title.setText(getCategoryTitle(category));
        

        其中getColorByCategory()getCategoryTitle() 是您自己的函数。

        【讨论】:

          【解决方案5】:

          有两种方法可以让我不由自主地想到。哈希映射和/或使用 Resources 对象。

          有地图会涉及一些设置,如下所示:

          private static final Map<String, Integer> COLOURS = new HashMap<String, Integer>();
          
          static {
              COLOURS.put("pills", R.color.red);
              COLOURS.put("pumps", R.color.green);
          }
          

          那么以后设置颜色就很容易了:

          layout.setBackgroundColor(COLOURS.get(category));
          

          如果不能保证您拥有的数据是完美的,您可能希望在设置地图上的颜色之前先对它们进行空值检查。

          或者,您可以像这样使用 Resources 对象。

          Resources resources = context.getResources();
          resources.getColor(resources.get("colour_" + category, "color", context.getPackageName()));
          

          【讨论】:

            【解决方案6】:

            您可以使用枚举更有效地执行此操作:

            (在你的班级)声明

            public enum Category {
                infusion (R.color.infusion, R.string.title_infusion, "infusion"),
                pills (R.color.pills, R.string.title_pills, "pills") //,
                //etc... comma-seperated values. Those are handled like any other enum
                ;
                public final int relatedBackground;
                public final String relatedTitle;
                public final String identifier; //To keep the identifiers you used previously
            
                private Category (int back, String title, String id) {
                    this.relatedBackground = back;
                    this.relatedTitle = title;
                    this.identifier = id;
                }
            }
            

            你的方法应该是这样的:

            public void foo(Category cat) { //You pass in your enum type
                //Do what you want
                if(cat != null) { //Avoid NullPointerException if necessary
                    layout.setBackgroundResource(cat.relatedBackground); 
                    title.setText(cat.relatedTitle);
                }
            }
            

            此方法是解决您遇到的问题的好方法,因为您可以通过添加新值到逗号分隔列表来维护您的项目。您还无需担心每次都必须从某个表中查找值

            缺点是很难/无法调整枚举在运行时。由于枚举中的所有变量都必须是最终的,因为枚举类型本身是不可修改的,所以你不能做像

            这样的事情
            cat.relatedbackground = someValue; // Can't do that: all fields are final
            

            如果您想这样做,则必须使用外部表。除此之外,它是一个出色的解决方案

            【讨论】:

              猜你喜欢
              • 2015-09-10
              • 1970-01-01
              • 2023-03-06
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-04-12
              • 2015-12-07
              相关资源
              最近更新 更多