instead of unbinding items from the loader, unregistering listeners

in activity.onDestroy()

Bug: 28740269
Change-Id: I6bf2ad6aca43970fd10cfbcc113e609c227e07bf
This commit is contained in:
Sunny Goyal
2016-05-17 13:38:54 -07:00
parent 5b83d6ce8f
commit aaf7d1d13b
6 changed files with 31 additions and 59 deletions
+2 -10
View File
@@ -109,10 +109,8 @@ public class FolderInfo extends ItemInfo {
listeners.add(listener);
}
void removeListener(FolderListener listener) {
if (listeners.contains(listener)) {
listeners.remove(listener);
}
public void removeListener(FolderListener listener) {
listeners.remove(listener);
}
public void itemsChanged(boolean animate) {
@@ -121,12 +119,6 @@ public class FolderInfo extends ItemInfo {
}
}
@Override
void unbind() {
super.unbind();
listeners.clear();
}
public interface FolderListener {
public void onAdd(ShortcutInfo item);
public void onRemove(ShortcutInfo item);
-9
View File
@@ -183,15 +183,6 @@ public class ItemInfo {
}
}
/**
* It is very important that sub-classes implement this if they contain any references
* to the activity (anything in the view hierarchy etc.). If not, leaks can result since
* ItemInfo objects persist across rotation and can hence leak by holding stale references
* to the old view hierarchy / activity.
*/
void unbind() {
}
@Override
public String toString() {
return "Item(id=" + this.id + " type=" + this.itemType + " container=" + this.container
+4
View File
@@ -1967,6 +1967,7 @@ public class Launcher extends Activity
mHandler.removeMessages(ADVANCE_MSG);
mHandler.removeMessages(0);
mWorkspace.removeCallbacks(mBuildLayersRunnable);
mWorkspace.removeFolderListeners();
// Stop callbacks from LauncherModel
// It's possible to receive onDestroy after a new Launcher activity has
@@ -2365,6 +2366,9 @@ public class Launcher extends Activity
}
} else if (itemInfo instanceof FolderInfo) {
final FolderInfo folderInfo = (FolderInfo) itemInfo;
if (v instanceof FolderIcon) {
((FolderIcon) v).removeListeners();
}
mWorkspace.removeWorkspaceItem(v);
if (deleteFromDb) {
LauncherModel.deleteFolderAndContentsFromDatabase(this, folderInfo);
+5 -40
View File
@@ -65,6 +65,7 @@ import com.android.launcher3.util.FlagOp;
import com.android.launcher3.util.LongArrayMap;
import com.android.launcher3.util.ManagedProfileHeuristic;
import com.android.launcher3.util.PackageManagerHelper;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.StringFilter;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.util.ViewOnDrawExecutor;
@@ -578,38 +579,6 @@ public class LauncherModel extends BroadcastReceiver
runOnWorkerThread(r);
}
private void unbindItemInfosAndClearQueuedBindRunnables() {
if (sWorkerThread.getThreadId() == Process.myTid()) {
throw new RuntimeException("Expected unbindLauncherItemInfos() to be called from the " +
"main thread");
}
// Remove any queued UI runnables
mHandler.cancelAll();
// Unbind all the workspace items
unbindWorkspaceItemsOnMainThread();
}
/** Unbinds all the sBgWorkspaceItems and sBgAppWidgets on the main thread */
void unbindWorkspaceItemsOnMainThread() {
// Ensure that we don't use the same workspace items data structure on the main thread
// by making a copy of workspace items first.
final ArrayList<ItemInfo> tmpItems = new ArrayList<ItemInfo>();
synchronized (sBgLock) {
tmpItems.addAll(sBgWorkspaceItems);
tmpItems.addAll(sBgAppWidgets);
}
Runnable r = new Runnable() {
@Override
public void run() {
for (ItemInfo item : tmpItems) {
item.unbind();
}
}
};
runOnMainThread(r);
}
/**
* Adds an item to the DB if it was not created previously, or move it to a new
* <container, screen, cellX, cellY>
@@ -1137,10 +1106,10 @@ public class LauncherModel extends BroadcastReceiver
*/
public void initialize(Callbacks callbacks) {
synchronized (mLock) {
// Disconnect any of the callbacks and drawables associated with ItemInfos on the
// workspace to prevent leaking Launcher activities on orientation change.
unbindItemInfosAndClearQueuedBindRunnables();
mCallbacks = new WeakReference<Callbacks>(callbacks);
Preconditions.assertUIThread();
// Remove any queued UI runnables
mHandler.cancelAll();
mCallbacks = new WeakReference<>(callbacks);
}
}
@@ -2482,10 +2451,6 @@ public class LauncherModel extends BroadcastReceiver
final long currentScreenId = currentScreen < 0
? INVALID_SCREEN_ID : orderedScreenIds.get(currentScreen);
// Load all the items that are on the current page first (and in the process, unbind
// all the existing workspace items before we call startBinding() below.
unbindWorkspaceItemsOnMainThread();
// Separate the items that are on the current screen, and all the other remaining items
ArrayList<ItemInfo> currentWorkspaceItems = new ArrayList<>();
ArrayList<ItemInfo> otherWorkspaceItems = new ArrayList<>();
+15
View File
@@ -3669,6 +3669,21 @@ public class Workspace extends PagedView
}
}
/**
* Removes all folder listeners
*/
public void removeFolderListeners() {
mapOverItems(false, new ItemOperator() {
@Override
public boolean evaluate(ItemInfo info, View view) {
if (view instanceof FolderIcon) {
((FolderIcon) view).removeListeners();
}
return false;
}
});
}
@Override
public void deferCompleteDropAfterUninstallActivity() {
mDeferDropAfterUninstall = true;
@@ -1000,6 +1000,11 @@ public class FolderIcon extends FrameLayout implements FolderListener {
mLongPressHelper.cancelLongPress();
}
public void removeListeners() {
mInfo.removeListener(this);
mInfo.removeListener(mFolder);
}
public interface PreviewLayoutRule {
public PreviewItemDrawingParams computePreviewItemDrawingParams(int index, int curNumItems,
PreviewItemDrawingParams params);