/** * Updates the set of filtered apps with the current filter. At this point, we expect * mCachedSectionNames to have been calculated for the set of all apps in mApps. */ private void updateAdapterItems() { SectionInfo lastSectionInfo = null; String lastSectionName = null; FastScrollSectionInfo lastFastScrollerSectionInfo = null; int position = 0; int appIndex = 0; // Prepare to update the list of sections, filtered apps, etc. mFilteredApps.clear(); mFastScrollerSections.clear(); mAdapterItems.clear(); mSections.clear(); if (DEBUG_PREDICTIONS) { if (mPredictedAppComponents.isEmpty() && !mApps.isEmpty()) { mPredictedAppComponents.add( new ComponentKey(mApps.get(0).componentName, UserHandleCompat.myUserHandle())); mPredictedAppComponents.add( new ComponentKey(mApps.get(0).componentName, UserHandleCompat.myUserHandle())); mPredictedAppComponents.add( new ComponentKey(mApps.get(0).componentName, UserHandleCompat.myUserHandle())); mPredictedAppComponents.add( new ComponentKey(mApps.get(0).componentName, UserHandleCompat.myUserHandle())); } } // Process the predicted app components mPredictedApps.clear(); if (mPredictedAppComponents != null && !mPredictedAppComponents.isEmpty() && !hasFilter()) { for (ComponentKey ck : mPredictedAppComponents) { AppInfo info = mComponentToAppMap.get(ck); if (info != null) { mPredictedApps.add(info); } else { if (LauncherAppState.isDogfoodBuild()) { Log.e(TAG, "Predicted app not found: " + ck.flattenToString(mLauncher)); } } // Stop at the number of predicted apps if (mPredictedApps.size() == mNumPredictedAppsPerRow) { break; } } if (!mPredictedApps.isEmpty()) { // Add a section for the predictions lastSectionInfo = new SectionInfo(); lastFastScrollerSectionInfo = new FastScrollSectionInfo(""); AdapterItem sectionItem = AdapterItem.asSectionBreak(position++, lastSectionInfo); mSections.add(lastSectionInfo); mFastScrollerSections.add(lastFastScrollerSectionInfo); mAdapterItems.add(sectionItem); // Add the predicted app items for (AppInfo info : mPredictedApps) { AdapterItem appItem = AdapterItem.asPredictedApp( position++, lastSectionInfo, "", lastSectionInfo.numApps++, info, appIndex++); if (lastSectionInfo.firstAppItem == null) { lastSectionInfo.firstAppItem = appItem; lastFastScrollerSectionInfo.fastScrollToItem = appItem; } mAdapterItems.add(appItem); mFilteredApps.add(info); } } } // Recreate the filtered and sectioned apps (for convenience for the grid layout) from the // ordered set of sections for (AppInfo info : getFiltersAppInfos()) { String sectionName = getAndUpdateCachedSectionName(info.title); // Create a new section if the section names do not match if (lastSectionInfo == null || !sectionName.equals(lastSectionName)) { lastSectionName = sectionName; lastSectionInfo = new SectionInfo(); lastFastScrollerSectionInfo = new FastScrollSectionInfo(sectionName); mSections.add(lastSectionInfo); mFastScrollerSections.add(lastFastScrollerSectionInfo); // Create a new section item to break the flow of items in the list if (!hasFilter()) { AdapterItem sectionItem = AdapterItem.asSectionBreak(position++, lastSectionInfo); mAdapterItems.add(sectionItem); } } // Create an app item AdapterItem appItem = AdapterItem.asApp( position++, lastSectionInfo, sectionName, lastSectionInfo.numApps++, info, appIndex++); if (lastSectionInfo.firstAppItem == null) { lastSectionInfo.firstAppItem = appItem; lastFastScrollerSectionInfo.fastScrollToItem = appItem; } mAdapterItems.add(appItem); mFilteredApps.add(info); } // Append the search market item if we are currently searching if (hasFilter()) { if (hasNoFilteredResults()) { mAdapterItems.add(AdapterItem.asEmptySearch(position++)); } else { mAdapterItems.add(AdapterItem.asDivider(position++)); } mAdapterItems.add(AdapterItem.asMarketSearch(position++)); } // Merge multiple sections together as requested by the merge strategy for this device mergeSections(); if (mNumAppsPerRow != 0) { // Update the number of rows in the adapter after we do all the merging (otherwise, we // would have to shift the values again) int numAppsInSection = 0; int numAppsInRow = 0; int rowIndex = -1; for (AdapterItem item : mAdapterItems) { item.rowIndex = 0; if (item.viewType == AllAppsGridAdapter.SECTION_BREAK_VIEW_TYPE) { numAppsInSection = 0; } else if (item.viewType == AllAppsGridAdapter.ICON_VIEW_TYPE || item.viewType == AllAppsGridAdapter.PREDICTION_ICON_VIEW_TYPE) { if (numAppsInSection % mNumAppsPerRow == 0) { numAppsInRow = 0; rowIndex++; } item.rowIndex = rowIndex; item.rowAppIndex = numAppsInRow; numAppsInSection++; numAppsInRow++; } } mNumAppRowsInAdapter = rowIndex + 1; // Pre-calculate all the fast scroller fractions switch (mFastScrollDistributionMode) { case FAST_SCROLL_FRACTION_DISTRIBUTE_BY_ROWS_FRACTION: float rowFraction = 1f / mNumAppRowsInAdapter; for (FastScrollSectionInfo info : mFastScrollerSections) { AdapterItem item = info.fastScrollToItem; if (item.viewType != AllAppsGridAdapter.ICON_VIEW_TYPE && item.viewType != AllAppsGridAdapter.PREDICTION_ICON_VIEW_TYPE) { info.touchFraction = 0f; continue; } float subRowFraction = item.rowAppIndex * (rowFraction / mNumAppsPerRow); info.touchFraction = item.rowIndex * rowFraction + subRowFraction; } break; case FAST_SCROLL_FRACTION_DISTRIBUTE_BY_NUM_SECTIONS: float perSectionTouchFraction = 1f / mFastScrollerSections.size(); float cumulativeTouchFraction = 0f; for (FastScrollSectionInfo info : mFastScrollerSections) { AdapterItem item = info.fastScrollToItem; if (item.viewType != AllAppsGridAdapter.ICON_VIEW_TYPE && item.viewType != AllAppsGridAdapter.PREDICTION_ICON_VIEW_TYPE) { info.touchFraction = 0f; continue; } info.touchFraction = cumulativeTouchFraction; cumulativeTouchFraction += perSectionTouchFraction; } break; } } // Refresh the recycler view if (mAdapter != null) { mAdapter.notifyDataSetChanged(); } }