3737import android .graphics .drawable .shapes .Shape ;
3838import android .os .Parcel ;
3939import android .os .Parcelable ;
40- import android .os .SystemClock ;
4140import android .util .AttributeSet ;
42- import android .view .Choreographer ;
41+ import android .util .Pool ;
42+ import android .util .Poolable ;
43+ import android .util .PoolableManager ;
44+ import android .util .Pools ;
4345import android .view .Gravity ;
4446import android .view .RemotableViewMethod ;
4547import android .view .View ;
5557import android .view .animation .Transformation ;
5658import android .widget .RemoteViews .RemoteView ;
5759
60+ import java .util .ArrayList ;
61+
5862
5963/**
6064 * <p>
@@ -218,6 +222,10 @@ public class ProgressBar extends View {
218222 private boolean mShouldStartAnimationDrawable ;
219223
220224 private boolean mInDrawing ;
225+ private boolean mAttached ;
226+ private boolean mRefreshIsPosted ;
227+
228+ private final ArrayList <RefreshData > mRefreshData = new ArrayList <RefreshData >();
221229
222230 private AccessibilityEventSender mAccessibilityEventSender ;
223231
@@ -558,29 +566,76 @@ public void postInvalidate() {
558566 }
559567
560568 private class RefreshProgressRunnable implements Runnable {
569+ public void run () {
570+ synchronized (ProgressBar .this ) {
571+ final int count = mRefreshData .size ();
572+ for (int i = 0 ; i < count ; i ++) {
573+ final RefreshData rd = mRefreshData .get (i );
574+ doRefreshProgress (rd .id , rd .progress , rd .fromUser , true );
575+ rd .recycle ();
576+ }
577+ mRefreshData .clear ();
578+ mRefreshIsPosted = false ;
579+ }
580+ }
581+ }
561582
562- private int mId ;
563- private int mProgress ;
564- private boolean mFromUser ;
583+ private static class RefreshData implements Poolable <RefreshData > {
584+ public int id ;
585+ public int progress ;
586+ public boolean fromUser ;
565587
566- RefreshProgressRunnable (int id , int progress , boolean fromUser ) {
567- mId = id ;
568- mProgress = progress ;
569- mFromUser = fromUser ;
570- }
588+ private RefreshData mNext ;
589+ private boolean mIsPooled ;
571590
572- public void run () {
573- doRefreshProgress (mId , mProgress , mFromUser , true );
574- // Put ourselves back in the cache when we are done
575- mRefreshProgressRunnable = this ;
591+ private static final int POOL_MAX = 24 ;
592+ private static final Pool <RefreshData > sPool = Pools .synchronizedPool (
593+ Pools .finitePool (new PoolableManager <RefreshData >() {
594+ @ Override
595+ public RefreshData newInstance () {
596+ return new RefreshData ();
597+ }
598+
599+ @ Override
600+ public void onAcquired (RefreshData element ) {
601+ }
602+
603+ @ Override
604+ public void onReleased (RefreshData element ) {
605+ }
606+ }, POOL_MAX ));
607+
608+ public static RefreshData obtain (int id , int progress , boolean fromUser ) {
609+ RefreshData rd = sPool .acquire ();
610+ rd .id = id ;
611+ rd .progress = progress ;
612+ rd .fromUser = fromUser ;
613+ return rd ;
576614 }
577615
578- public void setup (int id , int progress , boolean fromUser ) {
579- mId = id ;
580- mProgress = progress ;
581- mFromUser = fromUser ;
616+ public void recycle () {
617+ sPool .release (this );
618+ }
619+
620+ @ Override
621+ public void setNextPoolable (RefreshData element ) {
622+ mNext = element ;
623+ }
624+
625+ @ Override
626+ public RefreshData getNextPoolable () {
627+ return mNext ;
628+ }
629+
630+ @ Override
631+ public boolean isPooled () {
632+ return mIsPooled ;
633+ }
634+
635+ @ Override
636+ public void setPooled (boolean isPooled ) {
637+ mIsPooled = isPooled ;
582638 }
583-
584639 }
585640
586641 private synchronized void doRefreshProgress (int id , int progress , boolean fromUser ,
@@ -619,14 +674,16 @@ private synchronized void refreshProgress(int id, int progress, boolean fromUser
619674 if (mRefreshProgressRunnable != null ) {
620675 // Use cached RefreshProgressRunnable if available
621676 r = mRefreshProgressRunnable ;
622- // Uncache it
623- mRefreshProgressRunnable = null ;
624- r .setup (id , progress , fromUser );
625677 } else {
626678 // Make a new one
627- r = new RefreshProgressRunnable (id , progress , fromUser );
679+ r = new RefreshProgressRunnable ();
680+ }
681+ final RefreshData rd = RefreshData .obtain (id , progress , fromUser );
682+ mRefreshData .add (rd );
683+ if (mAttached && !mRefreshIsPosted ) {
684+ post (r );
685+ mRefreshIsPosted = true ;
628686 }
629- post (r );
630687 }
631688 }
632689
@@ -1092,14 +1149,29 @@ protected void onAttachedToWindow() {
10921149 if (mIndeterminate ) {
10931150 startAnimation ();
10941151 }
1152+ if (mRefreshData != null ) {
1153+ synchronized (this ) {
1154+ final int count = mRefreshData .size ();
1155+ for (int i = 0 ; i < count ; i ++) {
1156+ final RefreshData rd = mRefreshData .get (i );
1157+ doRefreshProgress (rd .id , rd .progress , rd .fromUser , true );
1158+ rd .recycle ();
1159+ }
1160+ mRefreshData .clear ();
1161+ }
1162+ }
1163+ mAttached = true ;
10951164 }
10961165
10971166 @ Override
10981167 protected void onDetachedFromWindow () {
10991168 if (mIndeterminate ) {
11001169 stopAnimation ();
11011170 }
1102- if (mRefreshProgressRunnable != null ) {
1171+ if (mRefreshProgressRunnable != null ) {
1172+ removeCallbacks (mRefreshProgressRunnable );
1173+ }
1174+ if (mRefreshProgressRunnable != null && mRefreshIsPosted ) {
11031175 removeCallbacks (mRefreshProgressRunnable );
11041176 }
11051177 if (mAccessibilityEventSender != null ) {
@@ -1108,6 +1180,7 @@ protected void onDetachedFromWindow() {
11081180 // This should come after stopAnimation(), otherwise an invalidate message remains in the
11091181 // queue, which can prevent the entire view hierarchy from being GC'ed during a rotation
11101182 super .onDetachedFromWindow ();
1183+ mAttached = false ;
11111184 }
11121185
11131186 @ Override
0 commit comments