From 085fba050aad5f4b639b5a33dadc99e8e8974747 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Sun, 23 Jul 2017 18:32:52 +0800 Subject: [PATCH] Introduce self-written SectionedAdapter --- .../magisk/adapters/ReposAdapter.java | 204 ++++++++---------- .../magisk/adapters/SectionedAdapter.java | 78 +++++++ 2 files changed, 169 insertions(+), 113 deletions(-) create mode 100644 app/src/main/java/com/topjohnwu/magisk/adapters/SectionedAdapter.java diff --git a/app/src/main/java/com/topjohnwu/magisk/adapters/ReposAdapter.java b/app/src/main/java/com/topjohnwu/magisk/adapters/ReposAdapter.java index fc03e2a52..f47249977 100644 --- a/app/src/main/java/com/topjohnwu/magisk/adapters/ReposAdapter.java +++ b/app/src/main/java/com/topjohnwu/magisk/adapters/ReposAdapter.java @@ -6,6 +6,7 @@ import android.database.Cursor; import android.net.Uri; import android.support.v7.widget.RecyclerView; import android.text.TextUtils; +import android.util.Pair; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -30,116 +31,103 @@ import java.util.Map; import butterknife.BindView; import butterknife.ButterKnife; -public class ReposAdapter extends RecyclerView.Adapter { +public class ReposAdapter extends SectionedAdapter { - private static final int SECTION_TYPE = 0; - private static final int REPO_TYPE = 1; + private static final int UPDATES = 0; + private static final int INSTALLED = 1; + private static final int OTHERS = 2; - private List mUpdateRepos, mInstalledRepos, mOthersRepos; - private int[] sectionList; - private int size; private Cursor repoCursor = null; private Map moduleMap; private RepoDatabaseHelper repoDB; + private List>> repoPairs; public ReposAdapter(RepoDatabaseHelper db, Map map) { repoDB = db; moduleMap = map; - mUpdateRepos = new ArrayList<>(); - mInstalledRepos = new ArrayList<>(); - mOthersRepos = new ArrayList<>(); - sectionList = new int[3]; - size = 0; + repoPairs = new ArrayList<>(); + } + + + @Override + public int getSectionCount() { + return repoPairs.size(); } @Override - public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - Context context = parent.getContext(); - View v; - RecyclerView.ViewHolder holder = null; - switch (viewType) { - case SECTION_TYPE: - v = LayoutInflater.from(context).inflate(R.layout.section, parent, false); - holder = new SectionHolder(v); + public int getItemCount(int section) { + return repoPairs.get(section).second.size(); + } + + @Override + public SectionHolder onCreateSectionViewHolder(ViewGroup parent) { + View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.section, parent, false); + return new SectionHolder(v); + } + + @Override + public RepoHolder onCreateItemViewHolder(ViewGroup parent, int viewType) { + View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_repo, parent, false); + return new RepoHolder(v); + } + + @Override + public void onBindSectionViewHolder(SectionHolder holder, int section) { + switch (repoPairs.get(section).first) { + case UPDATES: + holder.sectionText.setText(R.string.update_available); break; - case REPO_TYPE: - v = LayoutInflater.from(context).inflate(R.layout.list_item_repo, parent, false); - holder = new RepoHolder(v); + case INSTALLED: + holder.sectionText.setText(R.string.installed); + break; + case OTHERS: + holder.sectionText.setText(R.string.not_installed); break; } - return holder; } @Override - public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + public void onBindItemViewHolder(RepoHolder holder, int section, int position) { + Repo repo = repoPairs.get(section).second.get(position); Context context = holder.itemView.getContext(); - switch (getItemViewType(position)) { - case SECTION_TYPE: - SectionHolder section = (SectionHolder) holder; - if (position == sectionList[0]) { - section.sectionText.setText(context.getString(R.string.update_available)); - } else if (position == sectionList[1]) { - section.sectionText.setText(context.getString(R.string.installed)); - } else { - section.sectionText.setText(context.getString(R.string.not_installed)); - } - break; - case REPO_TYPE: - RepoHolder repoHolder = (RepoHolder) holder; - Repo repo = getRepo(position); - repoHolder.title.setText(repo.getName()); - repoHolder.versionName.setText(repo.getVersion()); - String author = repo.getAuthor(); - repoHolder.author.setText(TextUtils.isEmpty(author) ? null : context.getString(R.string.author, author)); - repoHolder.description.setText(repo.getDescription()); - repoHolder.infoLayout.setOnClickListener(v -> new MarkDownWindow(null, repo.getDetailUrl(), context)); + holder.title.setText(repo.getName()); + holder.versionName.setText(repo.getVersion()); + String author = repo.getAuthor(); + holder.author.setText(TextUtils.isEmpty(author) ? null : context.getString(R.string.author, author)); + holder.description.setText(repo.getDescription()); - repoHolder.downloadImage.setOnClickListener(v -> { - String filename = repo.getName() + "-" + repo.getVersion() + ".zip"; - new AlertDialogBuilder(context) - .setTitle(context.getString(R.string.repo_install_title, repo.getName())) - .setMessage(context.getString(R.string.repo_install_msg, filename)) - .setCancelable(true) - .setPositiveButton(R.string.install, (d, i) -> Utils.dlAndReceive( - context, - new DownloadReceiver() { - @Override - public void onDownloadDone(Uri uri) { - new ProcessRepoZip((Activity) context, uri, true).exec(); - } - }, - repo.getZipUrl(), - Utils.getLegalFilename(filename))) - .setNeutralButton(R.string.download, (d, i) -> Utils.dlAndReceive( - context, - new DownloadReceiver() { - @Override - public void onDownloadDone(Uri uri) { - new ProcessRepoZip((Activity) context, uri, false).exec(); - } - }, - repo.getZipUrl(), - Utils.getLegalFilename(filename))) - .setNegativeButton(R.string.no_thanks, null) - .show(); - }); - break; - } - } + holder.infoLayout.setOnClickListener(v -> new MarkDownWindow(null, repo.getDetailUrl(), context)); - @Override - public int getItemViewType(int position) { - for (int i : sectionList) { - if (position == i) - return SECTION_TYPE; - } - return REPO_TYPE; - } - - @Override - public int getItemCount() { - return size; + holder.downloadImage.setOnClickListener(v -> { + String filename = repo.getName() + "-" + repo.getVersion() + ".zip"; + new AlertDialogBuilder(context) + .setTitle(context.getString(R.string.repo_install_title, repo.getName())) + .setMessage(context.getString(R.string.repo_install_msg, filename)) + .setCancelable(true) + .setPositiveButton(R.string.install, (d, i) -> Utils.dlAndReceive( + context, + new DownloadReceiver() { + @Override + public void onDownloadDone(Uri uri) { + new ProcessRepoZip((Activity) context, uri, true).exec(); + } + }, + repo.getZipUrl(), + Utils.getLegalFilename(filename))) + .setNeutralButton(R.string.download, (d, i) -> Utils.dlAndReceive( + context, + new DownloadReceiver() { + @Override + public void onDownloadDone(Uri uri) { + new ProcessRepoZip((Activity) context, uri, false).exec(); + } + }, + repo.getZipUrl(), + Utils.getLegalFilename(filename))) + .setNegativeButton(R.string.no_thanks, null) + .show(); + }); } public void notifyDBChanged() { @@ -150,53 +138,43 @@ public class ReposAdapter extends RecyclerView.Adapter } public void filter(String s) { - mUpdateRepos.clear(); - mInstalledRepos.clear(); - mOthersRepos.clear(); - sectionList[0] = sectionList[1] = sectionList[2] = 0; + List updates = new ArrayList<>(); + List installed = new ArrayList<>(); + List others = new ArrayList<>(); + + repoPairs.clear(); while (repoCursor.moveToNext()) { Repo repo = new Repo(repoCursor); if (repo.getName().toLowerCase().contains(s.toLowerCase()) || repo.getAuthor().toLowerCase().contains(s.toLowerCase()) || repo.getDescription().toLowerCase().contains(s.toLowerCase()) ) { - // Passed the filter + // Passed the repoFilter Module module = moduleMap.get(repo.getId()); if (module != null) { if (repo.getVersionCode() > module.getVersionCode()) { // Updates - mUpdateRepos.add(repo); + updates.add(repo); } else { - mInstalledRepos.add(repo); + installed.add(repo); } } else { - mOthersRepos.add(repo); + others.add(repo); } } } repoCursor.moveToFirst(); - sectionList[0] = mUpdateRepos.isEmpty() ? -1 : 0; - size = mUpdateRepos.isEmpty() ? 0 : mUpdateRepos.size() + 1; - sectionList[1] = mInstalledRepos.isEmpty() ? -1 : size; - size += mInstalledRepos.isEmpty() ? 0 : mInstalledRepos.size() + 1; - sectionList[2] = mOthersRepos.isEmpty() ? -1 : size; - size += mOthersRepos.isEmpty() ? 0 : mOthersRepos.size() + 1; + if (!updates.isEmpty()) + repoPairs.add(new Pair<>(UPDATES, updates)); + if (!installed.isEmpty()) + repoPairs.add(new Pair<>(INSTALLED, installed)); + if (!others.isEmpty()) + repoPairs.add(new Pair<>(OTHERS, others)); notifyDataSetChanged(); } - private Repo getRepo(int position) { - if (!mUpdateRepos.isEmpty()) position -= 1; - if (position < mUpdateRepos.size()) return mUpdateRepos.get(position); - position -= mUpdateRepos.size(); - if (!mInstalledRepos.isEmpty()) position -= 1; - if (position < mInstalledRepos.size()) return mInstalledRepos.get(position); - position -= mInstalledRepos.size(); - if (!mOthersRepos.isEmpty()) position -= 1; - return mOthersRepos.get(position); - } - static class SectionHolder extends RecyclerView.ViewHolder { @BindView(R.id.section_text) TextView sectionText; diff --git a/app/src/main/java/com/topjohnwu/magisk/adapters/SectionedAdapter.java b/app/src/main/java/com/topjohnwu/magisk/adapters/SectionedAdapter.java new file mode 100644 index 000000000..c73ff5f2f --- /dev/null +++ b/app/src/main/java/com/topjohnwu/magisk/adapters/SectionedAdapter.java @@ -0,0 +1,78 @@ +package com.topjohnwu.magisk.adapters; + +import android.support.v7.widget.RecyclerView; +import android.view.ViewGroup; + +public abstract class SectionedAdapter + extends RecyclerView.Adapter { + + private static final int SECTION_TYPE = Integer.MIN_VALUE; + + @Override + final public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + if (viewType == SECTION_TYPE) + return onCreateSectionViewHolder(parent); + return onCreateItemViewHolder(parent, viewType); + } + + @Override + @SuppressWarnings("unchecked") + final public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + PositionInfo info = getPositionInfo(position); + if (info.position == -1) + onBindSectionViewHolder((S) holder, info.section); + else + onBindItemViewHolder((C) holder, info.section, info.position); + } + + @Override + final public int getItemCount() { + int size, sec; + size = sec = getSectionCount(); + for (int i = 0; i < sec; ++i){ + size += getItemCount(i); + } + return size; + } + + @Override + final public int getItemViewType(int position) { + PositionInfo info = getPositionInfo(position); + if (info.position == -1) + return SECTION_TYPE; + else + return getItemViewType(info.section, info.position); + } + + public int getItemViewType(int section, int position) { + return 0; + } + + private PositionInfo getPositionInfo(int position) { + int section = 0; + while (true) { + if (position == 0) + return new PositionInfo(section, -1); + position -= 1; + if (position < getItemCount(section)) + return new PositionInfo(section, position); + position -= getItemCount(section++); + } + } + + private static class PositionInfo { + int section; + int position; + PositionInfo(int section, int position) { + this.section = section; + this.position = position; + } + } + + public abstract int getSectionCount(); + public abstract int getItemCount(int section); + public abstract S onCreateSectionViewHolder(ViewGroup parent); + public abstract C onCreateItemViewHolder(ViewGroup parent, int viewType); + public abstract void onBindSectionViewHolder(S holder, int section); + public abstract void onBindItemViewHolder(C holder, int section, int position); +}