ඇන්ඩ්‍රොයිඩ් හි 'සන්දර්භය' ලබා ගැනීමට ස්ථිතික ක්‍රමය?


982

Contextස්ථිතික ක්‍රමයක් තුළ වත්මන් අවස්ථාව ලබා ගැනීමට ක්‍රමයක් තිබේද?

මම ඒ ආකාරයෙන් සොයන්නේ එය වෙනස් වන සෑම අවස්ථාවකම 'සන්දර්භය' උදාහරණය සුරැකීමට අකමැති බැවිනි.


57
සන්දර්භය සුරැකීම හොඳ අදහසක් වන්නේ එය අපහසු නිසා පමණක් නොව, එය විශාල මතක කාන්දුවීම් වලට තුඩු දිය හැකි බැවිනි!
වික්‍රම් බොඩිචර්ලා

12
Ik වික්‍රම් බොඩිචර්ලා ඔව්, නමුත් පහත පිළිතුරු උපකල්පනය කරන්නේ අපි යෙදුම් සන්දර්භය ගැන කතා කරන බවයි. එබැවින්, මතක කාන්දු වීම ගැටළුවක් නොවේ, නමුත් පරිශීලකයා මෙම විසඳුම් භාවිතා කළ යුත්තේ එය භාවිතා කිරීමට නිවැරදි සන්දර්භය ඇති තැන පමණි.
ටොම්

ඔබට ස්ථිතික ක්‍රමයක් ලබා ගැනීමට අවශ්‍ය නම් Context, කේතය සැලසුම් කිරීමට වඩා හොඳ ක්‍රමයක් තිබිය හැකිය.
ඇනොන්සේජ්

3
ඇන්ඩ්‍රොයිඩ් ප්‍රලේඛනය නිර්දේශ කරන්නේ සන්දර්භය සිංගල්ටන් ලබා ගන්නන්ට ලබා දීමයි. developer.android.com/reference/android/app/Application.html
මාර්කෝ Luglio

ස්ථිතික සන්දර්භය හරහා getInstance () සමඟ සම්මත කර ඇති තනි බොත්තම් සහ සන්දර්භය සඳහා කැමති නම්, කරුණාකර බලන්න, වැඩකරන කේතය සමඟ සහය දක්වන මගේ තර්කය මෙහි පැහැදිලි කිරීමට උත්සාහ කළෙමි: stackoverflow.com/a/38967293/4469112
Alessio

Answers:


1317

මෙය කරන්න:

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()ඔබේ යෙදුම් සන්දර්භය සංඛ්‍යාත්මකව ලබා ගැනීමට අමතන්න .


