When singleton Application object is sometimes null
I currently have a class Application
that I expect to see throughout the entire lifecycle of the application.
MyApplication.java
public class MyApplication extends android.support.multidex.MultiDexApplication {
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
public static MyApplication instance() {
return me;
}
@SuppressLint("NewApi")
@Override
public void onCreate(){
super.onCreate();
me = this;
registerNetworkCallback(MyApplication.instance());
However, in a very rare situation, it MyApplication.instance()
returns zero at the link change broadcast receiver.
ConnectivityChangeBroadcastReceiver.java
public class ConnectivityChangeBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// MyApplication.instance() is returning null?!?!
}
How to register a network callback
public static void registerNetworkCallback(final Context context) {
/*
Apps targeting Android 7.0 (API level 24) do not receive CONNECTIVITY_ACTION broadcasts if
they register to receive them in their manifest. Apps that are running can still listen for
CONNECTIVITY_CHANGE on their main thread by registering a BroadcastReceiver with
Context.registerReceiver().
*/
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
return;
}
try {
if (!connectivityChangeBroadcastReceiverDisabled) {
// Although ConnectivityChangeBroadcastReceiver will not be triggered, just to be extra
// caution...
PackageManager pm = context.getPackageManager();
ComponentName compName = new ComponentName(context, ConnectivityChangeBroadcastReceiver.class);
pm.setComponentEnabledSetting(
compName,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
connectivityChangeBroadcastReceiverDisabled = true;
}
if (networkCallback == null) {
networkCallback = new ConnectivityManager.NetworkCallback() {
/**
* @param network
*/
@Override
public void onAvailable(Network network) {
Handler handler = new Handler(Looper.getMainLooper());
Runnable runnable = new Runnable() {
@Override
public void run() {
ConnectivityChangeBroadcastReceiver.onReceive(context);
}
};
handler.post(runnable);
}
};
}
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkRequest.Builder builder = new NetworkRequest.Builder();
NetworkRequest networkRequest = builder.build();
connectivityManager.registerNetworkCallback(networkRequest, networkCallback);
} catch (Exception e) {
Log.e(TAG, "", e);
}
}
Do you have an idea why there is a rare possibility, when ConnectivityChangeBroadcastReceiver
run in onReceive
, singleton MyApplication.instance()
returns null?
+3
source to share
1 answer
I understand the high probability that I am leaking the application context, making the OS have no chance of garbage collection
Malfunctioning application context!
registerNetworkCallback(MyApplication.instance());
public static void registerNetworkCallback(final Context context) {
...
networkCallback = new ConnectivityManager.NetworkCallback() {
/**
* @param network
*/
@Override
public void onAvailable(Network network) {
Handler handler = new Handler(Looper.getMainLooper());
Runnable runnable = new Runnable() {
@Override
public void run() {
ConnectivityChangeBroadcastReceiver.onReceive(context);
No application context leak!
registerNetworkCallback(MyApplication.instance());
// No more final on context, to avoid it is being used in anonymous class.
public static void registerNetworkCallback(Context context) {
...
networkCallback = new ConnectivityManager.NetworkCallback() {
/**
* @param network
*/
@Override
public void onAvailable(Network network) {
Handler handler = new Handler(Looper.getMainLooper());
Runnable runnable = new Runnable() {
@Override
public void run() {
ConnectivityChangeBroadcastReceiver.onReceive(MyApplication.instance());
0
source to share