don't notify network change listeners unless a change is in fact a change and until there's been two seconds without changes. There's a lot of connection up-and-down spam when connecting and maybe with iffy connectivity, and no point in passing that through to code that will do stuff like stopping a send thread in response.

This commit is contained in:
Eric House 2014-03-01 15:17:14 -08:00
parent 23638310bc
commit 386c28e596

View file

@ -24,14 +24,17 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.NetworkInfo;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.os.Handler;
import java.util.HashSet;
import java.util.Iterator;
import android.os.Build;
import junit.framework.Assert;
public class NetStateCache {
private static final long WAIT_STABLE_MILLIS = 2 * 1000;
public interface StateChangedIf {
public void netAvail( boolean nowAvailable );
@ -40,7 +43,7 @@ public class NetStateCache {
private static Boolean s_haveReceiver = new Boolean( false );
private static HashSet<StateChangedIf> s_ifs;
private static boolean s_netAvail = false;
private static CommsBroadcastReceiver s_receiver;
private static PvtBroadcastReceiver s_receiver;
private static final boolean s_onSim = Build.PRODUCT.contains("sdk");
public static void register( Context context, StateChangedIf proc )
@ -78,7 +81,7 @@ public class NetStateCache {
s_netAvail = ni != null && ni.isAvailable() && ni.isConnected();
s_receiver = new CommsBroadcastReceiver();
s_receiver = new PvtBroadcastReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction( ConnectivityManager.CONNECTIVITY_ACTION );
@ -91,17 +94,30 @@ public class NetStateCache {
}
}
private static class CommsBroadcastReceiver extends BroadcastReceiver {
private static class PvtBroadcastReceiver extends BroadcastReceiver {
private Runnable mNotifyLater;
private Handler mHandler;
private boolean mLastStateSent;
public PvtBroadcastReceiver()
{
DbgUtils.assertOnUIThread();
mHandler = new Handler();
mLastStateSent = s_netAvail;
}
@Override
public void onReceive( Context context, Intent intent )
{
DbgUtils.assertOnUIThread();
if ( intent.getAction().
equals( ConnectivityManager.CONNECTIVITY_ACTION)) {
NetworkInfo ni = (NetworkInfo)intent.
getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
NetworkInfo.State state = ni.getState();
DbgUtils.logf( "CommsBroadcastReceiver.onReceive: "
DbgUtils.logf( "PvtBroadcastReceiver.onReceive: "
+ "new network state: %s", state.toString() );
boolean netAvail;
@ -119,16 +135,38 @@ public class NetStateCache {
}
if ( s_netAvail != netAvail ) {
s_netAvail = netAvail;
Iterator<StateChangedIf> iter = s_ifs.iterator();
while ( iter.hasNext() ) {
StateChangedIf proc = iter.next();
proc.netAvail( netAvail );
s_netAvail = netAvail; // keep current in case we're asked
// We want to wait for WAIT_STABLE_MILLIS of inactivity
// before informing listeners. So each time there's a
// change, kill any existing timer then set another, which
// will only fire if we go that long without coming
// through here again.
if ( null != mNotifyLater ) {
mHandler.removeCallbacks( mNotifyLater );
mNotifyLater = null;
}
if ( mLastStateSent != s_netAvail ) {
mNotifyLater = new Runnable() {
@Override
public void run() {
DbgUtils.logf( "PvtBroadcastReceiver: run() fired." );
Assert.assertTrue( mLastStateSent != s_netAvail );
mLastStateSent = s_netAvail;
synchronized( s_ifs ) {
Iterator<StateChangedIf> iter = s_ifs.iterator();
while ( iter.hasNext() ) {
iter.next().netAvail( s_netAvail );
}
}
}
};
mHandler.postDelayed( mNotifyLater, WAIT_STABLE_MILLIS );
}
}
}
}
} // class CommsBroadcastReceiver
} // class PvtBroadcastReceiver
}