83
මෙම ක්‍රමයට අවාසියක් තිබේද? මෙය වංචාවක් සේ පෙනේ. (
කඩුල්ලක් ද

208
අවාසිය නම් සමහර ස්ථිතික ආරම්භක කේතයන් ඔබේ සන්දර්භය වස්තුව ලබා ගැනීමට උත්සාහ කිරීමට පෙර ස්ථිතික නොවන onCreate () කැඳවනු ඇති බවට කිසිදු සහතිකයක් නොමැති වීමයි. ඒ කියන්නේ ඔබේ ඇමතුම් කේතය මෙම ප්‍රශ්නයේ සමස්ත කරුණම පරාජය කරන ආකාරයේ ශුන්‍ය අගයන් සමඟ කටයුතු කිරීමට සූදානම් විය යුතුය.
මෙලින්ඩා ග්‍රීන්

8
සමහර විට .. අපි මෙම static contextවිචල්‍යය ලෙස ප්‍රකාශ කළ volatileයුතුද?
ව්ලැඩිමීර් සොරොකින්

15
Om ටොම් මෙය ස්ථිතික දත්ත සාමාජිකයෙකු මුලින් ස්ථිතිකව සිටීම නොවේ. දී ඇති කේතයේ, ස්ථිතික සාමාජිකයා onCreate () හි ස්ථිතික නොවන ලෙස ආරම්භ කරනු ලැබේ. මෙම අවස්ථාවෙහිදී සංඛ්‍යානමය වශයෙන් ආරම්භක දත්ත පවා ප්‍රමාණවත් නොවේ. මන්දයත් දී ඇති පන්තියේ ස්ථිතික ආරම්භය වෙනත් පන්තියක ස්ථිතික ආරම්භයේදී ප්‍රවේශ වීමට පෙර සිදුවනු ඇති බවට කිසිවක් සහතික නොවන බැවිනි.
මෙලින්ඩා ග්‍රීන්

11
ElMelindaGreen යෙදුම සඳහා වන ලියකියවිලි වලට අනුව, කිසියම් ක්‍රියාකාරකමක්, සේවාවක් හෝ ග්‍රාහකයක් (අන්තර්ගත සපයන්නන් හැර) නිර්මාණය කිරීමට පෙර onCreate () කැඳවනු ලැබේ. ඔබ අන්තර්ගත සැපයුම්කරුවෙකුගෙන් getAppContext () වෙත පිවිසීමට උත්සාහ නොකරන තාක් කල් මෙම විසඳුම ආරක්ෂිත නොවේද?
මැග්නස් ඩබ්ලිව්

91

යෙදුම් සන්දර්භය ලබා ගැනීම සඳහා පහසු ක්‍රමයක් අවශ්‍ය යෙදුම් වලින් බහුතරයක් තමන්ගේම පන්තියක් නිර්මාණය කරයි 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 () භාවිතා කරන සන්දර්භයක් ලබා දිය හැකිය.


පරාවර්තනය

පරාවර්තනය භාවිතා කරමින් යෙදුම් සන්දර්භය ලබා ගැනීමට තවත් ක්‍රමයක් තිබේ. ඇන්ඩ්‍රොයිඩ් වල පරාවර්තනය බොහෝ විට පහත් කොට සලකනු ලබන අතර මම පෞද්ගලිකව සිතන්නේ මෙය නිෂ්පාදනයේදී භාවිතා නොකළ යුතු බවයි.

යෙදුම් සන්දර්භය ලබා ගැනීම සඳහා අපි API 1 සිට ලබා ගත හැකි සැඟවුණු පන්තියකට ( ActivityThread ) ක්‍රමයක් ඉල්ලා සිටිය යුතුය :

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

සුබ කේතීකරණයක්!


59

අපි යෙදුම් සන්දර්භය ලබා ගැනීම ගැන කතා කරනවා යැයි උපකල්පනය කරමින්, @ රෝහිත් ගැටෝල් විසින් යෙදුම දීර් ing කිරීම යෝජනා කළ පරිදි මම එය ක්‍රියාත්මක කළෙමි. එවකට සිදුවූ දෙය නම්, එවැනි ආකාරයකින් ලබාගත් සන්දර්භය සැමවිටම ශුන්‍ය නොවන බවට සහතිකයක් නොමැති වීමයි. ඔබට එය අවශ්‍ය වේලාවේදී, සාමාන්‍යයෙන් ඔබට උදව්කරුවෙකු ආරම්භ කිරීමට හෝ සම්පතක් ලබා ගැනීමට අවශ්‍ය නිසා ඔබට කාලය ප්‍රමාද කළ නොහැක. ශුන්‍ය නඩුව හැසිරවීම ඔබට උදව් නොකරනු ඇත. මම සඳහන් පරිදි මම මූලික වශයෙන්, ඇන්ඩ්රොයිඩ් ගෘහ නිර්මාණ ශිල්පය එරෙහිව සටන් කරන තේරුම් එසේ ලේඛන

සටහන: සාමාන්‍යයෙන් උප කාණ්ඩය යෙදීම අවශ්‍ය නොවේ. බොහෝ අවස්ථාවන්හීදී, ස්ථිතික සිංගල්ටන් වලට එකම ක්‍රියාකාරීත්වය වඩාත් මොඩියුලර් ආකාරයකින් සැපයිය හැකිය. ඔබේ සිංගල්ටන්ට ගෝලීය සන්දර්භයක් අවශ්‍ය නම් (නිදසුනක් ලෙස විකාශන ග්‍රාහක ලියාපදිංචි කිරීම සඳහා), ඔබේ සිංගල්ටන් ගේ getInstance () ක්‍රමයට ආයාචනා කිරීමේදී සන්දර්භය තර්කයක් ලෙස Context.getApplicationContext () ඇතුළත් කරන්න.

සහ ඩයැන් හැක්බර්න් විසින් පැහැදිලි කරන ලදී

යෙදුම ඔබට ලබා ගත හැකි දෙයක් ලෙස පැවතීමට ඇති එකම හේතුව නම්, 1.0 ට පෙර සංවර්ධනය අතරතුර අපගේ යෙදුම් සංවර්ධකයෙකු දිගින් දිගටම මට දෝෂාරෝපණය කරමින් සිටි නිසා ඔවුන්ට ව්‍යුත්පන්න කළ හැකි ඉහළ මට්ටමේ යෙදුම් වස්තුවක් තිබිය යුතු නිසා ඔවුන්ට වඩාත් “සාමාන්‍ය” විය හැකිය. "ඔවුන්ට අයදුම්පත් ආකෘතිය, මම අවසානයේදී එය ලබා දුන්නා. මම එය ලබා දීම ගැන සදාකාලිකවම කනගාටු වෙමි. :)

ඇය මෙම ගැටලුවට විසඳුම ද යෝජනා කරයි:

ඔබට අවශ්‍ය දේ ඔබගේ යෙදුමේ විවිධ කොටස් හරහා බෙදා ගත හැකි ගෝලීය තත්වයක් නම්, තනි තට්ටුවක් භාවිතා කරන්න. [...] තවද මෙය ස්වාභාවිකවම ඔබ මේවා කළමනාකරණය කළ යුතු ආකාරය වෙත යොමු කරයි - ඉල්ලුමට අනුව ඒවා ආරම්භ කිරීම.

ඒ නිසා මම කළේ යෙදුම දීර් ing කිරීමෙන් ඉවත් වීම සහ පුද්ගලික ඉදිකිරීම්කරු තුළ යෙදුම් සන්දර්භය පිළිබඳ සඳහනක් සුරකින අතරම සන්දර්භය කෙලින්ම තනි සහායකයාගේ getInstance () වෙත යොමු කිරීමයි:

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
Less ඇලෙසියෝ මෙම ක්‍රමය මතක කාන්දු වීමට තුඩු දෙන්නේ නැද්ද
පිලිප් කිගෙනි

2
odcodephillip ඔබ කතා කරන්නේ කුමක් දැයි මට තේරෙන්නේ නැත. සිංගල්ටන් මඟින් යොමු කරනුයේ යෙදුම් සන්දර්භය සම්මත කරන ලද ක්‍රියාකාරකමෙන් මිස ධාරක ක්‍රියාකාරකමෙන් නොවේ. එය නීත්‍යානුකූල වන අතර එය කිසිදු මතක කාන්දුවක් ඇති නොකරනු ඇත. මා ලියූ බ්ලොග් අඩවියේ ප්‍රධාන කරුණ එයයි . ඔබ හරි යැයි ඔබ සිතන්නේ නම්, කරුණාකර මට කතා කරන මතක කාන්දුව ප්‍රතිනිෂ්පාදනය කළ හැකි නියැදි කේතයක් මට එවන්න, මන්ද එය එසේ නොවේ.
ඇලෙසියෝ

1
මම හිතන්නේ @ කිගෙනි ෆිලිප් නිවැරදියි, මෙය තවමත් සම්පත් කාන්දුවක් නියෝජනය කරයි. ඔබගේ පළමු ඇමතුමෙන් පසුව යොමු සටහනක් සිතන්න getInstance(ctx). ඔබ සතුව GC instanceවර්ගයේ වර්ගයක් ඇත MyHelper, එය පෞද්ගලික mContextවර්ගයේ ක්ෂේත්‍රයක් ඇත Context, එමඟින් සම්මත කරන ලද සන්දර්භය හරහා එකතු කරන ලද යෙදුම් සන්දර්භය සඳහන් කරයි getInstance(). instanceකිසි විටෙකත් දෙවන වරටත් සකසා නැත, හෝ නිෂ්කාශනය නොකෙරේ, එබැවින් GC විසින් සඳහන් කර ඇති උපසිරැසිය කිසි විටෙකත් අල්ලා නොගනී instance. ඔබ කිසිදු ක්‍රියාකාරකමක් කාන්දු නොකරන බැවින් එය අඩු වියදම් IMO වේ.
මාර්ක් මැකේනා

1
ArkMarkMcKenna ඔබ පවසන පරිදි "පුද්ගලික සන්දර්භය mContext වර්ගයේ සන්දර්භය ඇත, එය යෙදුම් සන්දර්භය සඳහන් කරයි", එබැවින් ඔබට පැහැදිලි වන්නේ mContext යනු යෙදුම් සන්දර්භය වෙත යොමු කිරීමක් මිස කිසිදු සන්දර්භයකට නොවන බවයි. දී getApplicationContext () ලේඛන ඔබ කියවන: "කාගේ ජීව වත්මන් අංගයක් වෙනුවට ක්රියාවලිය ජීවිත කාලය බැඳ ඇති බව වත්මන් සන්දර්භය වෙන් වේ, සංදර්භය". මෙය මතක කාන්දුවක් ඇති කරන්නේ කෙසේද? යෙදුම් සන්දර්භය GC'd වන්නේ ක්‍රියාවලිය පිටවන විට පමණි.
ඇලෙසියෝ

1
@Alessio ඔබ ඉල්ලුම් සන්දර්භය සැඳහුම සම්පතක් කාන්දුවක් ලෙස සුදුසුකම් නොවන බව පිළිගැනීමට නම් ඔබ ස්ථිතික යොමු කරමිනි මෙම සරල හැකි thisතුළ Application.onCreate()වඩා හොඳ පිළිගත් පිළිතුර වන පරිදි,.
මාර්ක් මැකේනා

49

නැහැ, මම හිතන්නේ නැහැ. අවාසනාවට, ඔබ ඇමතුමක් හෝ වෙනත් උප පංතියකින් ඇමතුමක් getApplicationContext()ලබාගෙන Activityඇත Context. එසේම, මෙම ප්රශ්නය තරමක් සම්බන්ධ වේ.


8
ලිපියට නිවැරදි සබැඳිය: android-developers.blogspot.co.il/2009/01/…
තල් වයිස්

39

මෙන්න වේ රහිත ආදායමක් ලබා ගැනීමට මග අයදුම් මෙම UI නූල් ඕනෑම තැනක සිට (අ සංදර්භය වන). එය සැඟවුණු ස්ථිතික ක්‍රමය මත රඳා පවතී ActivityThread.currentApplication(). එය අවම වශයෙන් Android 4.x හි වැඩ කළ යුතුය.

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
}

