blob: 5551f07467e07b4c7fc9f00098c3e68e082524a8 [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.launcher3.allapps;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.LinearLayout;
import com.android.launcher3.AppInfo;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.ComponentKeyMapper;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
public class PredictionRowView extends LinearLayout {
private static final String TAG = "PredictionRowView";
private HashMap<ComponentKey, AppInfo> mComponentToAppMap;
private int mNumPredictedAppsPerRow;
// The set of predicted app component names
private final List<ComponentKeyMapper<AppInfo>> mPredictedAppComponents = new ArrayList<>();
// The set of predicted apps resolved from the component names and the current set of apps
private final List<AppInfo> mPredictedApps = new ArrayList<>();
public PredictionRowView(@NonNull Context context) {
this(context, null);
}
public PredictionRowView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
setOrientation(LinearLayout.HORIZONTAL);
}
public void setComponentToAppMap(HashMap<ComponentKey, AppInfo> componentToAppMap) {
this.mComponentToAppMap = componentToAppMap;
}
/**
* Sets the number of apps per row.
*/
public void setNumAppsPerRow(int numPredictedAppsPerRow) {
mNumPredictedAppsPerRow = numPredictedAppsPerRow;
}
public void onAppsUpdated() {
// TODO
}
/**
* Returns the predicted apps.
*/
public List<AppInfo> getPredictedApps() {
return mPredictedApps;
}
/**
* Sets the current set of predicted apps.
*
* This can be called before we get the full set of applications, we should merge the results
* only in onAppsUpdated() which is idempotent.
*
* If the number of predicted apps is the same as the previous list of predicted apps,
* we can optimize by swapping them in place.
*/
public void setPredictedApps(List<ComponentKeyMapper<AppInfo>> apps) {
mPredictedAppComponents.clear();
mPredictedAppComponents.addAll(apps);
List<AppInfo> newPredictedApps = processPredictedAppComponents(apps);
// We only need to do work if any of the visible predicted apps have changed.
if (!newPredictedApps.equals(mPredictedApps)) {
if (newPredictedApps.size() == mPredictedApps.size()) {
swapInNewPredictedApps(newPredictedApps);
} else {
// We need to update the appIndex of all the items.
onAppsUpdated();
}
}
}
private List<AppInfo> processPredictedAppComponents(
List<ComponentKeyMapper<AppInfo>> components) {
if (mComponentToAppMap.isEmpty()) {
// Apps have not been bound yet.
return Collections.emptyList();
}
List<AppInfo> predictedApps = new ArrayList<>();
for (ComponentKeyMapper<AppInfo> mapper : components) {
AppInfo info = mapper.getItem(mComponentToAppMap);
if (info != null) {
predictedApps.add(info);
} else {
if (FeatureFlags.IS_DOGFOOD_BUILD) {
Log.e(TAG, "Predicted app not found: " + mapper);
}
}
// Stop at the number of predicted apps
if (predictedApps.size() == mNumPredictedAppsPerRow) {
break;
}
}
return predictedApps;
}
/**
* Swaps out the old predicted apps with the new predicted apps, in place. This optimization
* allows us to skip an entire relayout that would otherwise be called by notifyDataSetChanged.
*
* Note: This should only be called if the # of predicted apps is the same.
* This method assumes that predicted apps are the first items in the adapter.
*/
private void swapInNewPredictedApps(List<AppInfo> apps) {
// TODO
}
}