एंड्रॉइड में 'कॉन्टेक्ट' पाने का स्टैटिक तरीका?


970

क्या Contextस्थैतिक विधि के अंदर वर्तमान आवृत्ति प्राप्त करने का एक तरीका है?

मैं उस तरह की तलाश कर रहा हूं क्योंकि मैं हर बार बदलने के दौरान 'प्रसंग' उदाहरण को सहेजने से नफरत करता हूं।


57
प्रसंग नहीं सहेजना एक अच्छा विचार है न सिर्फ इसलिए कि यह असुविधाजनक है, बल्कि इसलिए भी क्योंकि इससे बड़ी मेमोरी लीक हो सकती है!
विक्रम बोडिचेर्ला

12
@VikramBodicherla हां, लेकिन नीचे दिए गए जवाब यह मानते हैं कि हम एप्लिकेशन संदर्भ के बारे में बात कर रहे हैं। तो, मेमोरी लीक एक मुद्दा नहीं है, लेकिन उपयोगकर्ता को केवल इन समाधानों का उपयोग करना चाहिए जहां उपयोग करने के लिए सही संदर्भ है।
टॉम

यदि आपको प्राप्त करने का एक स्थिर तरीका उपयोग करना है Context, तो कोड को डिज़ाइन करने का एक बेहतर तरीका हो सकता है।
अनॉसेज

3
एंड्रॉइड डॉक्यूमेंटेशन एकल के गेटर्स के संदर्भ को पारित करने की सिफारिश करता है। developer.android.com/reference/android/app/Application.html
मार्को लुग्लियो

एकमात्र और संदर्भ getInstance () स्थिर संदर्भ से अधिक के साथ पारित पसंद करते हैं के लिए, कृपया, एक नजर है मैं अपने तर्क समझाने की कोशिश की यहाँ काम कोड के साथ समर्थित: stackoverflow.com/a/38967293/4469112
एलेसियो

जवाबों:


1302

यह करो:

Android मैनिफ़ेस्ट फ़ाइल में, निम्न की घोषणा करें।

<application android:name="com.xyz.MyApplication">

</application>

फिर कक्षा लिखें:

public class MyApplication extends Application {

    private static Context context;

    public void onCreate() {
        super.onCreate();
        MyApplication.context = getApplicationContext();
    }

    public static Context getAppContext() {
        return MyApplication.context;
    }
}

अब हर जगह MyApplication.getAppContext()अपने आवेदन के संदर्भ को सांख्यिकीय रूप से प्राप्त करने के लिए कॉल करें ।


81
क्या इस पद्धति का कोई नकारात्मक पहलू है? यह धोखा जैसा लगता है। (ए हैक?)
jjnguy

203
नकारात्मक पक्ष यह है कि इस बात की कोई गारंटी नहीं है कि आपके स्टेटिक ऑब्जेक्ट को लाने के लिए कुछ स्टेटिक इनिशियलाइज़ेशन कोड को लाने से पहले नॉन-स्टैटिक ऑनक्रिएट () को कॉल किया जाएगा। इसका मतलब है कि आपके कॉलिंग कोड को उन शून्य मानों से निपटने के लिए तैयार रहने की आवश्यकता होगी जो इस प्रश्न के पूरे बिंदु को हराते हैं।
मेलिंडा ग्रीन

8
भी शायद .. हम इस static contextचर के रूप में घोषित करना चाहिए volatile?
व्लादिमीर सोरोकिन

14
@ यह एक स्टैटिक डेटा सदस्य के शुरू में स्टेटिक होने का मामला नहीं है। दिए गए कोड में, स्थिर सदस्य को ऑन-क्रिएट () में गैर-सांख्यिकीय रूप से आरंभीकृत किया जा रहा है। यहां तक ​​कि वैधानिक रूप से आरंभिक डेटा भी इस मामले में पर्याप्त नहीं है क्योंकि कुछ भी यह सुनिश्चित नहीं करता है कि दिए गए वर्ग का स्थैतिक आरंभ कुछ अन्य वर्ग के स्थैतिक आरंभ के दौरान एक्सेस होने से पहले होगा।
मेलिंडा ग्रीन

