在編寫某些自定義類時疹尾,無法方便的取得Context(Activity或Application),例如需要獲取res資源椎例,取些drawable或string之類的链蕊,通常會比較麻煩。
解決方法一般有:
1馒疹、傳入Context(例如Toast)
2佳簸、繼承Application使用單例(此法在編寫應(yīng)用無關(guān)的工具類時無法很好的解決問題)
一般來說,能使用Activity盡量不用Application作為Context颖变,官方文檔(This generally should only be used if you need a Context whose lifecycle is separate from the current context, that is tied to the lifetime of the process rather than the current component.)
但在獲取資源文件時通常并無大礙生均,因此筆者特別為能夠在任意位置獲取應(yīng)用Context做了一番研究。
在上述方法2中雖有缺陷腥刹,但經(jīng)過一番改造仍不失為一個不錯的解決方法马胧。
首先我們構(gòu)造一個存儲Context的類ContextHolder,在Application初始化時將Application傳入ContextHolder衔峰,這個方法在很多第三方庫都能見到類似的處理佩脊。
public class ContextHolder {
static Context ApplicationContext;
public static void initial(Context context) {
ApplicationContext = context;
}
public static Context getContext() {
return ApplicationContext;
}
}
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
ContextHolder.initial(this);
}
}
這樣我們就能在任意位置調(diào)用ContextHolder.getContext()來獲取應(yīng)用Context。
那么有沒有可能不需要任何初始化操作就能完成這個需求呢垫卤?筆者做了一些嘗試威彰。
由于實際上獲取應(yīng)用Context也就是獲取當(dāng)前應(yīng)用實例,經(jīng)筆者研究下面2種方法都可以通過反射直接獲取當(dāng)前應(yīng)用穴肘。
try {
Application application = (Application) Class.forName("android.app.ActivityThread").getMethod("currentApplication").invoke(null, (Object[]) null);
}
catch (Exception e) {
e.printStackTrace();
}
try {
Application application = (Application) Class.forName("android.app.AppGlobals").getMethod("getInitialApplication").invoke(null, (Object[]) null);
}
catch (Exception e) {
e.printStackTrace();
}
經(jīng)測試歇盼,即使應(yīng)用處于后臺仍能正確獲取到調(diào)用此方法的Application。
筆者以此開發(fā)的工具:
AndroidContextHolder