在模型对象中引用 Strings.XML 以支持本地化

发布于 2024-12-08 12:19:00 字数 1486 浏览 0 评论 0原文

我正在找到这个问题的公认答案和讨论 getString Outside of a Context或活动不清楚。

我是 Android 新手,我试图了解如何在模型类中引用我的资源字符串,以便我可以正确支持本地化。

具体来说,我的模型具有 Location 属性,我希望能够返回方位罗盘序数的字符串。因为像“North”这样的罗盘序数需要本地化,所以我尝试将它们存储在我的 strings.xml 中。

我想我明白我需要应用程序上下文来访问资源对象,但我想知道这是否可能而无需传递上下文。在模型中存储 UI 上下文似乎违反了 MVC。

为了实现这一目标,我想在我的模型中包含一个像这样的方法。第一个 if 显示我如何尝试使用 strings.xml 条目。

public String compassOrdinalForBearing(float bearing) {

assert bearing >= 0.0 && bearing <= 360.0;

if ((bearing > 336.5) && (bearing <= 360.0))
    //Problem here
    return Context.getResources().getString(R.string.compass_ordinal_north);
else if ((bearing >= 0) && (bearing <= 22.5))
    return "North";
else if ((bearing > 22.5)  && (bearing <= 67.5))
    return "Northeast";
else if ((bearing > 67.5)  && (bearing <= 112.5))
    return "East";
else if ((bearing > 112.5) && (bearing <= 157.5))
    return "Southeast"; 
else if ((bearing > 157.5) && (bearing <= 202.5))
    return "South";
else if ((bearing > 202.5) && (bearing <= 247.5))
    return "Southwest";
else if ((bearing > 247.5) && (bearing <= 292.5))
    return "West";
else if ((bearing > 292.5) && (bearing <= 337.5))
    return "Northwest";
else
    assert false;
    return null;
}

I'm finding the accepted answer and discussion for this SO question getString Outside of a Context or Activity unclear.

I'm new to Android and I'm trying to understand how I can reference my resource strings in a model class so that I can properly support localization.

Specifically, my model has a Location property and I would like to be able to return a string for the compass ordinal for the bearing. Because compass ordinals like "North" need to be localized I'm trying to store them in my strings.xml.

I think I understand that I need the application context to get to the resources object but I'm wondering if this is possible without having to pass the context in. Storing a UI context in a model seems like a violation of MVC.

To accomplish this I wanted to include a method in my model like this. The first if shows how I'm trying to use the strings.xml entry.

public String compassOrdinalForBearing(float bearing) {

assert bearing >= 0.0 && bearing <= 360.0;

if ((bearing > 336.5) && (bearing <= 360.0))
    //Problem here
    return Context.getResources().getString(R.string.compass_ordinal_north);
else if ((bearing >= 0) && (bearing <= 22.5))
    return "North";
else if ((bearing > 22.5)  && (bearing <= 67.5))
    return "Northeast";
else if ((bearing > 67.5)  && (bearing <= 112.5))
    return "East";
else if ((bearing > 112.5) && (bearing <= 157.5))
    return "Southeast"; 
else if ((bearing > 157.5) && (bearing <= 202.5))
    return "South";
else if ((bearing > 202.5) && (bearing <= 247.5))
    return "Southwest";
else if ((bearing > 247.5) && (bearing <= 292.5))
    return "West";
else if ((bearing > 292.5) && (bearing <= 337.5))
    return "Northwest";
else
    assert false;
    return null;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

浮世清欢 2024-12-15 12:19:00

通常所做的就是对 Application 类进行子类化,保证该类只有一个实例。

应用程序子类:

public class MyApplication extends Application {
   private static Context mContext;

   @Override
   public void onCreate(){
      super.onCreate();
      mContext = this;
   }

   public static Context getContext(){
        return mContext;
   }
}

您的类:

public String compassOrdinalForBearing(float bearing) {
    Context context = MyApplication.getContext();

    String north = context.getResources().getString(R.string.compass_ordinal_north);)
}

但不要忘记更改清单:

<application android:name="com.example.myapp.MyApplication">

