上下文或活动之外的 getString

发布于 2024-10-03 13:16:55 字数 313 浏览 4 评论 0 原文

我发现 R.string 非常适合将硬编码字符串保留在我的代码之外,并且我希望继续在实用程序类中使用它,该实用程序类与我的应用程序中的模型配合使用以生成输出。例如,在本例中,我从活动之外的模型生成一封电子邮件。

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

编辑:我们可以在不使用Context的情况下访问资源吗?

I've found the R.string pretty awesome for keeping hardcoded strings out of my code, and I'd like to keep using it in a utility class that works with models in my application to generate output. For instance, in this case I am generating an email from a model outside of the activity.

Is it possible to use getString outside a Context or Activity? I suppose I could pass in the current activity, but it seems unnecessary. Please correct me if I'm wrong!

Edit: Can we access the resources without using Context?

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

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

发布评论

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

评论(18

旧故 2024-10-10 13:16:55

是的,我们可以在不使用“Context”的情况下访问资源

使用:

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

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

对于本地资源,请使用此解决方案。这不是微不足道的,但它确实有效。

Yes, we can access resources without using `Context`

You can use:

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

... everywhere in your application, even in static constants declarations.
Unfortunately, it supports the system resources only.

For local resources use this solution. It is not trivial, but it works.

挽你眉间 2024-10-10 13:16:55

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

Unfortunately, the only way you can access any of the string resources is with a Context (i.e. an Activity or Service). What I've usually done in this case, is to simply require the caller to pass in the context.

动听の歌 2024-10-10 13:16:55

MyApplication 中,它扩展了 Application

public static Resources resources;

MyApplicationonCreate 中:

resources = getResources();

现在您可以在任何位置使用此字段您的申请。

In MyApplication, which extends Application:

public static Resources resources;

In MyApplication's onCreate:

resources = getResources();

Now you can use this field from anywhere in your application.

有深☉意 2024-10-10 13:16:55

##独特的方法

##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 getRes() {
        return res;
    }

}

(2) 将名称字段添加到 manifest.xml 标记中。

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

现在你可以走了。在应用程序中的任何位置使用 App.getRes().getString(R.string.some_id)

##Unique Approach

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

This will work everywhere in app. (Util class, Dialog, Fragment or
any class in your app
)

(1) Create or Edit (if already exist) your Application class.

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 getRes() {
        return res;
    }

}

(2) Add name field to your manifest.xml <application tag.

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

Now you are good to go. Use App.getRes().getString(R.string.some_id) anywhere in app.

能否归途做我良人 2024-10-10 13:16:55

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

因此,要使字符串在不同的类中可见,需要做两件事:

//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);
}

BTW, one of the reason of symbol not found error may be that your IDE imported android.R; class instead of yours one. Just change import android.R; to import your.namespace.R;

So 2 basic things to get string visible in the different class:

//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);
}
失而复得 2024-10-10 13:16:55

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

The best approach from the response of Khemraj:

App class

class App : Application() {

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


    // MARK: - Lifecycle

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

}

Declaration in the manifest

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

Constants class

class Localizations {

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

}

Using

textView.text = Localizations.info
枕花眠 2024-10-10 13:16:55

内部活动 :

Text(text = getString(android.R.string.yes))

内部非活动 :

Text(text = Resources.getSystem().getString(android.R.string.yes))

                          OR

Text(text = stringResource(android.R.string.yes))

Inside Activity :

Text(text = getString(android.R.string.yes))

Inside Non-Activity :

Text(text = Resources.getSystem().getString(android.R.string.yes))

                          OR

Text(text = stringResource(android.R.string.yes))
森林很绿却致人迷途 2024-10-10 13:16:55

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

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);

If you have a class that you use in an activity and you want to have access the ressource in that class, I recommend you to define a context as a private variable in class and initial it in constructor:

public class MyClass (){
    private Context context;

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

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

Making an instant of class in your activity:

MyClass m=new MyClass(this);
偏爱自由 2024-10-10 13:16:55

您可以在 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)

You can do this in Kotlin by creating a class that extends Application and then use its context to call the resources anywhere in your code

Your App class will look like this

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

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

Declare your Application class in AndroidManifest.xml (very important)

<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>

To access e.g. a string file use the following code