10
@MelindaGreen अनुप्रयोग के लिए प्रलेखन के अनुसार, onCreate () को किसी भी गतिविधि, सेवा या रिसीवर (सामग्री प्रदाताओं को छोड़कर) से पहले कहा जाता है। तो क्या यह समाधान तब तक सुरक्षित नहीं होगा जब तक आप किसी कंटेंट प्रोवाइडर से getAppContext () एक्सेस करने की कोशिश नहीं कर रहे हैं?
मैग्नस डब्ल्यू

86

एप्लिकेशन संदर्भ प्राप्त करने के लिए एक सुविधाजनक तरीका चाहते हैं, जो बहुसंख्यक अपनी खुद की कक्षा बनाते हैं जो फैली हुई है android.app.Application

मार्गदर्शक

आप अपनी परियोजना में निम्नलिखित की तरह पहली कक्षा बनाकर इसे पूरा कर सकते हैं:

import android.app.Application;
import android.content.Context;

public class App extends Application {

    private static Application sApplication;

    public static Application getApplication() {
        return sApplication;
    }

    public static Context getContext() {
        return getApplication().getApplicationContext();
    }

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

फिर, अपने AndroidManifest में आपको AndroidManifest.xml के टैग में अपनी कक्षा का नाम निर्दिष्ट करना चाहिए:

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

फिर आप निम्न का उपयोग करके किसी भी स्थिर विधि में एप्लिकेशन संदर्भ प्राप्त कर सकते हैं:

public static void someMethod() {
    Context context = App.getContext();
}

चेतावनी

अपने प्रोजेक्ट में उपरोक्त जैसा कुछ जोड़ने से पहले आपको विचार करना चाहिए कि प्रलेखन क्या कहता है:

एप्लिकेशन को उप-वर्ग करने की कोई आवश्यकता नहीं है। अधिकांश स्थिति में, स्थिर एकल एकल अधिक कार्यात्मक तरीके से समान कार्यक्षमता प्रदान कर सकते हैं। यदि आपके सिंगलटन को एक वैश्विक संदर्भ (उदाहरण के लिए प्रसारण रिसीवर्स को पंजीकृत करना) की आवश्यकता है, तो इसे पुनः प्राप्त करने के लिए फ़ंक्शन को एक संदर्भ दिया जा सकता है जो पहली बार सिंगलटन का निर्माण करते समय Context.getApplicationContext () का उपयोग करता है।


प्रतिबिंब

प्रतिबिंब का उपयोग करके एप्लिकेशन संदर्भ प्राप्त करने का एक और तरीका भी है। प्रतिबिंब को अक्सर एंड्रॉइड पर देखा जाता है और मुझे व्यक्तिगत रूप से लगता है कि इसका उपयोग उत्पादन में नहीं किया जाना चाहिए।

एप्लिकेशन संदर्भ को पुनः प्राप्त करने के लिए हमें एक छिपे हुए वर्ग ( एक्टिविटीथ्रेड ) पर एक विधि लागू करनी चाहिए जो एपीआई 1 के बाद से उपलब्ध है।

public static Application getApplicationUsingReflection() throws Exception {
    return (Application) Class.forName("android.app.ActivityThread")
            .getMethod("currentApplication").invoke(null, (Object[]) null);
}

एक और छिपा वर्ग ( AppGlobals ) है जो एक स्थिर तरीके से एप्लिकेशन संदर्भ प्राप्त करने का एक तरीका प्रदान करता है। यह संदर्भ का उपयोग करता है ActivityThreadइसलिए वास्तव में निम्नलिखित विधि और ऊपर पोस्ट किए गए के बीच कोई अंतर नहीं है:

public static Application getApplicationUsingReflection() throws Exception {
    return (Application) Class.forName("android.app.AppGlobals")
            .getMethod("getInitialApplication").invoke(null, (Object[]) null);
} 

हैप्पी कोडिंग!


56

यह मानते हुए कि हम अनुप्रयोग संदर्भ प्राप्त करने के बारे में बात कर रहे हैं, मैंने इसे @Rohit Ghatol द्वारा दिए गए अनुप्रयोग के अनुसार सुझाया। फिर क्या हुआ, यह है कि इस बात की कोई गारंटी नहीं है कि इस तरह से प्राप्त किया गया संदर्भ हमेशा अशक्त रहेगा। जिस समय आपको इसकी आवश्यकता होती है, यह आमतौर पर इसलिए होता है क्योंकि आप एक सहायक को प्रारंभ करना चाहते हैं, या एक संसाधन प्राप्त करना चाहते हैं, ताकि आप समय में देरी न कर सकें; अशक्त मामले को संभालने से आपको मदद नहीं मिलेगी। इसलिए मैंने समझा कि मैं मूल रूप से एंड्रॉइड आर्किटेक्चर के खिलाफ लड़ रहा था, जैसा कि डॉक्स में बताया गया है

नोट: आमतौर पर एप्लिकेशन को उपवर्ग करने की कोई आवश्यकता नहीं है। ज्यादातर स्थितियों में, स्टैटिक सिंगललेट अधिक कार्यात्मक तरीके से समान कार्यक्षमता प्रदान कर सकते हैं। यदि आपके सिंगलटन को वैश्विक संदर्भ की आवश्यकता है (उदाहरण के लिए प्रसारण रिसीवर्स को पंजीकृत करने के लिए), तो कॉन्टेक्स्ट तर्क के रूप में Context.getApplicationContext () को शामिल करें जब आपके सिंगलटन के getInstance () विधि को लागू किया जाए।

और डायने हैकॉर्न द्वारा समझाया गया

एकमात्र कारण यह है कि आप जिस चीज से प्राप्त कर सकते हैं, उसका एकमात्र कारण यह है कि हमारे विकास के पूर्व 1.0 विकास के दौरान डेवलपर्स लगातार मुझे इस बात के लिए प्रेरित कर रहे थे कि उन्हें एक शीर्ष-स्तरीय एप्लिकेशन ऑब्जेक्ट की आवश्यकता हो, जिससे वे प्राप्त कर सकें ताकि वे अधिक "सामान्य" हो सकें "उनके लिए आवेदन मॉडल, और मैंने अंततः दिया। मैं हमेशा उस पर देने का अफसोस करूंगा।" :)