මෙම ක්‍රමය අහෝසි විය හැකි බව සලකන්න, උදා: ඔබ UI නූල් වලින් පිටත ක්‍රමය අමතන විට හෝ යෙදුම නූල් වලට බැඳී නොමැත.

ඔබට යෙදුම් කේතය වෙනස් කළ හැකි නම් @RohitGhatol ගේ විසඳුම භාවිතා කිරීම වඩා හොඳය .


1
මම ඉහත ක්‍රමය KennyTM භාවිතා කළෙමි, නමුත් සමහර විට ක්‍රමය අහෝසි වේ. මේ සඳහා වෙනත් විකල්පයක් තිබේද? හරියට අපට මෙහි ශුන්‍යතාවයක් ලැබුණොත්, අපට වෙනත් තැනකින් සන්දර්භය ලබා ගත හැකිය. මගේ නඩුවේදී, යෙදුමේ onCreate () කැඳවනු නොලැබේ. නමුත් ඉහත ක්‍රමය ඊට පෙර කැඳවනු ලැබේ. Plzzz help
AndroidGuy

ක්‍රියාකාරකම් හා සම්බන්ධ සියලු දේ GC පිරිසිදු කළ අවස්ථාවක මෙය සැමවිටම ක්‍රියාත්මක නොවේ.
ඇලෙක්ස්වීපර්ල්

