एक संदर्भ या गतिविधि के बाहर हो जाओ


260

मैंने R.stringअपने कोड से हार्डकोड किए गए स्ट्रिंग्स को रखने के लिए बहुत बढ़िया पाया है , और मैं इसे एक उपयोगिता वर्ग में उपयोग करना जारी रखना चाहूंगा जो आउटपुट उत्पन्न करने के लिए मेरे आवेदन में मॉडल के साथ काम करता है। उदाहरण के लिए, इस मामले में मैं गतिविधि के बाहर एक मॉडल से एक ईमेल उत्पन्न कर रहा हूं।

क्या getStringबाहर उपयोग करना संभव है ContextयाActivity ? मुझे लगता है कि मैं वर्तमान गतिविधि में पास हो सकता हूं, लेकिन यह अनावश्यक लगता है। मुझे सही जवाब दो अगर मैं गलत हूँ!

संपादित करें: क्या हम बिना उपयोग किए संसाधनों का उपयोग कर सकते हैं Context?


4
स्ट्रिंग का उपयोग करने जा रहे वर्ग के संदर्भ में, आप इस बारे में भी जानकारी दे रहे हैं कि ऐप किस भाषा (en, es, etc) का उपयोग कर रहा है। तो अगर आपके पास दो तार हैं। xml, तो यह पता चलेगा कि किसका उपयोग करना है
खेल

जवाबों:


440

हां, हम `प्रसंग` का उपयोग किए बिना संसाधनों तक पहुँच सकते हैं

आप उपयोग कर सकते हैं:

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

... आपके आवेदन में हर जगह, स्थिर स्थिरांक घोषणाओं में भी। दुर्भाग्य से, यह केवल सिस्टम संसाधनों का समर्थन करता है

स्थानीय संसाधनों के लिए इस समाधान का उपयोग करें । यह तुच्छ नहीं है, लेकिन यह काम करता है।


17
सिस्टम संसाधनों से क्या अभिप्राय है? strings.xml सिस्टम संसाधन है या नहीं? मेरे लिए यह काम नहीं करता है, कहते हैं कि संसाधन नहीं मिल सकते।
kirhgoff

6
डिवाइस पर सिस्टम संसाधन Android से संबंधित हैं। strings.xml केवल आपके एप्लिकेशन से संबंधित है। के लिए देखो stackoverflow.com/a/4391811/715269 समाधान
Gangnus

3
यह उन फैक्ट्री कक्षाओं के लिए एक सुरुचिपूर्ण समाधान है जब तारों तक पहुंच होती है। मुझे हर जगह प्रसंग के साथ गुजरने में मजा नहीं आता। यह सिर्फ उन उदाहरणों के लिए अनावश्यक अव्यवस्था है जहां हम वास्तव में विश्व स्तर पर संग्रहीत स्ट्रिंग चाहते हैं।
जय स्नाइडर

1
क्या यह एक वर्ग के संदर्भ को पारित करने और इसका उपयोग करने की तुलना में अधिक आकर्षक है ??
सोलीक्यूडी

5
मुझे यह त्रुटि मिलती हैandroid.content.res.Resources$NotFoundException: String resource ID #0x7f0f0061
अब्राहिम करीमी

108

दुर्भाग्य से, आप किसी भी स्ट्रिंग संसाधन तक पहुँचने का एकमात्र तरीका एक Context(यानी Activityया Service) के साथ है। मैंने आमतौर पर इस मामले में जो किया है, वह यह है कि बस कॉल करने वाले को संदर्भ में पास करना होगा।


4
पारितोषिक के लिए धन्यवाद! मैंने बस यह कोशिश की, लेकिन किसी कारण से जब मैंने कोशिश की तो मुझे एक संकलन त्रुटि हो गई:ctx.getString(ctx.R.string.blah);
नीलमणि

मैं तर्क का उपयोग करने के तरीकों के लिए तर्क दूंगा Contextताकि आप इसे किसी गतिविधि या सेवा से उपयोग कर सकें।
MatrixFrog

2
आप की जरूरत नहीं है ctx.R.string.blah, बस का उपयोग करेंR.string.blah
Pentium10

2
मुझे यकीन नहीं है कि कहाँ से symbol not found errorआता है, लेकिन सुनिश्चित करें कि आपने Rकक्षा के शीर्ष पर आयात किया है।
पेंटियम