App.context?.resources?.getText(R.string.mystring)
一人独醉 2024-10-10 13:16:55

遵循并基于 Khemraj Sharma 的答案,这是 Kotlin 版本,带有额外的扩展作为奖励:

class App: Application() {

    override fun onCreate() {
        super.onCreate()
        mInstance = this
        res = resources
    }
    companion object{

        private var mInstance: App? = null
        private var res: Resources? = null

        fun getInstance(): App? {
            return mInstance
        }

        fun getRes(): Resources? {
            return res
        }
    }
}

然后我们可以创建一个扩展:

fun Int.resourceToString(): String {
    return App.getRes()?.getString(this) ?: "Not Found"
}

并直接在任何资源 id 上使用扩展:

var asString = R.string.my_string.resourceToString()

Following and based on Khemraj Sharma's answer, this is the Kotlin version, with an extra extention as a bonus:

class App: Application() {

    override fun onCreate() {
        super.onCreate()
        mInstance = this
        res = resources
    }
    companion object{

        private var mInstance: App? = null
        private var res: Resources? = null

        fun getInstance(): App? {
            return mInstance
        }

        fun getRes(): Resources? {
            return res
        }
    }
}

Then we can create an extension:

fun Int.resourceToString(): String {
    return App.getRes()?.getString(this) ?: "Not Found"
}

And use the extention directly on any resource id:

var asString = R.string.my_string.resourceToString()
安稳善良 2024-10-10 13:16:55

这应该让您可以从任何地方访问 applicationContext ,从而让您可以在任何可以使用它的地方获取 applicationContextToastgetString()sharedPreferences 等。

Singleton:

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"
    >

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

This should get you access to applicationContext from anywhere allowing you to get applicationContext anywhere that can use it; Toast, getString(), sharedPreferences, etc.

The Singleton:

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;
    }

}

Initialize the Singleton in your Application subclass:

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);
    }
}

If I´m not wrong, this gives you a hook to applicationContext everywhere, call it with ApplicationContextSingleton.getInstance.getApplicationContext();
You shouldn´t need to clear this at any point, as when application closes, this goes with it anyway.

Remember to update AndroidManifest.xml to use this Application subclass:

<?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"
    >

Please let me know if you see anything wrong here, thank you. :)

鸢与 2024-10-10 13:16:55

如果您使用 Hilt,您实际上可以注入上下文:

@Module
@InstallIn(SingletonComponent::class)
interface ResourceProvider {

    companion object {
    
    @Provides
    @Singleton
    @MyQualifier
    fun providesBaseUrl(@ApplicationContext context: Context): String = with(context) {
      getString(R.string.my_value)
    }
  }
}

If you are using Hilt, you can actually inject the context:

@Module
@InstallIn(SingletonComponent::class)
interface ResourceProvider {

    companion object {
    
    @Provides
    @Singleton
    @MyQualifier
    fun providesBaseUrl(@ApplicationContext context: Context): String = with(context) {
      getString(R.string.my_value)
    }
  }
}
狼性发作 2024-10-10 13:16:55

不知何故,我不喜欢存储静态值的黑客解决方案,因此想出了一个更长但也可以测试的干净版本。

找到了两种可能的方法 - 将

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

例如

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

在阅读之前:此版本使用数据绑定

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)

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

Somehow didn't like the hacky solutions of storing static values so came up with a bit longer but a clean version which can be tested as well.

Found 2 possible ways to do it-

  1. Pass context.resources as a parameter to your class where you want the string resource. Fairly simple. If passing as param is not possible, use the setter.

e.g.

data class MyModel(val resources: Resources) {
    fun getNameString(): String {
        resources.getString(R.string.someString)
    }
}
  1. Use the data-binding (requires fragment/activity though)

Before you read: This version uses 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>

Activity/Fragment-

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

Sometimes, you need to change the text based on a field in a model. So you would data-bind that model as well and since your activity/fragment knows about the model, you can very well fetch the value and then data-bind the string based on that.

忆依然 2024-10-10 13:16:55

如果您想在上下文或活动之外使用 getString,您应该在构造函数或方法参数中具有上下文,以便您可以访问 getstring() 方法。
特别是在 Fragment 中,您应该确保 getActivity() 或 getContext() 不提供 null 值。
要避免 Fragment 中的 getActivity() 或 getContext() 为 null,请尝试以下操作:
声明一个变量:

