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.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.net.NetworkInfo;
import android.net.ConnectivityManager; import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.os.Handler;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import android.os.Build;
import junit.framework.Assert; import junit.framework.Assert;
public class NetStateCache { public class NetStateCache {
private static final long WAIT_STABLE_MILLIS = 2 * 1000;
public interface StateChangedIf { public interface StateChangedIf {
public void netAvail( boolean nowAvailable ); public void netAvail( boolean nowAvailable );
@ -40,7 +43,7 @@ public class NetStateCache {
private static Boolean s_haveReceiver = new Boolean( false ); private static Boolean s_haveReceiver = new Boolean( false );
private static HashSet<StateChangedIf> s_ifs; private static HashSet<StateChangedIf> s_ifs;
private static boolean s_netAvail = false; 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"); private static final boolean s_onSim = Build.PRODUCT.contains("sdk");
public static void register( Context context, StateChangedIf proc ) public static void register( Context context, StateChangedIf proc )
@ -78,7 +81,7 @@ public class NetStateCache {
s_netAvail = ni != null && ni.isAvailable() && ni.isConnected(); s_netAvail = ni != null && ni.isAvailable() && ni.isConnected();
s_receiver = new CommsBroadcastReceiver(); s_receiver = new PvtBroadcastReceiver();
IntentFilter filter = new IntentFilter(); IntentFilter filter = new IntentFilter();
filter.addAction( ConnectivityManager.CONNECTIVITY_ACTION ); 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 @Override
public void onReceive( Context context, Intent intent ) public void onReceive( Context context, Intent intent )
{ {
DbgUtils.assertOnUIThread();
if ( intent.getAction(). if ( intent.getAction().
equals( ConnectivityManager.CONNECTIVITY_ACTION)) { equals( ConnectivityManager.CONNECTIVITY_ACTION)) {
NetworkInfo ni = (NetworkInfo)intent. NetworkInfo ni = (NetworkInfo)intent.
getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO); getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
NetworkInfo.State state = ni.getState(); NetworkInfo.State state = ni.getState();
DbgUtils.logf( "CommsBroadcastReceiver.onReceive: " DbgUtils.logf( "PvtBroadcastReceiver.onReceive: "
+ "new network state: %s", state.toString() ); + "new network state: %s", state.toString() );
boolean netAvail; boolean netAvail;
@ -119,16 +135,38 @@ public class NetStateCache {
} }
if ( s_netAvail != netAvail ) { if ( s_netAvail != netAvail ) {
s_netAvail = netAvail; s_netAvail = netAvail; // keep current in case we're asked
Iterator<StateChangedIf> iter = s_ifs.iterator();
while ( iter.hasNext() ) { // We want to wait for WAIT_STABLE_MILLIS of inactivity
StateChangedIf proc = iter.next(); // before informing listeners. So each time there's a
proc.netAvail( netAvail ); // 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
} }