1717package android .widget ;
1818
1919import java .lang .ref .WeakReference ;
20+ import java .util .ArrayList ;
2021import java .util .HashMap ;
2122import java .util .HashSet ;
2223import java .util .LinkedList ;
23-
2424import android .appwidget .AppWidgetManager ;
2525import android .content .Context ;
2626import android .content .Intent ;
3838import android .view .View ;
3939import android .view .View .MeasureSpec ;
4040import android .view .ViewGroup ;
41- import android .widget .RemoteViewsService .RemoteViewsFactory ;
4241
4342import com .android .internal .widget .IRemoteViewsAdapterConnection ;
4443import com .android .internal .widget .IRemoteViewsFactory ;
@@ -532,10 +531,9 @@ private RemoteViewsFrameLayout createLoadingView(int position, View convertView,
532531 private static class RemoteViewsIndexMetaData implements Parcelable {
533532 int typeId ;
534533 long itemId ;
535- boolean isRequested ;
536534
537- public RemoteViewsIndexMetaData (RemoteViews v , long itemId , boolean requested ) {
538- set (v , itemId , requested );
535+ public RemoteViewsIndexMetaData (RemoteViews v , long itemId ) {
536+ set (v , itemId );
539537 }
540538
541539 public RemoteViewsIndexMetaData (Parcel src ) {
@@ -554,17 +552,14 @@ public int describeContents() {
554552 return 0 ;
555553 }
556554
557- public void set (RemoteViews v , long id , boolean requested ) {
555+ public void set (RemoteViews v , long id ) {
558556 itemId = id ;
559557 if (v != null ) {
560558 typeId = v .getLayoutId ();
561559 } else {
562560 typeId = 0 ;
563561 }
564- isRequested = requested ;
565562 }
566-
567-
568563 }
569564
570565 /**
@@ -683,10 +678,11 @@ public int describeContents() {
683678 return 0 ;
684679 }
685680
686- public void insert (int position , RemoteViews v , long itemId , boolean isRequested ) {
681+ public void insert (int position , RemoteViews v , long itemId ,
682+ ArrayList <Integer > visibleWindow ) {
687683 // Trim the cache if we go beyond the count
688684 if (mIndexRemoteViews .size () >= mMaxCount ) {
689- mIndexRemoteViews .remove (getFarthestPositionFrom (position ));
685+ mIndexRemoteViews .remove (getFarthestPositionFrom (position , visibleWindow ));
690686 }
691687
692688 // Trim the cache if we go beyond the available memory size constraints
@@ -697,15 +693,15 @@ public void insert(int position, RemoteViews v, long itemId, boolean isRequested
697693 // remove based on both its position as well as it's current memory usage, as well
698694 // as whether it was directly requested vs. whether it was preloaded by our caching
699695 // mechanism.
700- mIndexRemoteViews .remove (getFarthestPositionFrom (pruneFromPosition ));
696+ mIndexRemoteViews .remove (getFarthestPositionFrom (pruneFromPosition , visibleWindow ));
701697 }
702698
703699 // Update the metadata cache
704700 if (mIndexMetaData .containsKey (position )) {
705701 final RemoteViewsIndexMetaData metaData = mIndexMetaData .get (position );
706- metaData .set (v , itemId , isRequested );
702+ metaData .set (v , itemId );
707703 } else {
708- mIndexMetaData .put (position , new RemoteViewsIndexMetaData (v , itemId , isRequested ));
704+ mIndexMetaData .put (position , new RemoteViewsIndexMetaData (v , itemId ));
709705 }
710706 mIndexRemoteViews .put (position , v );
711707 }
@@ -748,29 +744,30 @@ private int getRemoteViewsBitmapMemoryUsage() {
748744 }
749745 return mem ;
750746 }
751- private int getFarthestPositionFrom (int pos ) {
747+
748+ private int getFarthestPositionFrom (int pos , ArrayList <Integer > visibleWindow ) {
752749 // Find the index farthest away and remove that
753750 int maxDist = 0 ;
754751 int maxDistIndex = -1 ;
755- int maxDistNonRequested = 0 ;
756- int maxDistIndexNonRequested = -1 ;
752+ int maxDistNotVisible = 0 ;
753+ int maxDistIndexNotVisible = -1 ;
757754 for (int i : mIndexRemoteViews .keySet ()) {
758755 int dist = Math .abs (i -pos );
759- if (dist > maxDistNonRequested && !mIndexMetaData . get (i ). isRequested ) {
760- // maxDistNonRequested/maxDistIndexNonRequested will store the index of the
761- // farthest non-requested position
762- maxDistIndexNonRequested = i ;
763- maxDistNonRequested = dist ;
756+ if (dist > maxDistNotVisible && !visibleWindow . contains (i )) {
757+ // maxDistNotVisible/maxDistIndexNotVisible will store the index of the
758+ // farthest non-visible position
759+ maxDistIndexNotVisible = i ;
760+ maxDistNotVisible = dist ;
764761 }
765762 if (dist >= maxDist ) {
766763 // maxDist/maxDistIndex will store the index of the farthest position
767- // regardless of whether it was directly requested or not
764+ // regardless of whether it is visible or not
768765 maxDistIndex = i ;
769766 maxDist = dist ;
770767 }
771768 }
772- if (maxDistIndexNonRequested > -1 ) {
773- return maxDistIndexNonRequested ;
769+ if (maxDistIndexNotVisible > -1 ) {
770+ return maxDistIndexNotVisible ;
774771 }
775772 return maxDistIndex ;
776773 }
@@ -967,15 +964,13 @@ public void run() {
967964 if (mServiceConnection .isConnected ()) {
968965 // Get the next index to load
969966 int position = -1 ;
970- boolean isRequested = false ;
971967 synchronized (mCache ) {
972968 int [] res = mCache .getNextIndexToLoad ();
973969 position = res [0 ];
974- isRequested = res [1 ] > 0 ;
975970 }
976971 if (position > -1 ) {
977972 // Load the item, and notify any existing RemoteViewsFrameLayouts
978- updateRemoteViews (position , isRequested , true );
973+ updateRemoteViews (position , true );
979974
980975 // Queue up for the next one to load
981976 loadNextIndexInBackground ();
@@ -1037,8 +1032,7 @@ private void updateTemporaryMetaData() {
10371032 }
10381033 }
10391034
1040- private void updateRemoteViews (final int position , boolean isRequested , boolean
1041- notifyWhenLoaded ) {
1035+ private void updateRemoteViews (final int position , boolean notifyWhenLoaded ) {
10421036 IRemoteViewsFactory factory = mServiceConnection .getRemoteViewsFactory ();
10431037
10441038 // Load the item information from the remote service
@@ -1070,13 +1064,17 @@ private void updateRemoteViews(final int position, boolean isRequested, boolean
10701064 int layoutId = remoteViews .getLayoutId ();
10711065 RemoteViewsMetaData metaData = mCache .getMetaData ();
10721066 boolean viewTypeInRange ;
1067+ int cacheCount ;
10731068 synchronized (metaData ) {
10741069 viewTypeInRange = metaData .isViewTypeInRange (layoutId );
1070+ cacheCount = mCache .mMetaData .count ;
10751071 }
10761072 synchronized (mCache ) {
10771073 if (viewTypeInRange ) {
1074+ ArrayList <Integer > visibleWindow = getVisibleWindow (mVisibleWindowLowerBound ,
1075+ mVisibleWindowUpperBound , cacheCount );
10781076 // Cache the RemoteViews we loaded
1079- mCache .insert (position , remoteViews , itemId , isRequested );
1077+ mCache .insert (position , remoteViews , itemId , visibleWindow );
10801078
10811079 // Notify all the views that we have previously returned for this index that
10821080 // there is new data for it.
@@ -1199,7 +1197,6 @@ public View getView(int position, View convertView, ViewGroup parent) {
11991197 Context context = parent .getContext ();
12001198 RemoteViews rv = mCache .getRemoteViewsAt (position );
12011199 RemoteViewsIndexMetaData indexMetaData = mCache .getMetaDataAt (position );
1202- indexMetaData .isRequested = true ;
12031200 int typeId = indexMetaData .typeId ;
12041201
12051202 try {
@@ -1298,18 +1295,21 @@ private void onNotifyDataSetChanged() {
12981295 // Re-request the new metadata (only after the notification to the factory)
12991296 updateTemporaryMetaData ();
13001297 int newCount ;
1298+ ArrayList <Integer > visibleWindow ;
13011299 synchronized (mCache .getTemporaryMetaData ()) {
13021300 newCount = mCache .getTemporaryMetaData ().count ;
1301+ visibleWindow = getVisibleWindow (mVisibleWindowLowerBound ,
1302+ mVisibleWindowUpperBound , newCount );
13031303 }
13041304
13051305 // Pre-load (our best guess of) the views which are currently visible in the AdapterView.
13061306 // This mitigates flashing and flickering of loading views when a widget notifies that
13071307 // its data has changed.
1308- for (int i = mVisibleWindowLowerBound ; i <= mVisibleWindowUpperBound ; i ++ ) {
1308+ for (int i : visibleWindow ) {
13091309 // Because temporary meta data is only ever modified from this thread (ie.
13101310 // mWorkerThread), it is safe to assume that count is a valid representation.
13111311 if (i < newCount ) {
1312- updateRemoteViews (i , false , false );
1312+ updateRemoteViews (i , false );
13131313 }
13141314 }
13151315
@@ -1330,6 +1330,25 @@ public void run() {
13301330 mNotifyDataSetChangedAfterOnServiceConnected = false ;
13311331 }
13321332
1333+ private ArrayList <Integer > getVisibleWindow (int lower , int upper , int count ) {
1334+ ArrayList <Integer > window = new ArrayList <Integer >();
1335+ if (lower <= upper ) {
1336+ for (int i = lower ; i <= upper ; i ++){
1337+ window .add (i );
1338+ }
1339+ } else {
1340+ // If the upper bound is less than the lower bound it means that the visible window
1341+ // wraps around.
1342+ for (int i = lower ; i < count ; i ++) {
1343+ window .add (i );
1344+ }
1345+ for (int i = 0 ; i <= upper ; i ++) {
1346+ window .add (i );
1347+ }
1348+ }
1349+ return window ;
1350+ }
1351+
13331352 public void notifyDataSetChanged () {
13341353 // Dequeue any unbind messages
13351354 mMainQueue .removeMessages (sUnbindServiceMessageType );
0 commit comments