mirror of
git://xwords.git.sourceforge.net/gitroot/xwords/xwords
synced 2025-02-02 20:46:15 +01:00
first cut at fix to hundreds of games leading to attention-grabbing
battery usage: rather than have every single ExpiringDelegate set its own timer, run a single time they can attach themselves to.
This commit is contained in:
parent
dd0a677d97
commit
6fe302eab1
1 changed files with 82 additions and 44 deletions
|
@ -31,6 +31,10 @@ import android.graphics.drawable.Drawable;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Set;
|
||||||
import junit.framework.Assert;
|
import junit.framework.Assert;
|
||||||
|
|
||||||
public class ExpiringDelegate {
|
public class ExpiringDelegate {
|
||||||
|
@ -48,7 +52,6 @@ public class ExpiringDelegate {
|
||||||
private int m_backPct = -1;
|
private int m_backPct = -1;
|
||||||
private Drawable m_back = null;
|
private Drawable m_back = null;
|
||||||
private boolean m_doFrame = false;
|
private boolean m_doFrame = false;
|
||||||
private Handler m_handler;
|
|
||||||
private boolean m_haveTurnLocal = false;
|
private boolean m_haveTurnLocal = false;
|
||||||
private long m_startSecs;
|
private long m_startSecs;
|
||||||
private Runnable m_runnable = null;
|
private Runnable m_runnable = null;
|
||||||
|
@ -59,12 +62,79 @@ public class ExpiringDelegate {
|
||||||
private static float[] s_points;
|
private static float[] s_points;
|
||||||
private DrawSelDelegate m_dsdel;
|
private DrawSelDelegate m_dsdel;
|
||||||
|
|
||||||
|
// Combine all the timers into one. Since WeakReferences to the same
|
||||||
|
// object aren't equal we need a separate set of their hash codes to
|
||||||
|
// prevent storing duplicates.
|
||||||
|
private static class ExpUpdater implements Runnable {
|
||||||
|
private Handler m_handler;
|
||||||
|
private ArrayList<WeakReference<ExpiringDelegate>> m_refs
|
||||||
|
= new ArrayList<WeakReference<ExpiringDelegate>>();
|
||||||
|
private Set<Integer> m_hashes = new HashSet<Integer>();
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
int sizeBefore;
|
||||||
|
ArrayList<ExpiringDelegate> dlgts = new ArrayList<ExpiringDelegate>();
|
||||||
|
synchronized( this ) {
|
||||||
|
sizeBefore = m_refs.size();
|
||||||
|
m_hashes.clear();
|
||||||
|
Iterator<WeakReference<ExpiringDelegate>> iter = m_refs.iterator();
|
||||||
|
while ( iter.hasNext() ) {
|
||||||
|
WeakReference<ExpiringDelegate> ref = iter.next();
|
||||||
|
ExpiringDelegate dlgt = ref.get();
|
||||||
|
if ( null == dlgt/* || dlgts.contains( dlgt )*/ ) {
|
||||||
|
iter.remove();
|
||||||
|
} else {
|
||||||
|
dlgts.add(dlgt);
|
||||||
|
m_hashes.add( dlgt.hashCode() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DbgUtils.logdf( "ExpUpdater: ref had %d refs, now has %d expiringdelegate views",
|
||||||
|
sizeBefore, dlgts.size() );
|
||||||
|
|
||||||
|
for ( ExpiringDelegate dlgt : dlgts ) {
|
||||||
|
dlgt.timerFired();
|
||||||
|
}
|
||||||
|
|
||||||
|
reschedule();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void reschedule()
|
||||||
|
{
|
||||||
|
m_handler.postDelayed( this, INTERVAL_SECS * 1000 / 100 );
|
||||||
|
}
|
||||||
|
|
||||||
|
private void add( ExpiringDelegate self )
|
||||||
|
{
|
||||||
|
int hash = self.hashCode();
|
||||||
|
synchronized( this ) {
|
||||||
|
if ( ! m_hashes.contains( hash ) ) {
|
||||||
|
m_hashes.add( hash );
|
||||||
|
m_refs.add( new WeakReference<ExpiringDelegate>(self) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setHandler( Handler handler )
|
||||||
|
{
|
||||||
|
if ( handler != m_handler ) {
|
||||||
|
DbgUtils.logdf( "handler changing from %H to %H",
|
||||||
|
m_handler, handler );
|
||||||
|
m_handler = handler;
|
||||||
|
reschedule();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ExpUpdater s_updater;
|
||||||
static {
|
static {
|
||||||
s_rect = new Rect();
|
s_rect = new Rect();
|
||||||
s_paint = new Paint();
|
s_paint = new Paint();
|
||||||
s_paint.setStyle(Paint.Style.STROKE);
|
s_paint.setStyle(Paint.Style.STROKE);
|
||||||
s_paint.setStrokeWidth( 1 );
|
s_paint.setStrokeWidth( 1 );
|
||||||
s_points = new float[4*6];
|
s_points = new float[4*6];
|
||||||
|
s_updater = new ExpUpdater();
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExpiringDelegate( Context context, View view )
|
public ExpiringDelegate( Context context, View view )
|
||||||
|
@ -76,7 +146,7 @@ public class ExpiringDelegate {
|
||||||
|
|
||||||
public void setHandler( Handler handler )
|
public void setHandler( Handler handler )
|
||||||
{
|
{
|
||||||
m_handler = handler;
|
s_updater.setHandler( handler );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void configure( boolean haveTurn, boolean haveTurnLocal,
|
public void configure( boolean haveTurn, boolean haveTurnLocal,
|
||||||
|
@ -204,54 +274,22 @@ public class ExpiringDelegate {
|
||||||
m_pct = 100;
|
m_pct = 100;
|
||||||
} else if ( m_pct < 0 ) {
|
} else if ( m_pct < 0 ) {
|
||||||
m_pct = 0;
|
m_pct = 0;
|
||||||
} else if ( null != m_handler ) {
|
|
||||||
long onePct = INTERVAL_SECS / 100;
|
|
||||||
long lastStart = m_startSecs + (onePct * m_pct);
|
|
||||||
Assert.assertTrue( lastStart <= now );
|
|
||||||
long nextStartIn = lastStart + onePct - now;
|
|
||||||
// DbgUtils.logf( "pct change %d seconds from now", nextStartIn );
|
|
||||||
|
|
||||||
m_handler.postDelayed( mkRunnable(), 1000 * nextStartIn );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Runnable mkRunnable()
|
|
||||||
{
|
|
||||||
if ( null == m_runnable ) {
|
|
||||||
m_runnable = mkRunnable( this );
|
|
||||||
}
|
|
||||||
return m_runnable;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Runnable mkRunnable( ExpiringDelegate self )
|
|
||||||
{
|
|
||||||
final WeakReference<ExpiringDelegate> selfRef
|
|
||||||
= new WeakReference<ExpiringDelegate>( self );
|
|
||||||
return new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
ExpiringDelegate dlgt = selfRef.get();
|
|
||||||
if ( null != dlgt ) {
|
|
||||||
if ( XWApp.DEBUG_EXP_TIMERS ) {
|
|
||||||
DbgUtils.logf( "ExpiringDelegate: timer fired"
|
|
||||||
+ " for %H", this );
|
|
||||||
}
|
|
||||||
if ( dlgt.m_active ) {
|
|
||||||
dlgt.figurePct();
|
|
||||||
if ( dlgt.m_haveTurnLocal ) {
|
|
||||||
dlgt.m_back = null;
|
|
||||||
dlgt.setBackground();
|
|
||||||
}
|
|
||||||
if ( XWApp.DEBUG_EXP_TIMERS ) {
|
|
||||||
DbgUtils.logf( "ExpiringDelegate: invalidating"
|
|
||||||
+ " view %H", dlgt.m_view );
|
|
||||||
}
|
|
||||||
dlgt.m_view.invalidate();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
DbgUtils.logf( "ExpiringDelegate.run(): reference gc'd" );
|
s_updater.add( this );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
private void timerFired()
|
||||||
|
{
|
||||||
|
if ( m_active ) {
|
||||||
|
figurePct();
|
||||||
|
if ( m_haveTurnLocal ) {
|
||||||
|
m_back = null;
|
||||||
|
setBackground();
|
||||||
|
}
|
||||||
|
m_view.invalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue