Binding Taskbar directly from Launcher model
This allows taskbar to be loaded even in case of 3P Launchers and removes dependency on LauncherActivity lifecycle Bug: 187353581 Bug: 188788621 Test: Manual Change-Id: I5a0988e0697b41677d4c58f0213aef14ec0c0972
This commit is contained in:
@@ -23,12 +23,13 @@ import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.LauncherAppState;
|
||||
import com.android.launcher3.LauncherModel;
|
||||
import com.android.launcher3.LauncherModel.CallbackTask;
|
||||
import com.android.launcher3.LauncherProvider;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.LauncherSettings.Favorites;
|
||||
@@ -36,19 +37,22 @@ import com.android.launcher3.LauncherSettings.Settings;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.logging.FileLog;
|
||||
import com.android.launcher3.model.BgDataModel.Callbacks;
|
||||
import com.android.launcher3.model.data.FolderInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.util.ContentWriter;
|
||||
import com.android.launcher3.util.Executors;
|
||||
import com.android.launcher3.util.ItemInfoMatcher;
|
||||
import com.android.launcher3.util.LooperExecutor;
|
||||
import com.android.launcher3.widget.LauncherAppWidgetHost;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.StreamSupport;
|
||||
@@ -63,7 +67,10 @@ public class ModelWriter {
|
||||
private final Context mContext;
|
||||
private final LauncherModel mModel;
|
||||
private final BgDataModel mBgDataModel;
|
||||
private final Handler mUiHandler;
|
||||
private final LooperExecutor mUiExecutor;
|
||||
|
||||
@Nullable
|
||||
private final Callbacks mOwner;
|
||||
|
||||
private final boolean mHasVerticalHotseat;
|
||||
private final boolean mVerifyChanges;
|
||||
@@ -73,13 +80,15 @@ public class ModelWriter {
|
||||
private boolean mPreparingToUndo;
|
||||
|
||||
public ModelWriter(Context context, LauncherModel model, BgDataModel dataModel,
|
||||
boolean hasVerticalHotseat, boolean verifyChanges) {
|
||||
boolean hasVerticalHotseat, boolean verifyChanges,
|
||||
@Nullable Callbacks owner) {
|
||||
mContext = context;
|
||||
mModel = model;
|
||||
mBgDataModel = dataModel;
|
||||
mHasVerticalHotseat = hasVerticalHotseat;
|
||||
mVerifyChanges = verifyChanges;
|
||||
mUiHandler = new Handler(Looper.getMainLooper());
|
||||
mOwner = owner;
|
||||
mUiExecutor = Executors.MAIN_EXECUTOR;
|
||||
}
|
||||
|
||||
private void updateItemInfoProps(
|
||||
@@ -162,6 +171,8 @@ public class ModelWriter {
|
||||
public void moveItemInDatabase(final ItemInfo item,
|
||||
int container, int screenId, int cellX, int cellY) {
|
||||
updateItemInfoProps(item, container, screenId, cellX, cellY);
|
||||
notifyItemModified(item);
|
||||
|
||||
enqueueDeleteRunnable(new UpdateItemRunnable(item, () ->
|
||||
new ContentWriter(mContext)
|
||||
.put(Favorites.CONTAINER, item.container)
|
||||
@@ -178,6 +189,7 @@ public class ModelWriter {
|
||||
public void moveItemsInDatabase(final ArrayList<ItemInfo> items, int container, int screen) {
|
||||
ArrayList<ContentValues> contentValues = new ArrayList<>();
|
||||
int count = items.size();
|
||||
notifyOtherCallbacks(c -> c.bindItemsModified(items));
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
ItemInfo item = items.get(i);
|
||||
@@ -203,8 +215,9 @@ public class ModelWriter {
|
||||
updateItemInfoProps(item, container, screenId, cellX, cellY);
|
||||
item.spanX = spanX;
|
||||
item.spanY = spanY;
|
||||
notifyItemModified(item);
|
||||
|
||||
((Executor) MODEL_EXECUTOR).execute(new UpdateItemRunnable(item, () ->
|
||||
MODEL_EXECUTOR.execute(new UpdateItemRunnable(item, () ->
|
||||
new ContentWriter(mContext)
|
||||
.put(Favorites.CONTAINER, item.container)
|
||||
.put(Favorites.CELLX, item.cellX)
|
||||
@@ -219,13 +232,18 @@ public class ModelWriter {
|
||||
* Update an item to the database in a specified container.
|
||||
*/
|
||||
public void updateItemInDatabase(ItemInfo item) {
|
||||
((Executor) MODEL_EXECUTOR).execute(new UpdateItemRunnable(item, () -> {
|
||||
notifyItemModified(item);
|
||||
MODEL_EXECUTOR.execute(new UpdateItemRunnable(item, () -> {
|
||||
ContentWriter writer = new ContentWriter(mContext);
|
||||
item.onAddToDatabase(writer);
|
||||
return writer;
|
||||
}));
|
||||
}
|
||||
|
||||
private void notifyItemModified(ItemInfo item) {
|
||||
notifyOtherCallbacks(c -> c.bindItemsModified(Collections.singletonList(item)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an item to the database in a specified container. Sets the container, screen, cellX and
|
||||
* cellY fields of the item. Also assigns an ID to the item.
|
||||
@@ -236,10 +254,11 @@ public class ModelWriter {
|
||||
|
||||
final ContentResolver cr = mContext.getContentResolver();
|
||||
item.id = Settings.call(cr, Settings.METHOD_NEW_ITEM_ID).getInt(Settings.EXTRA_VALUE);
|
||||
notifyOtherCallbacks(c -> c.bindItems(Collections.singletonList(item), false));
|
||||
|
||||
ModelVerifier verifier = new ModelVerifier();
|
||||
final StackTraceElement[] stackTrace = new Throwable().getStackTrace();
|
||||
((Executor) MODEL_EXECUTOR).execute(() -> {
|
||||
MODEL_EXECUTOR.execute(() -> {
|
||||
// Write the item on background thread, as some properties might have been updated in
|
||||
// the background.
|
||||
final ContentWriter writer = new ContentWriter(mContext);
|
||||
@@ -281,6 +300,7 @@ public class ModelWriter {
|
||||
(item) -> item.getTargetComponent() == null ? ""
|
||||
: item.getTargetComponent().getPackageName()).collect(
|
||||
Collectors.joining(",")), new Exception());
|
||||
notifyDelete(items);
|
||||
enqueueDeleteRunnable(() -> {
|
||||
for (ItemInfo item : items) {
|
||||
final Uri uri = Favorites.getContentUri(item.id);
|
||||
@@ -297,6 +317,7 @@ public class ModelWriter {
|
||||
*/
|
||||
public void deleteFolderAndContentsFromDatabase(final FolderInfo info) {
|
||||
ModelVerifier verifier = new ModelVerifier();
|
||||
notifyDelete(Collections.singleton(info));
|
||||
|
||||
enqueueDeleteRunnable(() -> {
|
||||
ContentResolver cr = mContext.getContentResolver();
|
||||
@@ -315,6 +336,7 @@ public class ModelWriter {
|
||||
* Deletes the widget info and the widget id.
|
||||
*/
|
||||
public void deleteWidgetInfo(final LauncherAppWidgetInfo info, LauncherAppWidgetHost host) {
|
||||
notifyDelete(Collections.singleton(info));
|
||||
if (host != null && !info.isCustomWidget() && info.isWidgetIdAllocated()) {
|
||||
// Deleting an app widget ID is a void call but writes to disk before returning
|
||||
// to the caller...
|
||||
@@ -323,6 +345,10 @@ public class ModelWriter {
|
||||
deleteItemFromDatabase(info);
|
||||
}
|
||||
|
||||
private void notifyDelete(Collection<? extends ItemInfo> items) {
|
||||
notifyOtherCallbacks(c -> c.bindWorkspaceComponentsRemoved(ItemInfoMatcher.ofItems(items)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete operations tracked using {@link #enqueueDeleteRunnable} will only be called
|
||||
* if {@link #commitDelete} is called. Note that one of {@link #commitDelete()} or
|
||||
@@ -348,14 +374,14 @@ public class ModelWriter {
|
||||
if (mPreparingToUndo) {
|
||||
mDeleteRunnables.add(r);
|
||||
} else {
|
||||
((Executor) MODEL_EXECUTOR).execute(r);
|
||||
MODEL_EXECUTOR.execute(r);
|
||||
}
|
||||
}
|
||||
|
||||
public void commitDelete() {
|
||||
mPreparingToUndo = false;
|
||||
for (Runnable runnable : mDeleteRunnables) {
|
||||
((Executor) MODEL_EXECUTOR).execute(runnable);
|
||||
MODEL_EXECUTOR.execute(runnable);
|
||||
}
|
||||
mDeleteRunnables.clear();
|
||||
}
|
||||
@@ -371,6 +397,20 @@ public class ModelWriter {
|
||||
mModel.forceReload();
|
||||
}
|
||||
|
||||
private void notifyOtherCallbacks(CallbackTask task) {
|
||||
if (mOwner == null) {
|
||||
// If the call is happening from a model, it will take care of updating the callbacks
|
||||
return;
|
||||
}
|
||||
mUiExecutor.execute(() -> {
|
||||
for (Callbacks c : mModel.getCallbacks()) {
|
||||
if (c != mOwner) {
|
||||
task.execute(c);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private class UpdateItemRunnable extends UpdateItemBaseRunnable {
|
||||
private final ItemInfo mItem;
|
||||
private final Supplier<ContentWriter> mWriter;
|
||||
@@ -491,7 +531,7 @@ public class ModelWriter {
|
||||
|
||||
int executeId = mBgDataModel.lastBindId;
|
||||
|
||||
mUiHandler.post(() -> {
|
||||
mUiExecutor.post(() -> {
|
||||
int currentId = mBgDataModel.lastBindId;
|
||||
if (currentId > executeId) {
|
||||
// Model was already bound after job was executed.
|
||||
|
||||
Reference in New Issue
Block a user