diff --git a/app/src/main/java/org/fdroid/fdroid/views/categories/CategoryAdapter.java b/app/src/main/java/org/fdroid/fdroid/views/categories/CategoryAdapter.java index cf7f4b017..deb484acd 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/categories/CategoryAdapter.java +++ b/app/src/main/java/org/fdroid/fdroid/views/categories/CategoryAdapter.java @@ -1,17 +1,21 @@ package org.fdroid.fdroid.views.categories; import android.app.Activity; -import android.database.Cursor; +import android.support.annotation.NonNull; import android.support.v4.app.LoaderManager; import android.support.v7.widget.RecyclerView; import android.view.ViewGroup; import org.fdroid.fdroid.R; -import org.fdroid.fdroid.data.Schema; + +import java.util.Collections; +import java.util.List; public class CategoryAdapter extends RecyclerView.Adapter { - private Cursor cursor; + @NonNull + private List unlocalizedCategoryNames = Collections.emptyList(); + private final Activity activity; private final LoaderManager loaderManager; @@ -27,17 +31,16 @@ public class CategoryAdapter extends RecyclerView.Adapter { @Override public void onBindViewHolder(CategoryController holder, int position) { - cursor.moveToPosition(position); - holder.bindModel(cursor.getString(cursor.getColumnIndex(Schema.CategoryTable.Cols.NAME))); + holder.bindModel(unlocalizedCategoryNames.get(position)); } @Override public int getItemCount() { - return cursor == null ? 0 : cursor.getCount(); + return unlocalizedCategoryNames.size(); } - public void setCategoriesCursor(Cursor cursor) { - this.cursor = cursor; + public void setCategories(@NonNull List unlocalizedCategoryNames) { + this.unlocalizedCategoryNames = unlocalizedCategoryNames; notifyDataSetChanged(); } diff --git a/app/src/main/java/org/fdroid/fdroid/views/categories/CategoryController.java b/app/src/main/java/org/fdroid/fdroid/views/categories/CategoryController.java index dc83000e4..7184066dd 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/categories/CategoryController.java +++ b/app/src/main/java/org/fdroid/fdroid/views/categories/CategoryController.java @@ -75,11 +75,15 @@ public class CategoryController extends RecyclerView.ViewHolder implements Loade .build(); } + public static String translateCategory(Context context, String categoryName) { + int categoryNameId = getCategoryResource(context, categoryName, "string", false); + return categoryNameId == 0 ? categoryName : context.getString(categoryNameId); + } + void bindModel(@NonNull String categoryName) { currentCategory = categoryName; - int categoryNameId = getCategoryResource(activity, categoryName, "string", false); - String translatedName = categoryNameId == 0 ? categoryName : activity.getString(categoryNameId); + String translatedName = translateCategory(activity, categoryName); heading.setText(translatedName); heading.setContentDescription(activity.getString(R.string.tts_category_name, translatedName)); diff --git a/app/src/main/java/org/fdroid/fdroid/views/main/CategoriesViewBinder.java b/app/src/main/java/org/fdroid/fdroid/views/main/CategoriesViewBinder.java index 462cf096b..4c7402ea7 100644 --- a/app/src/main/java/org/fdroid/fdroid/views/main/CategoriesViewBinder.java +++ b/app/src/main/java/org/fdroid/fdroid/views/main/CategoriesViewBinder.java @@ -19,6 +19,12 @@ import org.fdroid.fdroid.data.CategoryProvider; import org.fdroid.fdroid.data.Schema; import org.fdroid.fdroid.views.apps.AppListActivity; import org.fdroid.fdroid.views.categories.CategoryAdapter; +import org.fdroid.fdroid.views.categories.CategoryController; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; /** * Responsible for ensuring that the categories view is inflated and then populated correctly. @@ -75,13 +81,38 @@ class CategoriesViewBinder implements LoaderManager.LoaderCallbacks { ); } + /** + * Reads all categories from the cursor and stores them in memory to provide to the {@link CategoryAdapter}. + * + * It does this so it is easier to deal with localized/unlocalized categories without having + * to store the localized version in the database. It is not expected that the list of categories + * will grow so large as to make this a performance concern. If it does in the future, the + * {@link CategoryAdapter} can be reverted to wrap the cursor again, and localized category + * names can be stored in the database (allowing sorting in their localized form). + */ @Override public void onLoadFinished(Loader loader, Cursor cursor) { - if (loader.getId() != LOADER_ID) { + if (loader.getId() != LOADER_ID || cursor == null) { return; } - categoryAdapter.setCategoriesCursor(cursor); + List categoryNames = new ArrayList<>(cursor.getCount()); + cursor.moveToFirst(); + while (!cursor.isAfterLast()) { + categoryNames.add(cursor.getString(cursor.getColumnIndex(Schema.CategoryTable.Cols.NAME))); + cursor.moveToNext(); + } + + Collections.sort(categoryNames, new Comparator() { + @Override + public int compare(String categoryOne, String categoryTwo) { + String localizedCategoryOne = CategoryController.translateCategory(activity, categoryOne); + String localizedCategoryTwo = CategoryController.translateCategory(activity, categoryTwo); + return localizedCategoryOne.compareTo(localizedCategoryTwo); + } + }); + + categoryAdapter.setCategories(categoryNames); if (categoryAdapter.getItemCount() == 0) { emptyState.setVisibility(View.VISIBLE); @@ -90,6 +121,8 @@ class CategoriesViewBinder implements LoaderManager.LoaderCallbacks { emptyState.setVisibility(View.GONE); categoriesList.setVisibility(View.VISIBLE); } + + cursor.close(); } @Override @@ -98,7 +131,7 @@ class CategoriesViewBinder implements LoaderManager.LoaderCallbacks { return; } - categoryAdapter.setCategoriesCursor(null); + categoryAdapter.setCategories(Collections.emptyList()); } }