Restore more missing DirectoryFragment functionality.
- Add a material-style horizontal progress bar to DocumentsUI. This
replaces the old loading footer.
- Restore the view-switching code that displayed a dedicated "empty"
view when displaying an empty directory.
- Fix tests.
Change-Id: Ifecb867f6edecbdeb37b8607d87d9797879a589d
diff --git a/src/com/android/documentsui/DirectoryFragment.java b/src/com/android/documentsui/DirectoryFragment.java
index c2821e1..b30cab6 100644
--- a/src/com/android/documentsui/DirectoryFragment.java
+++ b/src/com/android/documentsui/DirectoryFragment.java
@@ -135,6 +135,7 @@
private static final String EXTRA_IGNORE_STATE = "ignoreState";
private Model mModel;
+ private Model.UpdateListener mModelUpdateListener = new ModelUpdateListener();
private final Handler mHandler = new Handler(Looper.getMainLooper());
@@ -160,6 +161,7 @@
private int mColumnCount = 1; // This will get updated when layout changes.
private MessageBar mMessageBar;
+ private View mProgressBar;
public static void showNormal(FragmentManager fm, RootInfo root, DocumentInfo doc, int anim) {
show(fm, TYPE_NORMAL, root, doc, null, anim);
@@ -223,6 +225,7 @@
final View view = inflater.inflate(R.layout.fragment_directory, container, false);
mMessageBar = MessageBar.create(getChildFragmentManager());
+ mProgressBar = view.findViewById(R.id.progressbar);
mEmptyView = view.findViewById(android.R.id.empty);
@@ -311,9 +314,8 @@
: MultiSelectManager.MODE_SINGLE);
selMgr.addCallback(new SelectionModeListener());
- mModel = new Model(context, selMgr);
- mModel.setSelectionManager(selMgr);
- mModel.addUpdateListener(mAdapter);
+ mModel = new Model(context, selMgr, mAdapter);
+ mModel.addUpdateListener(mModelUpdateListener);
mType = getArguments().getInt(EXTRA_TYPE);
mStateKey = buildStateKey(root, doc);
@@ -897,8 +899,7 @@
}
}
- private final class DocumentsAdapter extends RecyclerView.Adapter<DocumentHolder>
- implements Model.UpdateListener {
+ private final class DocumentsAdapter extends RecyclerView.Adapter<DocumentHolder> {
private final Context mContext;
private final LayoutInflater mInflater;
@@ -909,30 +910,6 @@
}
@Override
- public void onModelUpdate(Model model) {
- if (model.info != null || model.error != null) {
- mMessageBar.setInfo(model.info);
- mMessageBar.setError(model.error);
- mMessageBar.show();
- }
-
- if (model.isEmpty()) {
- mEmptyView.setVisibility(View.VISIBLE);
- } else {
- mEmptyView.setVisibility(View.GONE);
- }
-
- notifyDataSetChanged();
- }
-
- @Override
- public void onModelUpdateFailed(Exception e) {
- // TODO: deal with catastrophic update failures
- String error = getString(R.string.query_error);
- notifyDataSetChanged();
- }
-
- @Override
public DocumentHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final State state = getDisplayState(DirectoryFragment.this);
final LayoutInflater inflater = LayoutInflater.from(getContext());
@@ -1675,6 +1652,7 @@
@VisibleForTesting
public static final class Model implements DocumentContext {
private MultiSelectManager mSelectionManager;
+ private RecyclerView.Adapter<?> mViewAdapter;
private Context mContext;
private int mCursorCount;
private boolean mIsLoading;
@@ -1684,17 +1662,11 @@
@Nullable private String info;
@Nullable private String error;
- Model(Context context, MultiSelectManager selectionManager) {
+ Model(Context context, MultiSelectManager selectionManager,
+ RecyclerView.Adapter<?> viewAdapter) {
mContext = context;
mSelectionManager = selectionManager;
- }
-
- /**
- * Sets the selection manager used by the model.
- * TODO: the model should instantiate the selection manager. See onActivityCreated.
- */
- void setSelectionManager(MultiSelectManager mgr) {
- mSelectionManager = mgr;
+ mViewAdapter = viewAdapter;
}
/**
@@ -1859,7 +1831,7 @@
int position = selected.get(i);
if (DEBUG) Log.d(TAG, "Marked position " + position + " for deletion");
mMarkedForDeletion.append(position, true);
- mUpdateListener.notifyItemRemoved(position);
+ mViewAdapter.notifyItemRemoved(position);
}
}
@@ -1874,7 +1846,7 @@
for (int i = 0; i < size; ++i) {
final int position = mMarkedForDeletion.keyAt(i);
mMarkedForDeletion.put(position, false);
- mUpdateListener.notifyItemInserted(position);
+ mViewAdapter.notifyItemInserted(position);
}
// Then, clear the deletion list.
@@ -1957,26 +1929,46 @@
mUpdateListener = listener;
}
- interface UpdateListener {
+ static class UpdateListener {
/**
* Called when a successful update has occurred.
*/
- void onModelUpdate(Model model);
+ void onModelUpdate(Model model) {}
/**
* Called when an update has been attempted but failed.
*/
- void onModelUpdateFailed(Exception e);
+ void onModelUpdateFailed(Exception e) {}
+ }
+ }
- /**
- * Called when an item has been removed from the model.
- */
- void notifyItemRemoved(int position);
+ private class ModelUpdateListener extends Model.UpdateListener {
+ @Override
+ public void onModelUpdate(Model model) {
+ if (model.info != null || model.error != null) {
+ mMessageBar.setInfo(model.info);
+ mMessageBar.setError(model.error);
+ mMessageBar.show();
+ }
- /**
- * Called when an item has been added to the model.
- */
- void notifyItemInserted(int position);
+ mProgressBar.setVisibility(model.isLoading() ? View.VISIBLE : View.GONE);
+
+ if (model.isEmpty()) {
+ mEmptyView.setVisibility(View.VISIBLE);
+ mRecView.setVisibility(View.GONE);
+ } else {
+ mEmptyView.setVisibility(View.GONE);
+ mRecView.setVisibility(View.VISIBLE);
+ }
+
+ mAdapter.notifyDataSetChanged();
+ }
+
+ @Override
+ public void onModelUpdateFailed(Exception e) {
+ // TODO: deal with catastrophic update failures
+ String error = getString(R.string.query_error);
+ mAdapter.notifyDataSetChanged();
}
}
}