32

එය ඔබ සන්දර්භය භාවිතා කරන්නේ කුමක් ද යන්න මත රඳා පවතී. එම ක්‍රමයට අවම වශයෙන් එක් අවාසියක් ගැන මට සිතිය හැකිය:

ඔබ AlertDialogසමඟ නිර්මාණය කිරීමට උත්සාහ කරන්නේ නම් AlertDialog.Builder, Applicationසන්දර්භය ක්‍රියා නොකරනු ඇත. ධාරාව සඳහා සන්දර්භය ඔබට අවශ්‍ය යැයි මම විශ්වාස කරමි Activity...


6
ඒක හරි. ඔබ ඒ සඳහා යෙදුම් සන්දර්භය භාවිතා කරන්නේ නම්, ඔබේ සංවාදය පෙරබිම් ක්‍රියාකාරකම් යටතේ සඟවා ඇති බව ඔබට පෙනෙනු ඇත.
නේට්

3
+1 පළමුව. සිදුවිය හැකි දෝෂය නම් ක්‍රියාකාරකම් ආරම්භ කිරීමට නොහැකි වීමයි ComponentInfo {com.samples / com.MyActivity and: android.view.WindowManager $ BadTokenException: කවුළුව එක් කිරීමට නොහැකි වීම - ටෝකන් ශුන්‍ය යෙදුමක් සඳහා නොවේ
Govind

18

කොට්ලින් මාර්ගය :

ප්‍රකාශනය:

<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 භාවිතා කිරීමට විවෘත නම් , ඔබට අවශ්‍ය ඕනෑම පන්තියකට සන්දර්භය එන්නත් කළ හැකිය. 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: ලබා දී ඇති ඇමතුම් පැකේජය ඇන්ඩ්‍රොයිඩ් ක්‍රියාවලියෙහි ක්‍රියාත්මක නොවේ ProcessRecord


7

කොට්ලින්

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

5

මැනිෆෙස්ට් ගොනුව වෙනස් කිරීමට ඔබට අවශ්‍ය නැතිනම්, ඔබේ ආරම්භක ක්‍රියාකාරකම් වලදී ඔබට සන්දර්භය ස්ථිතික විචල්‍යයක ගබඩා කළ හැකිය:

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
}