或者,您可以在实例化期间仅传递上下文,而不保留指向它的指针,因为几乎可以肯定这些对象将从上下文实例化。

private Static string NORTH = null;

public MyClass(Context context){
    initializeDirections(context);
}

private static void initializeDirections(Context context){
    if(NORTH == null){
        NORTH = context.getResources().getString(R.string.compass_ordinal_north);
    }
}

最后,两者的一种混乱组合,以防万一您确实无法在实例化时传递上下文,并且您不想将应用程序上下文保留在应用程序子类中:

public class MyApplication extends Application {
    @Override
    public void onCreate(){
        super.onCreate();
        MyClass.initializeDirections(this);
    }
}

public class MyClass{
    private static String NORTH = null;

    public static final void initializeDirections(Context context){
        NORTH = context.getResources().getString(R.string.compass_ordinal_north);
    }
}

编辑:在不相关的注释中,至少仅从这个片段中,您可以删除所有第一个条件。如果它已到达特定的“else”,则第一个条件必然为真。

例如:

else if ((bearing >= 0) && (bearing <= 22.5))
    return "North";
else if ((bearing > 22.5)  && (bearing <= 67.5))
    return "Northeast";

可能是:

else if (bearing <= 22.5)
    return "North";
else if (bearing <= 67.5)
    return "Northeast";

就好像 bearing 是 !<= 22.5,则必然 > 22.5。

这可能会或可能不会提高您的可读性,并且可能会或可能不会令您满意。只是一些可能不需要的两美分:)

Often what is done is subclassing the Application class, which is guaranteed to have only one instance.

Application subclass:

public class MyApplication extends Application {
   private static Context mContext;

   @Override
   public void onCreate(){
      super.onCreate();
      mContext = this;
   }

   public static Context getContext(){
        return mContext;
   }
}

Your class:

public String compassOrdinalForBearing(float bearing) {
    Context context = MyApplication.getContext();

    String north = context.getResources().getString(R.string.compass_ordinal_north);)
}

But don't forget to change the Manifest:

<application android:name="com.example.myapp.MyApplication">

Alternatively you can just pass in a context during instantiation, without keeping a pointer to it, as almost surely these objects will be instantiated from a context.

private Static string NORTH = null;

public MyClass(Context context){
    initializeDirections(context);
}

private static void initializeDirections(Context context){
    if(NORTH == null){
        NORTH = context.getResources().getString(R.string.compass_ordinal_north);
    }
}

Finally a kind of messy combination of the two just in case you genuinely cannot pass in a context upon instantiation and you do not want to keep the application context in the Application subclass:

public class MyApplication extends Application {
    @Override
    public void onCreate(){
        super.onCreate();
        MyClass.initializeDirections(this);
    }
}

public class MyClass{
    private static String NORTH = null;

    public static final void initializeDirections(Context context){
        NORTH = context.getResources().getString(R.string.compass_ordinal_north);
    }
}

Edit: On an unrelated note, at least from only this only snippet, you can kill all of the first conditionals. If it has reached that particular 'else', the first conditional is necessarily true.

For example:

else if ((bearing >= 0) && (bearing <= 22.5))
    return "North";
else if ((bearing > 22.5)  && (bearing <= 67.5))
    return "Northeast";

Could be:

else if (bearing <= 22.5)
    return "North";
else if (bearing <= 67.5)
    return "Northeast";

As if bearing is !<= 22.5, it is necessarily > 22.5.

This may or may not improve readability to you and may or may not be desirable to you. Just some probably unwanted two cents :)

月野兔 2024-12-15 12:19:00

但我想知道这是否可以在不必传递上下文的情况下实现

“否”,您确实需要传递上下文。

我想您需要本地化字符串资源的唯一地方是向用户呈现的一些 UI。 UI 始终是某些 Activity(也是 Context)的一部分,因此当您需要为您的模型获取本地化字符串。

but I'm wondering if this is possible without having to pass the context in

No, you do need to pass the context in.

I suppose the only place where you need localized string resources is some UI to be presented to users. UI is always a part of some Activity (which is also Context), so it should not be a problem to have a Context instance when you need to get localized strings for your model.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文