上下文或活动之外的getString


260

我发现R.string将硬编码的字符串保留在我的代码之外真是太棒了,我想继续在实用程序类中使用它,该实用程序类与我的应用程序中的模型一起使用以生成输出。例如,在这种情况下,我从活动之外的模型生成电子邮件。

是否可以getStringContext或外使用Activity?我想我可以通过当前活动,但这似乎没有必要。如果我错了,请纠正我!

编辑:我们可以使用访问资源Context吗?


4
通过将上下文传递给将使用字符串的类,您还将传递有关应用程序正在使用哪种语言(en,es等)的信息。因此,如果您有两个string.xml,它将知道要使用哪一个
sports

Answers:


440

是的,我们无需使用“上下文”就可以访问资源

您可以使用:

Resources.getSystem().getString(android.R.string.somecommonstuff)

...在应用程序中的任何地方,甚至在静态常量声明中也是如此。不幸的是,它支持系统资源

对于本地资源,请使用此解决方案。这并非微不足道,但可以。


17
系统资源是什么意思?strings.xml是否为系统资源?对我来说,它不起作用,说找不到资源。
kirhgoff

6
系统资源属于设备上的Android。strings.xml仅属于您的应用程序。查找stackoverflow.com/a/4391811/715269解决方案
Gangnus

3
对于访问字符串的那些Factory类,这是一个优雅的解决方案。我不喜欢到处传递Context。对于我们只希望全局存储字符串的实例而言,这只是不必要的混乱。
杰·斯奈德

1
这比将上下文传递给类并使用它更有效吗?
SoliQuiD

5
我收到此错误android.content.res.Resources$NotFoundException: String resource ID #0x7f0f0061
Ebrahim Karimi

108

不幸的是,访问任何字符串资源的唯一方法是使用一个Context(即an ActivityService)。在这种情况下,我通常要做的就是简单地要求调用者在上下文中传递。


4
谢谢你的提示!我只是尝试了此操作,但是由于某种原因,我在尝试时遇到了编译错误:ctx.getString(ctx.R.string.blah);
SapphireSun 2010年

我将对util方法的类型进行参数设置,Context以便您可以从Activity或Service中使用它。
MatrixFrog

2
您不需要ctx.R.string.blah,只需使用R.string.blah
Pentium10 2010年

2
我不确定从何symbol not found error而来,但请确保您已R导入该类的顶部。
Pentium10

11
答案是假。对比下一个。:-)
Gangnus 2012年

33

在中MyApplication,它扩展为Application

public static Resources resources;

MyApplicationonCreate

resources = getResources();

现在,您可以在应用程序中的任何位置使用此字段。


通过服务会起作用吗?(特别是当Android终止应用程序并仅启动服务时)
Atul 2016年

1
是的,Android通过调用Application.onCreate开始执行代码,然后运行您的服务。
konmik '16

23

顺便说一句,未找到符号错误的原因之一可能是您的IDE导入了android.R; 类而不是你的。只需更改import android.R; 进口your.namespace.R;

因此,在不同的类中使字符串可见的2个基本事项:

//make sure you are importing the right R class
import your.namespace.R;

//don't forget about the context
public void some_method(Context context) {
   context.getString(R.string.YOUR_STRING);
}

19

独特的方法

App.getRes().getString(R.string.some_id)

这将在应用程序中的任何地方工作。(实用程序类,对话框,片段或应用程序中的任何类

(1)创建或编辑您的Application班级(如果已经存在)。

import android.app.Application;
import android.content.res.Resources;

public class App extends Application {
    private static App mInstance;
    private static Resources res;


    @Override
    public void onCreate() {
        super.onCreate();
        mInstance = this;
        res = getResources();
    }

    public static App getInstance() {
        return mInstance;
    }

    public static Resources getResourses() {
        return res;
    }

}

(2)在manifest.xml <application标签中添加名称字段。

<application
        android:name=".App"
        ...
        >
        ...
    </application>

现在你很好。App.getRes().getString(R.string.some_id)在应用程序中的任何地方使用。


1
我个人喜欢这种方法。方便地从代码中的任何地方获取自定义字符串资源。
checkmate711 '18

此解决方案是否存在任何安全问题?
nibbana

@ user1823280不,我不认为。
Khemraj

完美的解决方案
Yasiru Nayanajith

4

如果您有在活动中使用的类,并且希望访问该类中的资源,则建议您将上下文定义为类中的私有变量,并在构造函数中将其初始化:

public class MyClass (){
    private Context context;

    public MyClass(Context context){
       this.context=context;
    }

    public testResource(){
       String s=context.getString(R.string.testString).toString();
    }
}

在您的活动中上课瞬间:

MyClass m=new MyClass(this);

0

这应该使您可以applicationContext从任何地方访问,从而可以在applicationContext任何可以使用它的地方进行访问。ToastgetString()sharedPreferences,等。

单身人士:

package com.domain.packagename;

import android.content.Context;

/**
 * Created by Versa on 10.09.15.
 */
public class ApplicationContextSingleton {
    private static PrefsContextSingleton mInstance;
    private Context context;

    public static ApplicationContextSingleton getInstance() {
        if (mInstance == null) mInstance = getSync();
        return mInstance;
    }

    private static synchronized ApplicationContextSingleton getSync() {
        if (mInstance == null) mInstance = new PrefsContextSingleton();
        return mInstance;
    }

    public void initialize(Context context) {
        this.context = context;
    }

    public Context getApplicationContext() {
        return context;
    }

}

在您的Application子类中初始化Singleton :

package com.domain.packagename;

import android.app.Application;

/**
 * Created by Versa on 25.08.15.
 */
public class mApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        ApplicationContextSingleton.getInstance().initialize(this);
    }
}