සටහන: අනෙක් සියලුම පිළිතුරු මෙන් මෙයද විභව මතක කාන්දුවකි.


2
මෙම නඩුවේ සන්දර්භය යෙදුමට බැඳී ඇති බැවින් එය හරියටම කාන්දු වන්නේ කුමක් ද? යෙදුම මිය ගියහොත් අනෙක් සියල්ලම එසේ වේ.
TheRealChx101

ස්ථිතික සන්දර්භය යොමු කිරීම් මත මෙම කාන්දුව වැළැක්වීමට කෙසේ හෝ තිබේද?
ඩේවිඩ් කාරුකි

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
ප්‍රධාන ක්‍රියාකාරිත්වය නිර්මාණය කිරීමෙන් පසුව ANY_METHOD ලෙස හැඳින්වෙන තාක් කල් මෙය ක්‍රියාත්මක වනු ඇත, නමුත් ක්‍රියාකාරකම් පිළිබඳ ස්ථිතික යොමු කිරීම් අනිවාර්යයෙන්ම පාහේ මතක කාන්දු වීමක් හඳුන්වා දෙයි (OP හි ප්‍රශ්නයට වෙනත් ප්‍රතිචාර දැනටමත් සඳහන් කර ඇති පරිදි), එබැවින් ඔබ ස්ථිතික යොමු කිරීමක් කළ යුතු නම්, යෙදුම භාවිතා කරන්න සන්දර්භය පමණි.
හෑන්ඩ් වර්ක්

1
අභ්‍යන්තර පන්ති නපුරු ය. නරකම දෙය නම් බොහෝ අය අසින්ක් ටාස්ක් සහ ඒ වගේ දේවල් සඳහා එසේ කිරීමයි, මන්ද බොහෝ නිබන්ධන එය එසේ කරන බැවිනි ...
රයින්හර්ඩ්

4

මෙම ප්‍රභවයට අනුව 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();
    }
}

ContextWrapper සඳහා JavaDoc

සන්දර්භය ක්‍රියාවට නැංවීම, එහි සියලු ඇමතුම් වෙනත් සන්දර්භයකට යොමු කරයි. මුල් සන්දර්භය වෙනස් නොකර හැසිරීම වෙනස් කිරීම සඳහා උපවර්ගය කළ හැකිය.


1
මෙය සිත්ගන්නා සුළුය. ContextWrapper ගැන ඉගෙන ගැනීමට හොඳයි. කෙසේ වෙතත්, ඔබට යෙදුම් සන්දර්භය තුළ මෙම ඉදිකිරීම්කරු වෙත යැවීමට අවශ්‍ය නම්, ඔබට එය කොතැනක හෝ ලබා ගත යුතුය.
jk7

3

මම හිතන්නේ ඔබට getAppContext()ක්‍රමයට ශරීරයක් අවශ්‍යයි :

public static Context getAppContext()
   return MyApplication.context; 

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

ඉන්පසු එය ඔබගේ යෙදුම් පන්තියේ onCreate with සමඟ ආරම්භ කරන්න

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 );තුළ onDestroy () ;


