在編寫(xiě)某些自定義類時(shí),無(wú)法方便的取得Context(Activity或Application),例如需要獲取res資源,取些drawable或string之類的,通常會(huì)比較麻煩。
解決方法一般有:
1、傳入Context(例如Toast)
2、繼承Application使用單例(此法在編寫(xiě)應(yīng)用無(wú)關(guān)的工具類時(shí)無(wú)法很好的解決問(wèn)題)
一般來(lái)說(shuō),能使用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.)
但在獲取資源文件時(shí)通常并無(wú)大礙,因此筆者特別為能夠在任意位置獲取應(yīng)用Context做了一番研究。
在上述方法2中雖有缺陷,但經(jīng)過(guò)一番改造仍不失為一個(gè)不錯(cuò)的解決方法。
首先我們構(gòu)造一個(gè)存儲(chǔ)Context的類ContextHolder,在Application初始化時(shí)將Application傳入ContextHolder,這個(gè)方法在很多第三方庫(kù)都能見(jiàn)到類似的處理。
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()來(lái)獲取應(yīng)用Context。
那么有沒(méi)有可能不需要任何初始化操作就能完成這個(gè)需求呢?筆者做了一些嘗試。
由于實(shí)際上獲取應(yīng)用Context也就是獲取當(dāng)前應(yīng)用實(shí)例,經(jīng)筆者研究下面2種方法都可以通過(guò)反射直接獲取當(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)測(cè)試,即使應(yīng)用處于后臺(tái)仍能正確獲取到調(diào)用此方法的Application。
筆者以此開(kāi)發(fā)的工具:
AndroidContextHolder