use wrapper to replace static reference

BoardDelegate can have a one-to-one relationship to this thing, and
occasional leakage was preventing opening a new alert, so some fix was
needed. This one's simple.
This commit is contained in:
Eric House 2020-11-27 11:47:38 -08:00
parent 9929de1fa7
commit 437aef5ed5
2 changed files with 93 additions and 110 deletions

View file

@ -130,6 +130,7 @@ public class BoardDelegate extends DelegateBase
private boolean m_haveStartedShowing; private boolean m_haveStartedShowing;
private Wrapper mNFCWrapper; private Wrapper mNFCWrapper;
private InvitesNeededAlert.Wrapper mINAWrapper;
public class TimerRunnable implements Runnable { public class TimerRunnable implements Runnable {
private int m_why; private int m_why;
@ -419,7 +420,7 @@ public class BoardDelegate extends DelegateBase
.create(); .create();
break; break;
case DLG_INVITE: case DLG_INVITE:
dialog = InvitesNeededAlert.make( this, alert, params ); dialog = mINAWrapper.make( alert, params );
break; break;
case ENABLE_NFC: case ENABLE_NFC:
@ -1505,7 +1506,7 @@ public class BoardDelegate extends DelegateBase
post( new Runnable() { post( new Runnable() {
@Override @Override
public void run() { public void run() {
InvitesNeededAlert.dismiss(); mINAWrapper.dismiss();
finish(); finish();
} }
} ); } );
@ -2459,8 +2460,10 @@ public class BoardDelegate extends DelegateBase
{ {
if ( alertOrderAt( StartAlertOrder.INVITE ) && ! isFinishing() ) { if ( alertOrderAt( StartAlertOrder.INVITE ) && ! isFinishing() ) {
boolean isRematch = null != m_summary && m_summary.hasRematchInfo(); boolean isRematch = null != m_summary && m_summary.hasRematchInfo();
InvitesNeededAlert.showOrHide( this, m_mySIS.nGuestDevs, if ( null == mINAWrapper ) {
m_mySIS.nMissing, isRematch ); mINAWrapper = new InvitesNeededAlert.Wrapper( this );
}
mINAWrapper.showOrHide( m_mySIS.nGuestDevs, m_mySIS.nMissing, isRematch );
} }
} }

View file

@ -36,23 +36,75 @@ import org.eehouse.android.xw4.loc.LocUtils;
class InvitesNeededAlert implements DialogInterface.OnDismissListener { class InvitesNeededAlert implements DialogInterface.OnDismissListener {
private static final String TAG = InvitesNeededAlert.class.getSimpleName(); private static final String TAG = InvitesNeededAlert.class.getSimpleName();
private static InvitesNeededAlert[] sInstance = {null};
private DBAlert mAlert;
private State mState;
private Callbacks mCallbacks;
private DelegateBase mDelegate; private DelegateBase mDelegate;
private State mState;
private DBAlert mAlert;
static class Wrapper {
private Callbacks mCallbacks;
private InvitesNeededAlert mSelf;
Wrapper( Callbacks callbacks ) { mCallbacks = callbacks; }
void showOrHide( int nDevsSeen, int nPlayersMissing, boolean isRematch )
{
DbgUtils.assertOnUIThread();
Log.d( TAG, "showOnceIf(nDevsSeen=%d, nPlayersMissing=%d); self: %s",
nDevsSeen, nPlayersMissing, mSelf );
if ( null == mSelf && 0 == nPlayersMissing ) {
// cool: need and have nothing, so do nothing
} else if ( 0 < nPlayersMissing && null == mSelf ) { // Need but don't have
makeNew( nDevsSeen, nPlayersMissing, isRematch );
} else if ( 0 == nPlayersMissing && null != mSelf ) { // Have and need to close
mSelf.close();
} else if ( null != mSelf && nPlayersMissing != mSelf.mState.mNPlayersMissing ) {
mSelf.close();
makeNew( nDevsSeen, nPlayersMissing, isRematch );
} else if ( null != mSelf && nPlayersMissing == mSelf.mState.mNPlayersMissing ) {
// nothing to do
} else {
Assert.failDbg();
}
}
Dialog make( DBAlert alert, Object[] params )
{
DbgUtils.assertOnUIThread();
return mSelf.makeImpl( mCallbacks, alert, params );
}
void dismiss()
{
Log.d( TAG, "dismiss()" );
DbgUtils.assertOnUIThread();
if ( null != mSelf ) {
mSelf.close();
mSelf = null;
}
}
private void makeNew( int nDevsSeen, int nPlayersMissing, boolean isRematch )
{
Log.d( TAG, "makeNew(nDevsSeen=%d, nPlayersMissing=%d)", nDevsSeen, nPlayersMissing );
State state = new State( nDevsSeen, nPlayersMissing, isRematch );
mSelf = new InvitesNeededAlert( mCallbacks.getDelegate(), state );
mCallbacks.getDelegate().showDialogFragment( DlgID.DLG_INVITE, state );
}
}
// Must be kept separate from this because gets passed as param to
// showDialogFragment()
private static class State implements Serializable { private static class State implements Serializable {
int nDevsSeen; private int mNDevsSeen;
int nPlayersMissing; private int mNPlayersMissing;
boolean isRematch; private boolean mIsRematch;
State( int nDevs, int nPlayers, boolean rematch ) State( int nDevs, int nPlayers, boolean rematch )
{ {
nDevsSeen = nDevs; mNDevsSeen = nDevs;
nPlayersMissing = nPlayers; mNPlayersMissing = nPlayers;
isRematch = rematch; mIsRematch = rematch;
} }
} }
@ -64,69 +116,6 @@ class InvitesNeededAlert implements DialogInterface.OnDismissListener {
void onInfoClicked(); void onInfoClicked();
} }
static void showOrHide( Callbacks callbacks, int nDevsSeen,
int nPlayersMissing, boolean isRematch )
{
DbgUtils.assertOnUIThread();
InvitesNeededAlert self = sInstance[0];
Log.d( TAG, "showOnceIf(nDevsSeen=%d, nPlayersMissing=%d); self: %s",
nDevsSeen, nPlayersMissing, self );
if ( null == self && 0 == nPlayersMissing ) {
// cool: need and have nothing, so do nothing
} else if ( 0 < nPlayersMissing && null == self ) { // Need but don't have
makeNew( callbacks, nDevsSeen, nPlayersMissing, isRematch );
} else if ( 0 == nPlayersMissing && null != self ) { // Have and need to close
close( self );
} else if ( null != self && nPlayersMissing != self.mState.nPlayersMissing ) {
close( self );
makeNew( callbacks, nDevsSeen, nPlayersMissing, isRematch );
} else if ( null != self && nPlayersMissing == self.mState.nPlayersMissing ) {
// nothing to do
} else {
Assert.failDbg();
}
}
static Dialog make( Callbacks callbacks, DBAlert alert, Object[] params )
{
DbgUtils.assertOnUIThread();
InvitesNeededAlert self = sInstance[0];
return self.makeImpl( callbacks, alert, params );
}
static void dismiss()
{
Log.d( TAG, "dismiss()" );
DbgUtils.assertOnUIThread();
InvitesNeededAlert self = sInstance[0];
if ( null != self ) {
close( self );
}
}
private static void makeNew( Callbacks callbacks, int nDevsSeen,
int nPlayersMissing, boolean isRematch )
{
Log.d( TAG, "makeNew(nDevsSeen=%d, nPlayersMissing=%d)", nDevsSeen, nPlayersMissing );
State state = new State( nDevsSeen, nPlayersMissing, isRematch );
InvitesNeededAlert self = new InvitesNeededAlert( callbacks, state );
callbacks.getDelegate().showDialogFragment( DlgID.DLG_INVITE, state );
}
private static void close( InvitesNeededAlert self )
{
DbgUtils.assertOnUIThread();
Assert.assertTrueNR( self == sInstance[0] );
if ( self == sInstance[0] ) {
sInstance[0] = null;
if ( null != self.mAlert ) {
InviteChoicesAlert.dismissAny();
self.mAlert.dismiss();
}
}
}
//////////////////////////////////////// ////////////////////////////////////////
// DialogInterface.OnDismissListener // DialogInterface.OnDismissListener
//////////////////////////////////////// ////////////////////////////////////////
@ -134,20 +123,26 @@ class InvitesNeededAlert implements DialogInterface.OnDismissListener {
public void onDismiss( DialogInterface dialog ) public void onDismiss( DialogInterface dialog )
{ {
Log.d( TAG, "onDismiss()" ); Log.d( TAG, "onDismiss()" );
close( this ); close();
} }
private InvitesNeededAlert( Callbacks callbacks, State state ) private void close()
{ {
mState = state;
mCallbacks = callbacks;
mDelegate = callbacks.getDelegate();
DbgUtils.assertOnUIThread(); DbgUtils.assertOnUIThread();
Assert.assertTrueNR( null == sInstance[0] ); if ( null != mAlert ) {
sInstance[0] = this; InviteChoicesAlert.dismissAny();
mAlert.dismiss();
}
} }
private Dialog makeImpl( Callbacks callbacks, final DBAlert alert, private InvitesNeededAlert( DelegateBase delegate, State state )
{
DbgUtils.assertOnUIThread();
mDelegate = delegate;
mState = state;
}
private Dialog makeImpl( final Callbacks callbacks, final DBAlert alert,
Object[] params ) Object[] params )
{ {
Dialog result = null; Dialog result = null;
@ -157,18 +152,19 @@ class InvitesNeededAlert implements DialogInterface.OnDismissListener {
Context context = mDelegate.getActivity(); Context context = mDelegate.getActivity();
String title; String title;
boolean isRematch = state.isRematch; boolean isRematch = state.mIsRematch;
final int nPlayersMissing = state.mNPlayersMissing;
if ( isRematch ) { if ( isRematch ) {
title = LocUtils.getString( context, R.string.waiting_rematch_title ); title = LocUtils.getString( context, R.string.waiting_rematch_title );
} else { } else {
title = LocUtils title = LocUtils
.getQuantityString( context, R.plurals.waiting_title_fmt, .getQuantityString( context, R.plurals.waiting_title_fmt,
state.nPlayersMissing, state.nPlayersMissing ); nPlayersMissing, nPlayersMissing );
} }
String message = LocUtils String message = LocUtils
.getQuantityString( context, R.plurals.invite_msg_fmt, .getQuantityString( context, R.plurals.invite_msg_fmt,
state.nPlayersMissing, state.nPlayersMissing ); nPlayersMissing, nPlayersMissing );
message += "\n\n" message += "\n\n"
+ LocUtils.getString( context, R.string.invite_msg_extra ); + LocUtils.getString( context, R.string.invite_msg_extra );
@ -185,21 +181,21 @@ class InvitesNeededAlert implements DialogInterface.OnDismissListener {
new OnClickListener() { new OnClickListener() {
@Override @Override
public void onClick( DialogInterface dlg, int item ) { public void onClick( DialogInterface dlg, int item ) {
onPosClick(); callbacks.onInviteClicked();
} }
} ); } );
if ( BuildConfig.NON_RELEASE ) { if ( BuildConfig.NON_RELEASE ) {
long rowid = mCallbacks.getRowID(); long rowid = callbacks.getRowID();
SentInvitesInfo sentInfo = DBUtils.getInvitesFor( context, rowid ); SentInvitesInfo sentInfo = DBUtils.getInvitesFor( context, rowid );
int nSent = sentInfo.getMinPlayerCount(); int nSent = sentInfo.getMinPlayerCount();
boolean invitesSent = nSent >= state.nPlayersMissing; boolean invitesSent = nSent >= nPlayersMissing;
if ( invitesSent ) { if ( invitesSent ) {
alert.setNoDismissListenerNeut( ab, R.string.newgame_invite_more, alert.setNoDismissListenerNeut( ab, R.string.newgame_invite_more,
new OnClickListener() { new OnClickListener() {
@Override @Override
public void onClick( DialogInterface dlg, int item ) { public void onClick( DialogInterface dlg, int item ) {
onNeutClick(); callbacks.onInfoClicked();
} }
} ); } );
} }
@ -209,7 +205,7 @@ class InvitesNeededAlert implements DialogInterface.OnDismissListener {
new OnClickListener() { new OnClickListener() {
@Override @Override
public void onClick( DialogInterface dlg, int item ) { public void onClick( DialogInterface dlg, int item ) {
onNegClick(); callbacks.onCloseClicked();
} }
} ); } );
@ -217,20 +213,4 @@ class InvitesNeededAlert implements DialogInterface.OnDismissListener {
result.setOnDismissListener( this ); result.setOnDismissListener( this );
return result; return result;
} }
private void onPosClick()
{
mCallbacks.onInviteClicked();
}
private void onNeutClick()
{
mCallbacks.onInfoClicked();
}
private void onNegClick()
{
Log.d( TAG, "onNegClick()" );
mCallbacks.onCloseClicked();
}
} }