컨텍스트 또는 활동 외부의 getString


260

R.string하드 코드 된 문자열을 코드에서 유지하는 것이 매우 훌륭 하다는 것을 알았으며 응용 프로그램의 모델과 함께 작동하여 출력을 생성하는 유틸리티 클래스에서 계속 사용하고 싶습니다. 예를 들어,이 경우 활동 외부의 모델에서 이메일을 생성합니다.

또는 getString밖에서 사용할 수ContextActivity 있습니까? 현재 활동을 통과 할 수 있다고 생각하지만 불필요한 것 같습니다. 내가 틀렸다면 정정 해주세요!

편집 : 우리는 사용 하지 않고 리소스에 액세스 할 수 있습니까 Context?


4
문자열을 사용할 클래스에 컨텍스트를 전달하면 앱에서 사용중인 언어 (en, es 등)에 대한 정보도 전달됩니다. 따라서 두 개의 strings.xml이 있으면 어떤 것을 사용해야하는지 알 수 있습니다
sports

답변:


440

예, 컨텍스트를 사용하지 않고도 리소스에 액세스 할 수 있습니다

당신이 사용할 수있는:

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

... 정적 상수 선언에서도 응용 프로그램의 모든 곳에서. 불행히도 시스템 리소스 만 지원 합니다 .

로컬 리소스의 경우이 솔루션을 사용 하십시오 . 사소한 것이 아니지만 작동합니다.


17
시스템 리소스 란 무엇입니까? strings.xml은 시스템 리소스입니까? 나를 위해 그것은 작동하지 않는다고 말합니다.
kirhgoff

6
시스템 리소스는 기기에서 Android에 속합니다. strings.xml은 애플리케이션에만 속합니다. stackoverflow.com/a/4391811/715269 솔루션 찾기
Gangnus

3
이것은 문자열에 액세스 할 때 해당 팩토리 클래스에 대한 우아한 솔루션입니다. 나는 어디에서나 컨텍스트를 통과하는 것을 좋아하지 않습니다. 실제로 문자열을 전역에 저장하려는 경우 불필요합니다.
Jay Snayder

1
컨텍스트를 클래스에 전달하고 사용하는 것보다 더 효과적입니까 ??
SoliQuiD

5
이 오류가 얻을android.content.res.Resources$NotFoundException: String resource ID #0x7f0f0061
에브라힘 카리미

108

불행히도 문자열 리소스에 액세스 할 수있는 유일한 방법은 Context( Activity또는 Service)를 사용하는 것입니다. 이 경우에 일반적으로 한 일은 단순히 호출자가 컨텍스트를 전달하도록 요구하는 것입니다.


4
팁 고마워! 방금 이것을 시도했지만 어떤 이유로 든 시도 할 때 컴파일 오류가 발생했습니다.ctx.getString(ctx.R.string.blah);
SapphireSun

ContextActivity 또는 Service에서 사용할 수 있도록 유형의 util 메소드에 인수를 작성합니다 .
MatrixFrog

2
당신은 필요하지 않습니다 ctx.R.string.blah, 단지 사용R.string.blah
Pentium10

2
어디에서 왔는지 확실하지 symbol not found error않지만 R수업 상단에 가져 왔는지 확인하십시오 .
Pentium10

11
대답은 거짓입니다. 다음 하나를보십시오. :-)
Gangnus

33

에서 MyApplication확장 Application:

public static Resources resources;

에서 MyApplication의 ' onCreate:

resources = getResources();

이제 응용 프로그램의 어느 곳에서나이 필드를 사용할 수 있습니다.


서비스를 통해 작동합니까? (특히 Android가 앱을 종료하고 서비스 만 시작하는 경우)
Atul

1
예, Android는 Application.onCreate를 호출하여 코드를 실행 한 후 서비스를 실행합니다.
konmik

23

BTW, symbol not found 오류 의 원인 중 하나는 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);
}

19

독특한 접근법

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

이것은 응용 프로그램의 모든 곳에서 작동합니다. ( Util class, 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 getResourses() {
        return res;
    }

}

(2) 이름 필드를 manifest.xml <application태그에 추가하십시오 .

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

이제 잘 가십시오. App.getRes().getString(R.string.some_id)앱 어디에서나 사용하십시오 .


1
나는 개인적으로이 접근법을 좋아한다. 코드의 어느 곳에서나 사용자 지정 문자열 리소스를 얻는 것이 편리합니다.
checkmate711

이 솔루션에 보안 문제가 있습니까?
nibbana

아니요, 생각하지 않습니다.
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합니다. 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;
    }

}

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

내가 틀리지 않으면 응용 프로그램 컨텍스트에 대한 연결 고리를 제공합니다. ApplicationContextSingleton.getInstance.getApplicationContext(); 어플리케이션을 닫을 때와 같이 언제든지 지울 필요는 없습니다.

AndroidManifest.xmlApplication서브 클래스 를 사용 하도록 업데이트하십시오 :

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

어쨌든 정적 값을 저장하는 해키 솔루션이 마음에 들지 않아 조금 더 길지만 깨끗한 버전도 테스트 할 수있었습니다.

가능한 두 가지 방법을 찾았습니다.

  1. 문자열 리소스를 원하는 클래스에 context.resources를 매개 변수로 전달하십시오. 상당히 간단합니다. param으로 전달할 수 없으면 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을 확장하는 클래스를 만든 다음 해당 컨텍스트를 사용하여 코드의 어느 곳에서나 리소스를 호출하여이를 수행 할 수 있습니다.

앱 클래스는 다음과 같습니다

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

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

AndroidManifest.xml에서 애플리케이션 클래스 선언 (매우 중요)

<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 Ádám

-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

1
getContext ()는 액티비티 및 프래그먼트 클래스에서만 사용 가능하므로 질문에 대한 답변을 제공하지 않습니다.
Umar Ata
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.