如果我没看错,那么您到处都会有一个对applicationContext的钩子,用调用它。ApplicationContextSingleton.getInstance.getApplicationContext(); 您不需要在任何时候清除它,因为当应用程序关闭时,它还是会伴随它。

记住要更新AndroidManifest.xml以使用此Application子类:

<?xml version="1.0" encoding="utf-8"?>

<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.domain.packagename"
    >

<application
    android:allowBackup="true"
    android:name=".mApplication" <!-- This is the important line -->
    android:label="@string/app_name"
    android:theme="@style/AppTheme"
    android:icon="@drawable/app_icon"
    >

如果您在这里发现任何问题,请告诉我,谢谢。:)


0

应对Khemraj的最佳方法:

应用类别

class App : Application() {

    companion object {
        lateinit var instance: Application
        lateinit var resourses: Resources
    }


    // MARK: - Lifecycle

    override fun onCreate() {
        super.onCreate()
        instance = this
        resourses = resources
    }

}

清单中的声明

<application
        android:name=".App"
        ...>
</application>     

常量类

class Localizations {

    companion object {
        val info = App.resourses.getString(R.string.info)
    }

}

使用

textView.text = Localizations.info

0

最好使用没有上下文活动的类似方法:

Resources.getSystem().getString(R.string.my_text)

0

不知何故不喜欢存储静态值的hacky解决方案,因此提出了更长的时间,但可以测试的干净版本。

发现2种可能的方法-

  1. 将context.resources作为参数传递给想要字符串资源的类。很简单。如果无法作为参数传递,请使用setter。

例如

data class MyModel(val resources: Resources) {
    fun getNameString(): String {
        resources.getString(R.string.someString)
    }
}
  1. 使用数据绑定(尽管需要片段/活动)

阅读之前:此版本使用 Data binding

XML-

<?xml version="1.0" encoding="utf-8"?>

<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">

<data>
    <variable
        name="someStringFetchedFromRes"
        type="String" />
</data>

<TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@{someStringFetchedFromRes}" />
</layout>

活动/片段

val binding = NameOfYourBinding.inflate(inflater)
binding.someStringFetchedFromRes = resources.getString(R.string.someStringFetchedFromRes)

有时,您需要根据模型中的字段更改文本。因此,您也将对该模型进行数据绑定,并且由于您的活动/片段了解该模型,因此您可以很好地获取值,然后根据该值对字符串进行数据绑定。


0

您可以在Kotlin中创建一个扩展Application的类,然后使用其上下文在代码中的任何位置调用资源来完成此操作

您的App类将如下所示

 class App : Application() {
    override fun onCreate() {
        super.onCreate()
        context = this
    }

    companion object {
        var context: Context? = null
            private set
    }
}

在AndroidManifest.xml中声明您的Application类(非常重要)

<application
        android:allowBackup="true"
        android:name=".App" //<--Your declaration Here
        ...>
        <activity
            android:name=".SplashActivity"  android:theme="@style/SplashTheme">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity android:name=".MainActivity"/>
    </application>

要访问例如字符串文件,请使用以下代码

App.context?.resources?.getText(R.string.mystring)

如果您在运行时以编程方式更改语言环境,则此方法将不起作用,因为应用程序上下文是单例,并在进程启动时进行了初始化。
Szörényi亚当

-2

这是我所做的,在您的MainActivity中,为上下文创建一个静态变量,如下所示:

public static Context mContext;

并在onCreate()中初始化mContext;

mContext = this;

然后,在要访问上下文的文件中说:

private Context context = MainActivity.mContext;

现在,您可以通过以下方式获取字符串资源,

String myString = context.getResources().getString(R.string.resource_id);

-8

我用过getContext().getApplicationContext().getString(R.string.nameOfString); 它对我有用 。


14
您认为getContext()到处都有吗?
Hamzeh Soboh,2015年

1
这不能提供问题的答案,因为getContext()仅在activites和fragment类中可用
Umar Ata
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.