वह इस समस्या के समाधान का सुझाव भी दे रही है:

यदि आप चाहते हैं कि कुछ वैश्विक स्थिति है जिसे आपके ऐप के विभिन्न हिस्सों में साझा किया जा सकता है, तो एक सिंगलटन का उपयोग करें। [...] और यह स्वाभाविक रूप से इस बात की ओर जाता है कि आपको इन चीजों को कैसे प्रबंधित करना चाहिए - उन्हें मांग पर आरंभ करना।

इसलिए मैंने जो किया था वह अनुप्रयोग को निकालने से छुटकारा पा रहा था, और निजी कंस्ट्रक्टर में आवेदन के संदर्भ के संदर्भ को सहेजते हुए संदर्भ को सीधे सिंगलटन हेल्पर के गेटइनस्टांस () में भेज दें:

private static MyHelper instance;
private final Context mContext;    

private MyHelper(@NonNull Context context) {
    mContext = context.getApplicationContext();
}

public static MyHelper getInstance(@NonNull Context context) {
    synchronized(MyHelper.class) {
        if (instance == null) {
            instance = new MyHelper(context);
        }
        return instance;
    }
}

कॉल करने वाला फिर सहायक के लिए एक स्थानीय संदर्भ पास करेगा:

Helper.getInstance(myCtx).doSomething();

इसलिए, इस सवाल का ठीक से जवाब देने के लिए: आवेदन के संदर्भ को कानूनी रूप से एक्सेस करने के तरीके हैं, लेकिन वे सभी को हतोत्साहित किया जाना चाहिए, और आपको सिंगलटन के getInstance () के लिए एक स्थानीय संदर्भ पास करना पसंद करना चाहिए।


रुचि रखने वाले किसी भी व्यक्ति के लिए, आप fwd ब्लॉग पर अधिक विस्तृत संस्करण पढ़ सकते हैं


1
@Alessio इस विधि को स्मृति लीक की ओर नहीं ले जाता है
फिलिप Kigenyi

