提问人:SapphireSun 提问时间:11/23/2010 最后编辑:StackExchange What The HeckSapphireSun 更新时间:11/17/2023 访问量:226040
getString 在上下文或 Activity 之外
getString Outside of a Context or Activity
问:
我发现将硬编码字符串排除在我的代码之外非常棒,我想继续在实用程序类中使用它,该类与我的应用程序中的模型一起使用以生成输出。例如,在本例中,我正在从活动外部的模型生成一封电子邮件。R.string
是否可以在 Context
或 Activity
之外使用 getString
?我想我可以传入当前的活动,但这似乎没有必要。如果我错了,请纠正我!
编辑:我们可以在不使用的情况下访问资源吗?Context
答:
不幸的是,访问任何字符串资源的唯一方法是使用 (即 or )。在这种情况下,我通常做的是简单地要求调用方在上下文中传递。Context
Activity
Service
评论
ctx.getString(ctx.R.string.blah);
Context
ctx.R.string.blah
R.string.blah
symbol not found error
R
是的,我们可以在不使用“上下文”的情况下访问资源
您可以使用:
Resources.getSystem().getString(android.R.string.somecommonstuff)
...在应用程序的任何位置,甚至在静态常量声明中。 不幸的是,它仅支持系统资源。
对于本地资源,请使用此解决方案。这不是微不足道的,但它是有效的。
评论
android.content.res.Resources$NotFoundException: String resource ID #0x7f0f0061
顺便说一句,找不到符号错误的原因之一可能是您的 IDE 导入了 android。R;类而不是你的类。只需更改导入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);
}
我用过它对我有用。getContext().getApplicationContext().getString(R.string.nameOfString);
评论
getContext()
在 中,它扩展了:MyApplication
Application
public static Resources resources;
在 的 :MyApplication
onCreate
resources = getResources();
现在,您可以在应用程序中的任何位置使用此字段。
评论
这应该可以让您从任何地方访问,从而让您到达任何可以使用它的地方;等。applicationContext
applicationContext
Toast
getString()
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;
}
}
初始化子类中的 Singleton:Application
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"
>
如果您在这里看到任何问题,请告诉我,谢谢。:)
如果你有一个在活动中使用的类,并且你想访问该类中的资源,我建议你在类中将上下文定义为私有变量,并在构造函数中初始化它:
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);
##独特的方法
##App.getRes().getString(R.string.some_id)
这将在应用程序中的任何地方工作。 (Util 类、Dialog、Fragment 或 应用中的任何类)
(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
<application
android:name=".App"
...
>
...
</application>
现在你已经准备好了。在应用程序中的任何地方使用。App.getRes().getString(R.string.some_id)
评论
Khemraj 回应的最佳方法:
App 类
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>
Constants 类
class Localizations {
companion object {
val info = App.resourses.getString(R.string.info)
}
}
用
textView.text = Localizations.info
评论
不知何故不喜欢存储静态值的笨拙解决方案,所以想出了一个更长但也可以测试的干净版本。
找到了 2 种可能的方法来做到这一点——
- 将 context.resources 作为参数传递给需要字符串资源的类。相当简单。如果无法作为参数传递,请使用 setter。
例如
data class MyModel(val resources: Resources) {
fun getNameString(): String {
resources.getString(R.string.someString)
}
}
- 使用数据绑定(但需要片段/活动)
阅读前:此版本使用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)
有时,您需要根据模型中的字段更改文本。因此,您也会对该模型进行数据绑定,并且由于您的活动/片段知道该模型,因此您可以很好地获取值,然后基于该值对字符串进行数据绑定。
您可以在 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)
评论
- AppCompatActivity
- Companion 对象
活动代码:
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)
评论
如果要在上下文或 Activity 之外使用 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();
内部活动:
Text(text = getString(android.R.string.yes))
内部非活动 :
Text(text = Resources.getSystem().getString(android.R.string.yes))
OR
Text(text = stringResource(android.R.string.yes))
如果你使用的是 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)
}
}
}
根据 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()
若要在没有上下文的情况下访问字符串资源,可以创建一个单独的实用程序类,并将应用程序上下文传递给它。下面是一个示例:
创建一个名为 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)
我用这段代码解决了这个问题
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);
}
评论