Context mContext;

现在覆盖 Fragment 的 onAttach 和 onDetach 方法:

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    mContext = context;
}

@Override
public void onDetach() {
    super.onDetach();
    mContext = null;
}

现在无论您在哪里使用 getString() 方法,都使用 mContext
前任:

        Toast.makeText(mContext,  mContext.getString(R.string.sample_toast_from_string_file), Toast.LENGTH_SHORT).show();

If you want to use getString Outside of a Context or Activity you should have context in constructor or method parameter so that you can access getstring() method.
Specially in Fragment You shoud ensure that getActivity() or getContext() are not providing null value.
To avoid null from getActivity() or getContext() in a Fragment try this :
Declare a variable :

Context mContext;

now override onAttach and onDetach method of Fragment :

@Override
public void onAttach(Context context) {
    super.onAttach(context);
    mContext = context;
}

@Override
public void onDetach() {
    super.onDetach();
    mContext = null;
}

Now Use mContext whereever you are using getString() method.
ex:

        Toast.makeText(mContext,  mContext.getString(R.string.sample_toast_from_string_file), Toast.LENGTH_SHORT).show();
智商已欠费 2024-10-10 13:16:55

要在没有上下文的情况下访问字符串资源,您可以创建一个单独的实用程序类并将应用程序上下文传递给它。下面是一个示例:

创建一个名为 ResourceUtils 的类:

   object ResourceUtils {
        private var applicationContext: Context? = null
    
        fun initialize(context: Context) {
            applicationContext = context.applicationContext
        }
    
        fun getString(resId: Int): String {
            applicationContext?.let {
                return it.resources.getString(resId)
            }
            throw IllegalStateException("ResourceUtils not initialized with application context")
        }
    }

在您的 Application 类中,使用应用程序上下文初始化 ResourceUtils:

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        ResourceUtils.initialize(this)
    }
}

现在,您可以使用 ResourceUtils.getString() 来访问没有上下文的字符串资源:

val appName = ResourceUtils.getString(R.string.app_name)

To access string resources without a context, you can create a separate utility class and pass the application context to it. Here's an example:

Create a class named ResourceUtils:

   object ResourceUtils {
        private var applicationContext: Context? = null
    
        fun initialize(context: Context) {
            applicationContext = context.applicationContext
        }
    
        fun getString(resId: Int): String {
            applicationContext?.let {
                return it.resources.getString(resId)
            }
            throw IllegalStateException("ResourceUtils not initialized with application context")
        }
    }

In your Application class, initialize the ResourceUtils with the application context:

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        ResourceUtils.initialize(this)
    }
}

Now, you can use ResourceUtils.getString() to access string resources without a context:

val appName = ResourceUtils.getString(R.string.app_name)
智商已欠费 2024-10-10 13:16:55

我用这段代码解决了这个问题

holder.btnAddFriend.setOnClickListener(v -> {
        // Obtener el nombre del usuario del elemento actual

        String username = user.getUsername();
        String id = v.getContext().getResources().getString(R.string.idusd);
 }

I resolve this problem with this code

holder.btnAddFriend.setOnClickListener(v -> {
        // Obtener el nombre del usuario del elemento actual

        String username = user.getUsername();
        String id = v.getContext().getResources().getString(R.string.idusd);
 }
天荒地未老 2024-10-10 13:16:55
  • AppCompatActivity
  • 伴随对象

活动代码:

class MainActivity : AppCompatActivity() {

    companion object {
        lateinit var instance: AppCompatActivity
            private set
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        instance = this
    }
}

从 AnyWhere 获取资源:

val text = MainActivity.instance.getString(R.string.task_1)
  • AppCompatActivity
  • Companion object

Activity code:

class MainActivity : AppCompatActivity() {

    companion object {
        lateinit var instance: AppCompatActivity
            private set
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        instance = this
    }
}

Getting a resource from AnyWhere:

val text = MainActivity.instance.getString(R.string.task_1)
梦情居士 2024-10-10 13:16:55

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

I used
getContext().getApplicationContext().getString(R.string.nameOfString);
It works for me.

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