2
@codephillip मुझे समझ नहीं आ रहा है कि आप किस बारे में बात कर रहे हैं। सिंगलटन ने पास की गतिविधि से प्राप्त अनुप्रयोग संदर्भ को संदर्भित किया, न कि मेजबान गतिविधि को। यह वैध है, और यह किसी भी स्मृति रिसाव का कारण नहीं होगा। मेरे द्वारा लिखे गए ब्लॉग का मुख्य बिंदु यही है । यदि आप वास्तव में सोचते हैं कि आप सही हैं, तो कृपया मुझे एक नमूना कोड भेजें जहां मैं आपके बारे में बात कर रहे मेमोरी लीक को पुन: उत्पन्न कर सकता हूं, क्योंकि यह मामला नहीं है।
एलेसियो

1
मुझे लगता है कि @KigenyiPhillip सही है, और यह अभी भी एक संसाधन रिसाव का प्रतिनिधित्व करता है। आपके पहले कॉल के बाद संदर्भ चार्ट चित्र getInstance(ctx)। आपके पास जीसी रूट instanceका प्रकार है MyHelper, जिसमें एक निजी mContextप्रकार का क्षेत्र है, जो पास Contextकिए गए संदर्भ के माध्यम से एकत्र किए गए एप्लिकेशन संदर्भ को संदर्भित करता है getInstance()instanceदूसरी बार सेट नहीं किया गया है, न ही क्लियर किया गया है, इसलिए GC कभी भी अपॉइंटमेंट को संदर्भित नहीं करेगा instance। आप किसी भी गतिविधियों को लीक नहीं करते हैं इसलिए यह कम लागत वाला IMO है।
मार्क मैककेना

1
@MarkMcKenna जैसा कि आप कहते हैं "जिसके पास एक निजी क्षेत्र है टाइप कॉन्क्स्ट का mContext, जो अनुप्रयोग संदर्भ को संदर्भित करता है", इसलिए यह आपके लिए स्पष्ट है कि mContext किसी संदर्भ के लिए नहीं, बल्कि अनुप्रयोग संदर्भ का संदर्भ है। में getApplicationContext () डॉक्स आप पढ़ सकते हैं: "एक प्रसंग जिसका जीवन चक्र वर्तमान संदर्भ, प्रक्रिया के बजाय मौजूदा घटक के जीवनकाल से जुड़ा हुआ है कि से अलग है।" यह एक मेमोरी लीक कैसे बना सकता है? आवेदन संदर्भ केवल GC GC है जब प्रक्रिया से बाहर निकलता है।
एलेसियो

1
@Alessio यदि आप स्वीकार करते हैं कि आवेदन संदर्भ के लिए एक संदर्भ के रूप में एक संसाधन रिसाव योग्य नहीं है, तो आप इस के लिए एक स्थिर संदर्भ पोस्टिंग द्वारा सरल बना सकते हैं thisमें Application.onCreate()जो स्वीकार किए जाते हैं जवाब बेहतर बनाता है।
मार्क मैककेना

49

नहीं, मुझे नहीं लगता कि वहाँ है। दुर्भाग्य से, आप किसी अन्य उपवर्ग getApplicationContext()से कॉल कर रहे हैं । साथ ही, यह प्रश्न कुछ हद तक संबंधित है।ActivityContext


8
लेख का सही लिंक: android-developers.blogspot.co.il/2009/01/…
Tal Weiss

38

यहां यूआई थ्रेड में कहीं से भी एप्लिकेशन (जो एक संदर्भ है) प्राप्त करने के लिए एक अनैच्छिक तरीका है । यह छिपे हुए स्थैतिक विधि पर निर्भर करता है । यह कम से कम एंड्रॉइड 4.x पर काम करना चाहिए।ActivityThread.currentApplication()

try {
    final Class<?> activityThreadClass =
            Class.forName("android.app.ActivityThread");
    final Method method = activityThreadClass.getMethod("currentApplication");
    return (Application) method.invoke(null, (Object[]) null);
} catch (final ClassNotFoundException e) {
    // handle exception
} catch (final NoSuchMethodException e) {
    // handle exception
} catch (final IllegalArgumentException e) {
    // handle exception
} catch (final IllegalAccessException e) {
    // handle exception
} catch (final InvocationTargetException e) {
    // handle exception
}

ध्यान दें कि इस विधि के लिए नल वापस करना संभव है, उदाहरण के लिए जब आप यूआई थ्रेड के बाहर विधि कहते हैं, या एप्लिकेशन थ्रेड के लिए बाध्य नहीं है।

