मैं स्थैतिक संदर्भ से संसाधन सामग्री कैसे प्राप्त कर सकता हूं?


168

xmlइससे पहले कि मैं setTextविजेट्स की तरह कुछ और करूं, मैं एक फाइल से स्ट्रिंग पढ़ना चाहता हूं , इसलिए मैं कॉल करने के लिए गतिविधि ऑब्जेक्ट के बिना ऐसा कैसे कर सकता हूं getResources()?

जवाबों:


373
  1. Applicationउदाहरण के लिए, का उपवर्ग बनाएँpublic class App extends Application {
  2. अपने नए वर्ग को इंगित करने के लिए android:nameअपने <application>टैग की विशेषता सेट करें AndroidManifest.xml, जैसेandroid: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 कैसे? किसी भी मामले में - मुझे यह मुश्किल तरीका लगा कि एंड्रॉइड में स्टैटिक्स पर भरोसा करना सिरदर्द के अलावा कुछ नहीं है। "अब आप इसे देखते हैं, अब आप नहीं"
बोसोन

18
मैं यह सोचने से नहीं बच सकता कि यह एक 'हैक' है। कम से कम मैं इसका उपयोग कर रहा हूं (यह समाधान देने के लिए btw धन्यवाद, क्योंकि मैं स्थानीयकरण को समाप्त करने के बारे में था) मुझे यह बुरा लग रहा है, जैसे यह किसी तरह गलत है।
इलियाक्स

8
अपने एप में हर एक स्टैटिक मेथड में पहले पैरामीटर के रूप में कॉन्टेक्ट में पास होने से बेहतर या बुरा? पूर्व में हैकिंग महसूस होती है, लेकिन बाद की आवश्यकता दोहराई जाती है।
डेव

12
डॉक्स कहते हैं "सामान्य रूप से एप्लिकेशन को उप-वर्ग करने की कोई आवश्यकता नहीं है। ज्यादातर स्थिति में, स्थैतिक सिंगललेटन्स अधिक मॉड्यूलर तरीके से एक ही कार्यक्षमता प्रदान कर सकते हैं। यदि आपके सिंगलटन को वैश्विक संदर्भ (उदाहरण के लिए प्रसारण रिसीवर को पंजीकृत करना) की आवश्यकता है, तो फ़ंक्शन को पुनः प्राप्त करने के लिए। यह एक संदर्भ दिया जा सकता है जो आंतरिक रूप से Context.getApplicationContext () का उपयोग करता है जब पहली बार सिंगलटन का निर्माण करते हैं। " ~ developer.android.com/reference/android/app/Application.html
डेविड डी सी ई फ्रीटास

25
मेमोरी को लीक होने से बचाने के लिए एक संदर्भ में संदर्भ को संग्रहीत करना बेहतर होगा: निजी स्थिर कमजोर संदर्भ <संदर्भ> mContext; सार्वजनिक स्थिर संदर्भ getContext () {रिटर्न mContext.get (); } यह तब मदद करता है जब ऐप क्रैश हो जाता है और आप स्थिर संदर्भ को शून्य पर सेट नहीं कर सकते हैं (WeakReference को कचरा एकत्र किया जा सकता है)।
फ्रैंकक्रॉन्ज

102

केवल सिस्टम संसाधनों के लिए!

उपयोग

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

आप स्थैतिक स्थिरांक घोषणाओं में भी उन्हें अपने आवेदन में हर जगह उपयोग कर सकते हैं!


2
यह अच्छा है। मैं आमतौर पर नाराज नहीं होता ... बस जब कोई अपरकेस का उपयोग करता है: पी जस्ट किडिंग। खैर, आपका मानक कुछ संसाधनों जैसे स्ट्रिंग्स और ड्रैबल्स के लिए काम करता है ... हालांकि, जैसा कि प्रलेखन कहता है, यह अभिविन्यास उपायों आदि जैसी चीजों के लिए अच्छा काम नहीं करता है, और साथ ही सबसे महत्वपूर्ण, यह आपको एक प्राप्त करने की अनुमति नहीं देगा। वैश्विक संदर्भ जो कभी-कभी उन चीजों के लिए उपयोगी होता है जिनकी आवश्यकता हो सकती है ( Toastउदाहरण के लिए, SharedPreferenceउदाहरण के लिए, डेटाबेस खोलना, जैसा कि मेरी लैटिन भाषा के शिक्षक कहते हैं: et cetera )।
क्रिस्टियन

1
आप इसे पूरी दुनिया में भी नहीं जीत सकते हैं :-)। लेकिन यह यहां प्रश्न द्वारा निर्धारित समस्या को हल करने में मदद करता है। मैं यह नहीं कह रहा हूं कि यह प्रत्येक कार्य को हल करता है, केवल यह कि यह आवेदन में लगभग हर स्थान पर अपने कार्य को हल करता है। मैंने 10 महीनों के लिए इस तरह के समाधान की तलाश की - हर समय जब मैं एंड्रॉइड का उपयोग करता हूं। और अब मुझे यह मिल गया।
गंगनुस

