上下文或活动之外的getString

我发现R.string非常棒,可以将硬编码的字符串排除在我的代码之外,我想在一个与应用程序中的模型一起工作的实用程序类中继续使用它来生成输出。例如,在本例中,我从活动外部的模型生成了一封电子邮件。

是否可以在__ABC1或__ABC2之外使用getString吗?我想我可以通过目前的活动,但似乎没有必要。如果我说错了,请指正!

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

214530 次浏览

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

是的,我们可以不使用“上下文”来访问资源

你可以使用:

Resources.getSystem().getString(android.R.string.somecommonstuff)
< p >…在应用程序的任何地方,甚至在静态常量声明中。 不幸的是,它支持仅系统资源.

对于本地资源,使用这个解决方案。这不是小事,但很有效。

顺便说一句,符号未找到错误的原因之一可能是你的IDE导入了android.R;而不是你的班级。只需要将进口android.R;改为进口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);
}
< p >我使用 getContext().getApplicationContext().getString(R.string.nameOfString);

MyApplication中,它扩展了Application:

public static Resources resources;

MyApplicationonCreate中:

resources = getResources();

现在您可以在应用程序中的任何地方使用该字段。

这应该让你从任何地方访问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子类中初始化单例:

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

如果你看到这里有什么问题,请告诉我,谢谢。:)

如果你有一个在活动中使用的类,并且你想要访问该类中的资源,我建议你在类中定义一个context作为私有变量,并在构造函数中初始化它:

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类,对话框,片段或 你的应用程序中的任何类)

(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)将name字段添加到manifest.xml <application标记中。

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

现在可以开始了。在应用程序的任何地方使用App.getRes().getString(R.string.some_id)

从赫姆拉吉的回应来看,最好的方法是:

应用程序类

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

不知何故,我不喜欢存储静态值的俗气解决方案,所以提出了一个更长的,但干净的版本,可以测试以及。

找到了两种可能的方法

  1. 通过上下文。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)

有时,您需要根据模型中的字段更改文本。所以你也会数据绑定那个模型,因为你的activity/fragment知道这个模型,你可以很好地获取值,然后基于它数据绑定字符串。

你可以在芬兰湾的科特林中通过创建一个扩展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 < / >强
  • < >强伴星< / >强

活动代码:

class MainActivity : AppCompatActivity() {


companion object {
lateinit var instance: AppCompatActivity
private set
}


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

从任何地方获取资源:

val text = MainActivity.instance.getString(R.string.task_1)
如果你想在上下文或活动之外使用getString,你应该在构造函数或方法参数中有上下文,这样你就可以访问getString()方法。 特别是在Fragment中,你应该确保getActivity()或getContext()没有提供空值。 要避免在Fragment中getActivity()或getContext()为空,请尝试以下方法: 声明一个变量:

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。 例:< / p >

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

如果你正在使用,你实际上可以注入上下文:

@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()