यदि आप एप्लिकेशन कोड को बदल सकते हैं, तो @RohitGhatol के समाधान का उपयोग करना अभी भी बेहतर है ।


1
मैंने उपरोक्त विधि केनीटीएम का उपयोग किया है, लेकिन कभी-कभी विधि शून्य हो जाती है। क्या इसका कोई और विकल्प है? जैसे अगर हमें यहाँ एक अशक्त मिलता है, हम संदर्भ को कहीं और से प्राप्त कर सकते हैं। मेरे मामले में, आवेदन के onCreate () को नहीं कहा जाता है। लेकिन उपरोक्त विधि को इसके पहले कहा जाता है। Plzzz मदद
AndroidGuy

यह हमेशा उस मामले में काम नहीं करेगा जहां जीसी ने सभी गतिविधि से संबंधित सामान को साफ किया।
एलेक्सवीपल

32

यह इस बात पर निर्भर करता है कि आप किस संदर्भ के लिए उपयोग कर रहे हैं। मैं उस तरीके से कम से कम एक नुकसान के बारे में सोच सकता हूं:

यदि आप एक AlertDialogसाथ बनाने की कोशिश कर रहे हैं AlertDialog.Builder, तो Applicationसंदर्भ काम नहीं करेगा। मेरा मानना ​​है कि आपको वर्तमान के संदर्भ की आवश्यकता है Activity...


6
ये सही है। यदि आप उसके लिए एप्लिकेशन संदर्भ का उपयोग करते हैं, तो आप अपने संवाद को अग्रभूमि गतिविधियों के तहत छिपा हुआ देख सकते हैं।
नैट

3
सबसे पहले +1। और जो संभावित त्रुटि आती है वह गतिविधि शुरू करने में असमर्थ है ComponentInfo {com.samples / com.yActivity}: android.view.WindowManager $ BadTokenException: विंडो जोड़ने में असमर्थ - टोकन एनल आवेदन के लिए नहीं है
गोविंद

15

कोटलिन रास्ता :

मैनिफ़ेस्ट:

<application android:name="MyApplication">

</application>

MyApplication.kt

class MyApplication: Application() {

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

    companion object {
        lateinit var instance: MyApplication
            private set
    }
}

इसके बाद आप संपत्ति तक पहुंच सकते हैं MyApplication.instance


11

यदि आप RoboGuice का उपयोग करने के लिए खुले हैं , तो आप किसी भी वर्ग को इच्छित संदर्भ में इंजेक्ट कर सकते हैं। यहाँ एक छोटा सा नमूना है कि इसे रोबोग्यूइस 2.0 (इस लेखन के समय बीटा 4) के साथ कैसे करें

import android.content.Context;
import android.os.Build;
import roboguice.inject.ContextSingleton;

import javax.inject.Inject;

@ContextSingleton
public class DataManager {
    @Inject
    public DataManager(Context context) {
            Properties properties = new Properties();
            properties.load(context.getResources().getAssets().open("data.properties"));
        } catch (IOException e) {
        }
    }
}

8

मैंने कुछ बिंदु पर इसका उपयोग किया है:

ActivityThread at = ActivityThread.systemMain();
Context context = at.getSystemContext();

यह एक वैध संदर्भ है जिसका मैंने सिस्टम सेवाओं में उपयोग किया है और काम किया है।

लेकिन, मैंने इसे केवल फ्रेमवर्क / बेस संशोधनों में उपयोग किया और एंड्रॉइड एप्लिकेशन में इसे आज़माया नहीं।

एक चेतावनी जिसे आपको जानना चाहिए: जब इस संदर्भ के साथ प्रसारण रिसीवर के लिए पंजीकरण करना, यह काम नहीं करेगा और आपको मिलेगा:

java.lang.SecurityException: दिया गया कॉलर पैकेज android प्रक्रिया में नहीं चल रहा है ProcessRecord


7

Kotlin

open class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        mInstance = this
    }

    companion object {
        lateinit var mInstance: MyApp
        fun getContext(): Context? {
            return mInstance.applicationContext
        }
    }
}

और जैसे संदर्भ प्राप्त करें