ඔබට අවශ්‍ය වන්නේ සන්දර්භය නම් ඔබට activity.getApplicationContext () අමතන්න; කාන්දුවීම් ගැන කරදර නොවී එය සංඛ්‍යානමය වශයෙන් රඳවා ගත හැකිය.
මින්ස්මන්

2
මෙය මතක කාන්දුවීම් ඇති කරයි
බ්ලූවිසාඩ්

1

මම දැන් වාෂ්ප ඒපීඅයි නමින් ඇන්ඩ්‍රොයිඩ් සඳහා jQuery ආනුභාව ලත් රාමුවක් නිකුත් කළෙමියෙදුම් සංවර්ධනය සරල කිරීම අරමුණු කරගත් මම .

මධ්‍යම $ෆැසෙඩ් පංතිය ඇමතීමෙන් ඔබට ලබා ගත හැකි WeakReferenceවර්තමාන Activityසන්දර්භය වෙත (ඊතන් නිකලස් විසින් රචිත ජාවා බ්ලොග් සටහනට සබැඳියක්) පවත්වා ගෙන යයි :

$.act()

WeakReference ඔබ මතක කාන්දු සමග ගැටළුවක් තිබිය යුතු නොවේ, ඒ සඳහා මුල් වස්තුව ගොඩ කුණු එකතු වැළැක්වීම තොරව යොමු පවත්වාගෙන යයි.

ඇත්ත වශයෙන්ම අවාසිය නම් ඔබ එම අවදානම ක්‍රියාත්මක කිරීමයි $.act() අවලංගු කළ හැකි . මම තවමත් මෙම තත්වය දැක නැත, එබැවින් එය අවම අවදානමක් පමණක් බව සඳහන් කිරීම වටී.

ඔබ VaporActivityඔබේ Activityපන්තිය ලෙස භාවිතා නොකරන්නේ නම් ඔබට සන්දර්භය අතින් සැකසිය හැකිය :

$.act(Activity);

එසේම, බොහෝ වාෂ්ප API රාමුව මෙම ගබඩා කළ සන්දර්භය සහජයෙන්ම භාවිතා කරයි, එයින් අදහස් කරන්නේ ඔබ රාමුව භාවිතා කිරීමට තීරණය කරන්නේ නම් එය ඔබම ගබඩා කර නොගත යුතු බවයි. වෙබ් අඩවිය පරීක්ෂා කරන්නවැඩි විස්තර සහ සාම්පල සඳහා .

එය උපකාරී වේ යැයි මම බලාපොරොත්තු වෙමි :)


1
පෙනෙන විදිහට මෙය පහත් කොට ඇත .. පැහැදිලි කිරීමක් හොඳයි!?
ඩාරියස්

1
මම මෙය අවතක්සේරු නොකළ නමුත් ජාවාස්ක්‍රිප්ට් අතෙහි ඇති ප්‍රශ්නයට කිසිදු සම්බන්ධයක් නැත, එමඟින් ඔබට ඇති විය හැකි අඩුපාඩු පැහැදිලි වනු ඇත! චියර්ස්.
අර්නානි ජොපර්ට්

චතුර කථික අතුරු මුහුණතක් වැනි jQuery හි සමහර අංගයන්ගෙන් සහ එහි වියුක්තතාවන්ගෙන් එය ආනුභාව ලත් බැවින් එය විකාරයකි . ඒවා යටින් පවතින භාෂාවේ අ nost ෙයවාදී මූලධර්ම වේ!
ඩාරියස්

1
එකම වේදිකාවක නොමැති රාමුවක API අර්ථ නිරූපණයන්ගෙන් එය ආනුභාව ලත් නිසා ඔබ එය පහත් කොට සලකන්නේද? වේදිකා-අ nost ෙයවාදී මූලධර්ම අනුගමනය කිරීමේ කාරණය ඔබට මග හැරී ඇතැයි මම සිතමි .....................................
ඩාරියස්

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

එය උපකාරී වේ යැයි සිතමි.


මෙම corehelper හි වස්තු පන්තිය ආරම්භ කෙරෙන අතර පසුකාලීන ක්‍රියාකාරකම් වලදී භාවිතා කළ හැකිද? කණගාටුයි, මම කොට්ලින්ට අලුත් ය
වෛද්‍ය aNdRO
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.