정적 컨텍스트에서 리소스 컨텐츠를 얻으려면 어떻게해야합니까?


168

위젯 xml과 같은 다른 많은 작업을 수행하기 전에 파일 에서 문자열을 읽고 싶습니다 setText. 따라서 활동 객체를 호출하지 않고 어떻게 할 수 getResources()있습니까?

답변:


373
  1. Application예를 들어 의 하위 클래스를 만듭니다.public class App extends Application {
  2. 태그 의 android:name속성을 새 클래스를 가리 키도록 설정하십시오. 예 :<application>AndroidManifest.xmlandroid:name=".App"
  3. onCreate()앱 인스턴스 의 메소드에서 컨텍스트 (예 this:)를 이름이 지정된 정적 필드에 저장 mContext하고이 필드를 리턴하는 정적 메소드를 작성하십시오 (예 getContext():

다음과 같이 보입니다.

public class App extends Application{

    private static Context mContext;

    @Override
    public void onCreate() {
        super.onCreate();
        mContext = this;
    }

    public static Context getContext(){
        return mContext;
    }
}

이제 App.getContext()컨텍스트를 얻고 싶을 때마다 getResources()(또는 App.getContext().getResources())를 사용할 수 있습니다.


9
응용 프로그램의 인스턴스는 동적 값이 아닙니다. @Gangnus? 어쨌든 안드로이드에서 정적에 의존하는 것이 어려운 일이라는 것을 알았습니다. "지금 당신은 그것을 보지 못합니다"
Bostone

18
나는 이것이 '핵'이라고 생각하는 것을 피할 수 없다. 완전히 그것을 사용하고 있습니다 (지역화를 외부화하려고했기 때문에이 솔루션을 주신 것에 감사드립니다) 어떻게 든 잘못되었습니다.
Illiax

8
앱의 모든 단일 정적 메소드에서 첫 번째 매개 변수로 컨텍스트를 전달하는 것보다 낫거나 더 낫습니까? 전자는 해키 느낌이지만 후자는 불필요하게 반복적입니다.
Dave

12
문서는 "일반적으로 응용 프로그램을 서브 클래스화할 필요가 없습니다. 대부분의 상황에서 정적 싱글 톤은보다 모듈 방식으로 동일한 기능을 제공 할 수 있습니다. 싱글 톤에 글로벌 컨텍스트 (예 : 브로드 캐스트 수신기 등록)가 필요한 경우 검색하는 함수 싱글 톤을 처음 생성 할 때 내부적으로 Context.getApplicationContext ()를 사용하는 컨텍스트가 제공 될 수 있습니다. " ~ developer.android.com/reference/android/app/Application.html
David d C e Freitas

25
메모리 누수를 피하려면 컨텍스트를 WeakReference에 저장하는 것이 좋습니다. private static WeakReference <Context> mContext; 공개 정적 컨텍스트 getContext () {return mContext.get (); } 이것은 앱이 충돌하고 정적 컨텍스트를 null로 설정할 수없는 경우에 도움이됩니다 (WeakReference는 가비지 수집 가능).
FrankKrumnow

102

시스템 리소스 전용!

사용하다

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

정적 상수 선언에서도 응용 프로그램의 모든 곳에서 사용할 수 있습니다!


2
멋지다. 나는 보통 누군가가 대문자를 사용할 때만 기분을 상하게하지 않습니다 : P 농담. 글쎄, 표준은 문자열 및 드로어 블과 같은 일부 리소스에서 작동하지만 문서에서 알 수 있듯이 방향 측정 등과 같은 작업에는 적합하지 않습니다. 또한 가장 중요한 것은이를 얻을 수 없다는 것입니다. 글로벌 컨텍스트는 때로는 필요할 수도있는 것들에 유용합니다 ( Toast예를 들어 SharedPreference라틴어 교사가 말한 것처럼 예 를 들어 인스턴스를 얻 거나 데이터베이스를 열 때 ).
Cristian

1
당신은 그것으로 세계의 평화를 이길 수조차 없습니다 :-). 그러나 여기서 질문에 의해 설정된 문제를 해결하는 데 도움이됩니다. 나는 그것이 모든 작업을 해결한다고 말하는 것이 아니라 응용 프로그램의 거의 모든 곳에서 작업을 해결한다는 것입니다. Android를 사용할 때마다 10 개월 동안 그러한 솔루션을 검색했습니다. 그리고 지금 나는 그것을 발견했다.
Gangnus

18
여기서 조심해야합니다. 이 방법을 사용하여 앱 리소스를 찾으려고하지 마십시오. 작은 글씨 읽기 : 시스템 리소스 (응용 프로그램 리소스 없음)에만 액세스 할 수 있고 현재 화면에 대해 구성되지 않은 전역 공유 리소스 개체를 반환합니다 (차원 단위를 사용할 수없고 방향에 따라 변경되지 않음 등).
Bostone

4
@ DroidIn.net 인용 : "하지만 시스템 리소스에만 해당됩니다!". / * sigh / *를 알고 있습니다
Gangnus

1
android.content.res.Resources $ NotFoundException : String resource ID
vinidog

6

내 Kotlin 솔루션은 정적 응용 프로그램 컨텍스트를 사용하는 것입니다.

class App : Application() {
    companion object {
        lateinit var instance: App private set
    }

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

그리고 Strings 클래스는 모든 곳에서 사용합니다.

object Strings {
    fun get(@StringRes stringRes: Int, vararg formatArgs: Any = emptyArray()): String {
        return App.instance.getString(stringRes, *formatArgs)
    }
}

따라서 리소스 문자열을 얻는 깔끔한 방법을 가질 수 있습니다

Strings.get(R.string.some_string)
Strings.get(R.string.some_string_with_arguments, "Some argument")

이 답변을 삭제하지 마십시오. 하나를 유지하겠습니다.


간단하고 깨끗한 솔루션, 코드를 공유해 주셔서 감사합니다!
Jeehut

감사! 이것은 알려진 해결책이지만 Strings도움이되었습니다.
CoolMind

4

또 다른 가능성이 있습니다. 다음과 같은 리소스에서 OpenGl 셰이더를로드합니다.

static private String vertexShaderCode;
static private String fragmentShaderCode;

static {
    vertexShaderCode = readResourceAsString("/res/raw/vertex_shader.glsl");
    fragmentShaderCode = readResourceAsString("/res/raw/fragment_shader.glsl");
}

private static String readResourceAsString(String path) {
    Exception innerException;
    Class<? extends FloorPlanRenderer> aClass = FloorPlanRenderer.class;
    InputStream inputStream = aClass.getResourceAsStream(path);

    byte[] bytes;
    try {
        bytes = new byte[inputStream.available()];
        inputStream.read(bytes);
        return new String(bytes);
    } catch (IOException e) {
        e.printStackTrace();
        innerException = e;
    }
    throw new RuntimeException("Cannot load shader code from resources.", innerException);
}

보시다시피 클래스 /res/... 변경 경로의 모든 리소스에 액세스 할 수 있습니다 aClass. 이것은 또한 테스트에서 리소스를로드하는 방법 (androidTests)


1
활동이 없을 때 나를 위해 일한 유일한 솔루션 (응용 프로그램을 확장 할 수있는 클래스가없는 플러그인 개발). 감사합니다 +1
itaton

3

싱글 톤 :

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

이제 어디서나 ApplicationContextSingleton.getInstance (). getApplicationContext (). getResources ()를 사용할 수 있어야하며 응용 프로그램 서브 클래스가없는 곳도 거의 없습니다.

여기에 잘못된 것이 있으면 알려주십시오. 감사합니다. :)


2

다른 해결책 :

비 정적 외부 클래스에 정적 서브 클래스가있는 경우 외부 클래스의 정적 변수를 통해 서브 클래스 내의 자원에 액세스 할 수 있으며,이 클래스는 외부 클래스 작성시 초기화됩니다. 처럼

public class Outerclass {

    static String resource1

    public onCreate() {
        resource1 = getString(R.string.text);
    }

    public static class Innerclass {

        public StringGetter (int num) {
            return resource1; 
        }
    }
}

나는 FragmentActivity 내에서 정적 FragmentPagerAdapter의 getPageTitle (int position) 함수에 사용했으며, 이는 I8N 때문에 유용합니다.


2

지름길

App.getRes()대신에 사용 합니다App.getContext().getResources() @Cristian이 대답 한대로

코드의 어느 곳에서나 사용하는 것은 매우 간단합니다!

다음은 어디서나 리소스에 액세스 할 수 있는 고유 한 솔루션입니다.Util class .

(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)코드 어디에서나 사용하십시오 .


0

더 많은 방법이 가능하다고 생각합니다. 그러나 때로는이 솔루션을 사용합니다. (전체 글로벌) :

    import android.content.Context;

    import <your package>.R;

    public class XmlVar {

        private XmlVar() {
        }

        private static String _write_success;

        public static String write_success() {
            return _write_success;
        }


        public static void Init(Context c) {
            _write_success = c.getResources().getString(R.string.write_success);
        }
    }
//After activity created:
cont = this.getApplicationContext();
XmlVar.Init(cont);
//And use everywhere
XmlVar.write_success();

0

정적 함수에서 openGL ES 용 셰이더를로드합니다.

파일 및 디렉토리 이름에 소문자를 사용해야합니다. 그렇지 않으면 작업이 실패합니다

public class MyGLRenderer implements GLSurfaceView.Renderer {

    ...

    public static int loadShader() {
        //    Read file as input stream
        InputStream inputStream = MyGLRenderer.class.getResourceAsStream("/res/raw/vertex_shader.txt");

        //    Convert input stream to string
        Scanner s = new Scanner(inputStream).useDelimiter("\\A");
        String shaderCode = s.hasNext() ? s.next() : "";
    }

    ...

}

0
public Static Resources mResources;

 @Override
     public void onCreate()
     {
           mResources = getResources();
     }

문제는 getResources ()에 컨텍스트가 필요하다는 것입니다. 따라서 이것은 아마도 "활동 객체없이"(onCreate () 메소드를 게시 한)에 대한 해결책이 아닐 것입니다.
Tobias Reich

0

API 레벨 27을 사용하고 있으며 약 이틀 동안 어려움을 겪고 나서 최상의 솔루션을 찾았습니다. Activity 또는 Application에서 파생되지 않은 클래스에서 xml 파일을 읽으려면 다음을 수행하십시오.

  1. testdata.xml 파일을 자산 디렉토리 안에 넣으십시오.

  2. 테스트 데이터 문서를 구문 분석하려면 다음 코드를 작성하십시오.

        InputStream inputStream = this.getClass().getResourceAsStream("/assets/testdata.xml");
    
        // create a new DocumentBuilderFactory
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        // use the factory to create a documentbuilder
        DocumentBuilder builder = factory.newDocumentBuilder();
        // create a new document from input stream
        Document doc = builder.parse(inputStream);

-1

정적 함수 를 구현하는 클래스에서이 클래스에서 private \ public 메소드를 호출 할 수 있습니다 . private \ public 메소드는 getResources에 액세스 할 수 있습니다 .

예를 들면 다음과 같습니다.

public class Text {

   public static void setColor(EditText et) {
      et.resetColor(); // it works

      // ERROR
      et.setTextColor(getResources().getColor(R.color.Black)); // ERROR
   }

   // set the color to be black when reset
   private void resetColor() {
       setTextColor(getResources().getColor(R.color.Black));
   }
}

다른 수업 활동에서 다음을 호출 할 수 있습니다.

Text.setColor('some EditText you initialized');

-1

상황이 있다면, 내면을 의미합니다.

public void onReceive(Context context, Intent intent){

}

이 코드를 사용하여 리소스를 얻을 수 있습니다.

context.getResources().getString(R.string.app_name);

2
질문의 제목은 정적 인 맥락에서 말합니다. 당신의 대답은 다루지 않습니다.
Rune Schjellerup Philosof
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.