MyApp.mInstance

या

MyApp.getContext()

4

आप निम्नलिखित का उपयोग कर सकते हैं:

MainActivity.this.getApplicationContext();

MainActivity.java:

...
public class MainActivity ... {
    static MainActivity ma;
...
    public void onCreate(Bundle b) {
         super...
         ma=this;
         ...

कोई अन्य वर्ग:

public ...
    public ANY_METHOD... {
         Context c = MainActivity.ma.getApplicationContext();

3
यह केवल तभी काम करता है जब आप एक आंतरिक वर्ग के अंदर हों, जो ओपी में शायद ही हो।
रिचर्ड जे। रॉस III

3
यह तब तक काम करेगा जब तक AnyAMETHOD को MainActivity बनाए जाने के बाद कॉल किया जाता है, लेकिन गतिविधियों के स्थैतिक संदर्भों को ध्यान में रखते हुए लगभग अनिवार्य रूप से मेमोरी लीक का परिचय देता है (जैसा कि ओपी के अन्य जवाबों में पहले से ही उल्लेख है), इसलिए यदि आपको वास्तव में एक स्थिर संदर्भ रखना चाहिए, तो एप्लिकेशन का उपयोग करें केवल संदर्भ।
handtwerk

1
भीतर के वर्ग बुरे हैं। सबसे बुरी बात यह है कि बहुत से लोग AsyncTasks और उस तरह की चीजों के लिए करते हैं, क्योंकि कई ट्यूटोरियल इस तरह से करते हैं ...
Reinherd

4

यदि आप मैनिफ़ेस्ट फ़ाइल को संशोधित नहीं करना चाहते हैं, तो आप मैन्युअल रूप से अपनी प्रारंभिक गतिविधि में स्थिर चर में संदर्भ को संग्रहीत कर सकते हैं:

public class App {
    private static Context context;

    public static void setContext(Context cntxt) {
        context = cntxt;
    }

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

और अपनी गतिविधि (या गतिविधियाँ) शुरू होने पर संदर्भ निर्धारित करें:

// MainActivity

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Set Context
    App.setContext(getApplicationContext());

    // Other stuff
}

नोट: अन्य सभी उत्तरों की तरह, यह एक संभावित मेमोरी लीक है।


1
क्या वास्तव में यह लीक होगा क्योंकि इस मामले में संदर्भ आवेदन के लिए बाध्य है? यदि आवेदन मर जाता है, तो बाकी सब कुछ होता है।
TheRealChx101

3

मुझे लगता है कि आपको getAppContext()विधि के लिए शरीर की आवश्यकता है :

public static Context getAppContext()
   return MyApplication.context; 

3

इस स्रोत के अनुसार आप ContextWrapper का विस्तार करके अपना स्वयं का संदर्भ प्राप्त कर सकते हैं

public class SomeClass extends ContextWrapper {

    public SomeClass(Context base) {
      super(base);
    }

    public void someMethod() {
        // notice how I can use "this" for Context
        // this works because this class has it's own Context just like an Activity or Service
        startActivity(this, SomeRealActivity.class);

        //would require context too
        File cacheDir = getCacheDir();
    }
}

JavaDoc for ContextWrapper

प्रसंग के कार्यान्वयन को लागू करना जो बस इसके सभी कॉल को दूसरे संदर्भ में दर्शाता है। मूल प्रसंग को बदले बिना व्यवहार को संशोधित करने के लिए उप-वर्ग किया जा सकता है।


1
यह दिलचस्प है। ContextWrapper के बारे में जानने के लिए अच्छा है। हालांकि, अगर आपको इस निर्माणकर्ता के लिए आवेदन के संदर्भ में पास करने की आवश्यकता है, तो भी आपको इसे कहीं से प्राप्त करने की आवश्यकता है।
jk7

2

यदि आप किसी कारण से किसी भी वर्ग में आवेदन का संदर्भ चाहते हैं, न कि केवल आवेदन / गतिविधि का विस्तार करने वाले, कुछ कारखाने या सहायक वर्गों के लिए। आप अपने ऐप में निम्नलिखित सिंगलटन जोड़ सकते हैं।

public class GlobalAppContextSingleton {
    private static GlobalAppContextSingleton mInstance;
    private Context context;

    public static GlobalAppContextSingleton getInstance() {
        if (mInstance == null) mInstance = getSync();
        return mInstance;
    }

    private static synchronized GlobalAppContextSingleton getSync() {
        if (mInstance == null) mInstance = 
                new GlobalAppContextSingleton();
        return mInstance;
    }

    public void initialize(Context context) {
        this.context = context;
    }

    public Context getApplicationContext() {
        return context;
    }
}

फिर इसे अपने एप्लिकेशन क्लास के ऑनक्रिएट के साथ इनिशियलाइज़ करें

GlobalAppContextSingleton.getInstance().initialize(this);

कहीं भी कॉल करके इसका उपयोग करें

GlobalAppContextSingleton.getInstance().getApplicationContext()

मैं इस दृष्टिकोण के लिए आवेदन लेकिन संदर्भ के लिए कुछ भी सिफारिश नहीं है। चूंकि यह मेमोरी लीक का कारण बन सकता है।


यह ऐसा नहीं है कि वर्ग / विधि के नाम पत्थर में सेट हैं, इसे लंबे समय तक रखा और (उम्मीद है) एक प्रश्नोत्तर के लिए वर्णनात्मक, इसे अपने स्वयं के उपयोग के लिए छोटा कर दिया।
वर्सा

1

मैं इसके साथ मेरी मदद करने के लिए सिंगलटन डिज़ाइन पैटर्न की विविधता का उपयोग करता हूं।

import android.app.Activity;
import android.content.Context;

public class ApplicationContextSingleton {
    private static Activity gContext;

    public static void setContext( Activity activity) {
        gContext = activity;
    }

    public static Activity getActivity() {
        return gContext;
    }

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

मैं तब ApplicationContextSingleton.setContext( this );अपनी गतिविधि में कॉल करता हूं ApplicationContextSingleton.setContext( null );ऑनक्रीट () और ऑनडेस्ट्रॉय () में ;


यदि आप सभी की जरूरत है संदर्भ है, तो आप गतिविधि कॉल कर सकते हैं ।getApplicationContext (); यह लीक के बारे में चिंता किए बिना सांख्यिकीय रूप से आयोजित किया जा सकता है।
मिंसमान

2
यह मेमोरी लीक का उत्पादन करेगा
ब्लूवॉकर

1

मैंने अभी-अभी एंड्रॉइड के लिए वाष्प एपीआई नामक एक jQuery- प्रेरित ढांचा जारी किया है जिसका उद्देश्य ऐप डेवलपमेंट को सरल बनाना है।

केंद्रीय $मुखौटा वर्गWeakReference वर्तमान Activityसंदर्भ के लिए (एथन निकोलस द्वारा इसके बारे में भयानक जावा ब्लॉग पोस्ट का लिंक) रखता है जिसे आप कॉल करके प्राप्त कर सकते हैं:

$.act()

WeakReference कचरा संग्रह को मूल वस्तु को पुनः प्राप्त किए बिना रोकने के संदर्भ को बनाए रखता है, इसलिए आपको मेमोरी लीक की समस्या नहीं होनी चाहिए।

निश्चित रूप से नकारात्मक पक्ष यह है कि आप जोखिम को चलाते हैं जो $.act()अशक्त हो सकता है। मैं अभी तक इस परिदृश्य में नहीं आया हूं, इसलिए यह शायद केवल एक न्यूनतम जोखिम है, जो उल्लेख के लायक है।

यदि आप VaporActivityअपनी Activityकक्षा के रूप में उपयोग नहीं कर रहे हैं, तो आप मैन्युअल रूप से संदर्भ सेट कर सकते हैं :

$.act(Activity);

इसके अलावा, वाष्प एपीआई ढांचे का ज्यादातर हिस्सा इस संचित संदर्भ का उपयोग करता है, जिसका मतलब है कि यदि आप ढांचे का उपयोग करने का निर्णय लेते हैं, तो आपको इसे स्वयं स्टोर करने की आवश्यकता नहीं है। साइट की जाँच करें अधिक जानकारी और नमूने के लिए।

मुझे आशा है कि वह मदद करेंगे :)


1
जाहिरा तौर पर यह बस नीचे उतर गया .. एक स्पष्टीकरण अच्छा होगा !?
डेरियस

1
मैंने इसे कम नहीं किया, लेकिन जावास्क्रिप्ट का इस सवाल से कोई लेना-देना नहीं है, जो आपके द्वारा किए गए किसी भी डाउनवोट की व्याख्या करेगा! चीयर्स।
एरनानी जोपरट

यह बहुत ही निरर्थक होगा क्योंकि यह एक धाराप्रवाह इंटरफ़ेस की तरह jQuery के कुछ पहलुओं से प्रेरित है, और इसके अमूर्त .. वे अंतर्निहित भाषा के अज्ञेय सिद्धांत हैं!
डेरियस

1
तो आप इसे नीचा दिखा रहे हैं क्योंकि यह एक फ्रेमवर्क के एपीआई शब्दार्थवाद से प्रेरित था जो एक ही मंच पर नहीं है ?! मुझे लगता है कि आप लोग मंच-अज्ञेय सिद्धांतों को लागू करने की बात को याद करते हैं। ………………………………।
डेरियस

3
यह उत्तर जावास्क्रिप्ट के लिए पूरी तरह से असंबंधित है। उत्तर देने से पहले नीचे पढ़ें: /
ब्लूव्हेल

1

रोहित का जवाब सही लगता है। हालाँकि, ध्यान रखें कि AndroidStudio का "इंस्टेंट रन" static Contextआपके कोड में विशेषताओं के न होने पर निर्भर करता है , जहाँ तक मुझे पता है।


1
तुम सही हो। और यह मेमोरी लीक का परिणाम भी होगा!
user1506104

1

कोटलिन में, साथी वस्तु में प्रसंग / एप प्रसंग डालना अभी भी चेतावनी का उत्पादन करता है Do not place Android context classes in static fields; this is a memory leak (and also breaks Instant Run)

या यदि आप कुछ इस तरह का उपयोग करते हैं:

    companion object {
        lateinit var instance: MyApp
    }

यह केवल स्मृति रिसाव की खोज न करने के लिए एक प्रकार का वृक्ष को बेवकूफ बना रहा है, ऐप इंस्टाग्राम अभी भी मेमोरी लीक का उत्पादन कर सकता है, क्योंकि एप्लिकेशन क्लास और इसका वंश एक संदर्भ है।

वैकल्पिक रूप से, आप अपने ऐप के संदर्भ को प्राप्त करने में मदद करने के लिए कार्यात्मक इंटरफ़ेस या कार्यात्मक गुणों का उपयोग कर सकते हैं।

बस एक वस्तु वर्ग बनाएँ:

object CoreHelper {
    lateinit var contextGetter: () -> Context
}

या आप अशक्त प्रकार का उपयोग करके इसे अधिक सुरक्षित रूप से उपयोग कर सकते हैं:

object CoreHelper {
    var contextGetter: (() -> Context)? = null
}

और अपने ऐप क्लास में इस लाइन को जोड़ें:


class MyApp: Application() {

    override fun onCreate() {
        super.onCreate()
        CoreHelper.contextGetter = {
            this
        }
    }
}

और अपने घोषणा पत्र में एप्लिकेशन का नाम घोषित करें . MyApp


    <application
            android:name=".MyApp"

जब आप संदर्भ प्राप्त करना चाहते हैं तो बस कॉल करें:

CoreHelper.contextGetter()

// or if you use the nullable version
CoreHelper.contextGetter?.invoke()

आशा है कि यह मदद करेगा।


इस कोरहैपर की ऑब्जेक्ट क्लास को इनिशियलाइज़ किया जाएगा और इसे बाद की स्टेज पर आउट गतिविधियों के ज़रिए इस्तेमाल किया जा सकता है? क्षमा करें, मैं कोटलिन के लिए नया हूं
डॉ। एएनआरडीओ

हाँ बिल्कुल।
हैई नुक्मैन

-1

कुछ इस तरह की कोशिश करो

import androidx.appcompat.app.AppCompatActivity;  
import android.content.Context; 
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {
    private static Context context;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        context = getApplicationContext();
    }

    public static void getContext(View view){
        Toast.makeText(context, "Got my context!",
                    Toast.LENGTH_LONG).show();    
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.