18
आपको यहां सावधान रहना होगा। इस पद्धति का उपयोग करके अपने एप्लिकेशन संसाधनों को खोजने का प्रयास न करें। ठीक प्रिंट पढ़ें: एक वैश्विक साझा संसाधन ऑब्जेक्ट लौटाएं जो केवल सिस्टम संसाधनों (कोई एप्लिकेशन संसाधन) तक पहुंच प्रदान करता है, और वर्तमान स्क्रीन के लिए कॉन्फ़िगर नहीं किया गया है (आयाम इकाइयों का उपयोग नहीं कर सकता है, अभिविन्यास, आदि के आधार पर परिवर्तित नहीं होता है)।
बोस्टोन

4
@ DroidIn.net प्रशस्ति पत्र: "लेकिन केवल सिस्टम संसाधनों के लिए!"। मुझे पता है / * आह / *
गंगनुस

1
मुझे इसका उपयोग करते हुए एक अपवाद मिला: android.content.res.esource $ NotFoundException: स्ट्रिंग रिसोर्स आईडी
विनिडॉग

6

मेरा Kotlin समाधान एक स्थिर अनुप्रयोग संदर्भ का उपयोग करना है:

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

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

और स्ट्रिंग्स वर्ग, जिसका मैं हर जगह उपयोग करता हूं:

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

कृपया इस उत्तर को न हटाएं, मुझे एक रखने दें।


सरल और साफ समाधान, कोड साझा करने के लिए धन्यवाद!
जीहुत

धन्यवाद! हालांकि यह एक ज्ञात समाधान है, Stringsमददगार था।
CoolMind

4

एक और आधिपत्य भी है। मैं इस तरह से संसाधनों से OpenGl shaders लोड करता हूं:

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

अब आप ApplicationContextSingleton.getInstance () .AppApplicationContext ()। GetResources () का उपयोग कहीं से भी कर सकते हैं, वह भी बहुत कम जगहों पर जहां एप्लिकेशन उपवर्ग can´t।

कृपया मुझे बताएं कि अगर आपको यहां कुछ भी गलत दिखाई देता है, तो धन्यवाद। :)


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 स्थिति) फ़ंक्शन के लिए उपयोग किया, जो I8N के कारण उपयोगी है।


2

छोटा रास्ता

मैं App.getRes()इसके बजाय उपयोग App.getContext().getResources()करता हूं (जैसा कि @Cristian ने उत्तर दिया)

अपने कोड में कहीं भी उपयोग करना बहुत सरल है!

तो यहाँ एक अनूठा समाधान है जिसके द्वारा आप संसाधनों को कहीं से भी एक्सेस कर सकते हैं Util class

(१) अपनी 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

मैं स्थिर कार्य से ओपन ES के लिए shader लोड करता हूं।

याद रखें कि आपको अपनी फ़ाइल और निर्देशिका नाम के लिए निचले मामले का उपयोग करना होगा, अन्यथा ऑपरेशन विफल हो जाएगा

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 () विधि पोस्ट की है) के लिए वास्तव में एक सॉलिट्यूड नहीं है
तोबियास रीच

0

मैं एपीआई स्तर 27 का उपयोग कर रहा हूं और लगभग दो दिनों तक संघर्ष करने के बाद सबसे अच्छा समाधान पाया। यदि आप एक वर्ग से एक 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

अपनी कक्षा में, जहाँ आप स्थैतिक कार्य को लागू करते हैं, आप इस कक्षा से एक निजी \ सार्वजनिक विधि को कॉल कर सकते हैं । निजी \ सार्वजनिक विधि 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
प्रश्न का शीर्षक स्थिर संदर्भ में कहता है। जो आपके उत्तर को कवर नहीं करता है।
रुण श्जेलरुप फिलोसोफ
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.