本章要点
掌握高级技巧
13.1 获取全局Context的技巧
Context用到的地方很多:弹出Toast,启动活动,发送广播,操作数据库,使用通知,等等等等。
活动本身就是一个Context对象。当应用程序的架构逐渐复杂,逻辑代码脱离Activity类,需要获取Context对象。比如,在第9章编写的HttpUtil类(封装了通用的网络操作),代码如下:
public class HttpUtil {
public static void sendHttpRequest(final String address, final HttpCallbackListener listener) {
new Thread(new Runnable() {
@Override
public void run() {
HttpURLConnection connection = null;
try {
URL url = new URL(address);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(8000);
connection.setReadTimeout(8000);
connection.setDoInput(true);
connection.setDoOutput(true);
InputStream in = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
if (listener != null) {
listener.onFinish(response.toString());
}
} catch (Exception e) {
e.printStackTrace();
if (listener != null) {
listener.onError(e);
}
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
}).start();
}
}
为了解决在HttpUtil类中获取Context对象,我们在sendHttpRequest()方法中添加Context参数,修改HttpUtil类中的代码如下:
public class HttpUtil {
public static void sendHttpRequest(Context context, final String address, final HttpCallbackListener listener) {
if (!isNetworkAvailable()) {
Toast.makeText(context, "network is unavailable", Toast.LENGTH_SHORT).show();
return;
}
new Thread(new Runnable() {
@Override
public void run() {
...
}).start();
}
//用于判断当前网络状态是否可用
private static boolean isNetworkAvailable() {
...
}
}
在项目的任何地方都有能够轻松获取到Context,Android提供了一个Application类,每当启动应用程序,系统会自动初始化这个类。因而定制自己的Application类,便于管理内部的全局状态信息,如Context。
创建一个MyApplication类继承自Application,代码如下:
public class MyApplication extends Application {
private static Context context;
@Override
public void onCreate() {
super.onCreate();
context = getApplicationContext();
}
public static Context getContext() {
return context;
}
}
接下来我们在AndroidManifest.xml中application指定(注意,完整的包名加类名),代码如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.hjw.networktest">
...
<application
android:name="com.example.hjw.networktest.MyApplication"
...
>
...
</application>
</manifest>
这样就实现了全局获取Context机制,使用MyApplication.getContext()就Ok,如下:
public static void sendHttpRequest( final String address, final HttpCallbackListener listener) {
if (!isNetworkAvailable()) {
Toast.makeText(MyApplication.getContext(), "network is unavailable", Toast.LENGTH_SHORT).show();
return;
}
...
}
在第6章中,为了让LitePal正常工作(内部自动获取Context),必须在AndroidManifest.xml中配置如下:
<application
android:name="org.litepal.LitePalApplication"
...>
...
</application>
任何一个项目中只能配置一个Application,为了解决MyApplication和LitePalApplication发生冲突,我们可以在MyApplication中调用LitePal初始化方法(效果和直接在AndroidManifest.xml配置的效果一样),如下:
public class MyApplication extends