11
जवाब है FALSE। अगले एक को देखें। :-)
गंगानुस

33

में MyApplication, जिसका विस्तार है Application:

public static Resources resources;

में MyApplicationकी onCreate:

resources = getResources();

अब आप अपने आवेदन में कहीं से भी इस क्षेत्र का उपयोग कर सकते हैं।


क्या यह सेवा के माध्यम से काम करेगा? (खासकर जब एंड्रॉइड ऐप को मारता है और केवल सेवा शुरू करता है)
अतुल

1
हां, Android Application.onCreate पर कॉल करके आपके कोड को निष्पादित करना शुरू कर देता है और इसके बाद यह आपकी सेवा चलाता है।
कोनमिक

23

BTW, त्रुटि नहीं मिली प्रतीक के कारणों में से एक यह हो सकता है कि आपका आईडीई AndroidR आयात करता है; तुम्हारी जगह क्लास। बस आयात androidR बदल ; अपने .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);
}

19

अनोखा दृष्टिकोण

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

यह ऐप में हर जगह काम करेगा। ( यूटिल क्लास, डायलॉग, फ्रैगमेंट या अपने ऐप में कोई भी क्लास )

(१) अपनी 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
मुझे व्यक्तिगत रूप से यह दृष्टिकोण पसंद है। कोड में कहीं से भी कस्टम स्ट्रिंग संसाधन प्राप्त करने के लिए सुविधाजनक है।
चेकमेट 711

क्या इस समाधान के साथ कोई सुरक्षा मुद्दे हैं?
निबाण

@ user1823280 नहीं, मुझे नहीं लगता।
खेमराज

सही समाधान
यासिरु नयनजिथ

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

अगर मैं गलत नहीं हूँ, तो यह आपको हर जगह 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"
    >

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


0

खेमराज की प्रतिक्रिया से सबसे अच्छा तरीका:

अनुप्रयोग वर्ग

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

किसी तरह स्थैतिक मूल्यों को संग्रहीत करने का हैकी समाधान पसंद नहीं आया, इसलिए थोड़ी देर तक लेकिन एक स्वच्छ संस्करण जिसे भी परीक्षण किया जा सकता है।

इसे करने के 2 संभावित तरीके मिले-

  1. जहाँ आप स्ट्रिंग संसाधन चाहते हैं, अपनी श्रेणी के लिए एक पैरामीटर के रूप में Reference.resources पास करें। काफी सरल। यदि परम के रूप में गुजरना संभव नहीं है, तो सेटर का उपयोग करें।

जैसे

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>

गतिविधि / Fragment-

val binding = NameOfYourBinding.inflate(inflater)
binding.someStringFetchedFromRes = resources.getString(R.string.someStringFetchedFromRes)

कभी-कभी, आपको एक मॉडल में फ़ील्ड के आधार पर पाठ को बदलने की आवश्यकता होती है। तो आप उस मॉडल को डेटा-बाइंड करेंगे और चूंकि आपकी गतिविधि / टुकड़ा मॉडल के बारे में जानता है, आप बहुत अच्छी तरह से मूल्य प्राप्त कर सकते हैं और फिर उसके आधार पर स्ट्रिंग को डेटा-बाइंड कर सकते हैं।


0

आप कोटलिन में एक ऐसा वर्ग बना सकते हैं जो अनुप्रयोग का विस्तार करता है और फिर इसके संदर्भ का उपयोग आपके कोड में कहीं भी संसाधनों को कॉल करने के लिए करता है

आपका ऐप क्लास इस तरह दिखेगा

 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)

यदि आप प्रोग्राम को रनटाइम के दौरान स्थानीय रूप से बदलते हैं तो यह काम नहीं करेगा क्योंकि एप्लिकेशन संदर्भ एक सिंगलटन है और जब आपकी प्रक्रिया शुरू हुई थी तो इसे प्रारंभ किया गया था।
सजेनी Áदाम

-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()है कि हर जगह उपलब्ध है ?!
हम्जेह सोबोह

1
यह प्रश्न का उत्तर प्रदान नहीं करता है क्योंकि getContext () केवल एक्टिविटिज और फ्रैगमेंट कक्षाओं में उपलब्ध है
उमर अता
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.