diff options
author | 2016-11-16 18:56:19 +0000 | |
---|---|---|
committer | 2016-11-16 18:56:19 +0000 | |
commit | bf01dcab88930b75f6c0f2387cdbb8f934bf5bf6 (patch) | |
tree | 4761138d6f8dc30d93cf23ced601c96e90c5755a | |
parent | 5bd7d1cb05657b9b8f48c17416c372d05f4348c5 (diff) | |
parent | bbb7d0352dba6cc45696799a5d1a819eb17cd3d4 (diff) |
Merge "Integration ContentResolver#refresh into RefreshLayout." into nyc-andromeda-dev
-rw-r--r-- | src/com/android/documentsui/RefreshTask.java | 103 | ||||
-rw-r--r-- | src/com/android/documentsui/TimeoutTask.java | 4 | ||||
-rw-r--r-- | src/com/android/documentsui/dirlist/DirectoryFragment.java | 29 |
3 files changed, 130 insertions, 6 deletions
diff --git a/src/com/android/documentsui/RefreshTask.java b/src/com/android/documentsui/RefreshTask.java new file mode 100644 index 000000000..252197616 --- /dev/null +++ b/src/com/android/documentsui/RefreshTask.java @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2016 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.documentsui; + +import static com.android.documentsui.base.Shared.DEBUG; + +import android.annotation.Nullable; +import android.app.Activity; +import android.app.Fragment; +import android.content.ContentProviderClient; +import android.content.ContentResolver; +import android.content.Context; +import android.net.Uri; +import android.os.CancellationSignal; +import android.util.Log; + +import com.android.documentsui.TimeoutTask; +import com.android.documentsui.base.CheckedTask; +import com.android.documentsui.base.State; +import com.android.documentsui.dirlist.Model; + +import java.util.function.Consumer; + +/** + * A {@link CheckedTask} that calls + * {@link ContentResolver#refresh(Uri, android.os.Bundle, android.os.CancellationSignal)} on the + * current directory, and then calls the supplied callback with the refresh return value. + */ +public class RefreshTask extends TimeoutTask<Void, Boolean> { + + private final static String TAG = "RefreshTask"; + + private final Context mContext; + private final State mState; + private final Consumer<Boolean> mCallback; + private final CancellationSignal mSignal; + + + public RefreshTask(State state, Activity activity, Consumer<Boolean> callback) { + this(state, activity, activity::isDestroyed, callback); + } + + public RefreshTask(State state, Fragment fragment, Consumer<Boolean> callback) { + this(state, fragment.getContext(), fragment::isDetached, callback); + } + + public RefreshTask(State state, Context context, Check check, Consumer<Boolean> callback) { + super(check); + mContext = context.getApplicationContext(); + mState = state; + mCallback = callback; + mSignal = new CancellationSignal(); + } + + @Override + public @Nullable Boolean run(Void... params) { + final Uri uri = mState.stack.peek().derivedUri; + final ContentResolver resolver = mContext.getContentResolver(); + final String authority = uri.getAuthority(); + boolean refreshed = false; + ContentProviderClient client = null; + try { + client = DocumentsApplication.acquireUnstableProviderOrThrow(resolver, authority); + refreshed = client.refresh(uri, null, mSignal); + } catch (Exception e) { + Log.w(TAG, "Failed to refresh", e); + } finally { + ContentProviderClient.releaseQuietly(client); + } + return refreshed; + } + + @Override + protected void onTimeout() { + mSignal.cancel(); + } + + @Override + public void finish(Boolean refreshed) { + if (DEBUG) { + if (refreshed) { + Log.v(TAG, "Provider has new content and has refreshed"); + } else { + Log.v(TAG, "Provider has no new content and did not refresh"); + } + } + mCallback.accept(refreshed); + } +} diff --git a/src/com/android/documentsui/TimeoutTask.java b/src/com/android/documentsui/TimeoutTask.java index 1d36b48b2..ffa4da624 100644 --- a/src/com/android/documentsui/TimeoutTask.java +++ b/src/com/android/documentsui/TimeoutTask.java @@ -51,10 +51,14 @@ public abstract class TimeoutTask<Input, Output> extends CheckedTask<Input, Outp Handler handler = new Handler(); handler.postDelayed(() -> { if (getStatus() == AsyncTask.Status.RUNNING) { + onTimeout(); cancel(true); this.finish(null); } }, mTimeout); } + // Override this do more proper clean up in case of timeout, such as using + // CancellationSignal#cancel. + protected void onTimeout() { } } diff --git a/src/com/android/documentsui/dirlist/DirectoryFragment.java b/src/com/android/documentsui/dirlist/DirectoryFragment.java index 4e04ef85f..c1bd936f8 100644 --- a/src/com/android/documentsui/dirlist/DirectoryFragment.java +++ b/src/com/android/documentsui/dirlist/DirectoryFragment.java @@ -16,6 +16,7 @@ package com.android.documentsui.dirlist; +import static android.content.ContentResolver.EXTRA_REFRESH_SUPPORTED; import static com.android.documentsui.base.DocumentInfo.getCursorInt; import static com.android.documentsui.base.DocumentInfo.getCursorString; import static com.android.documentsui.base.Shared.DEBUG; @@ -42,6 +43,7 @@ import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Handler; +import android.os.Looper; import android.os.Parcelable; import android.provider.DocumentsContract; import android.provider.DocumentsContract.Document; @@ -82,6 +84,7 @@ import com.android.documentsui.MessageBar; import com.android.documentsui.Metrics; import com.android.documentsui.R; import com.android.documentsui.RecentsLoader; +import com.android.documentsui.RefreshTask; import com.android.documentsui.ThumbnailCache; import com.android.documentsui.base.DocumentInfo; import com.android.documentsui.base.EventHandler; @@ -145,7 +148,7 @@ public class DirectoryFragment extends Fragment private static final int LOADER_ID = 42; private static final int CACHE_EVICT_LIMIT = 100; - private static final int REFRESH_SPINNER_DISMISS_DELAY = 500; + private static final int REFRESH_SPINNER_TIMEOUT = 500; private BaseActivity mActivity; @@ -1142,8 +1145,18 @@ public class DirectoryFragment extends Fragment cache.removeUri(mModel.getItemUri(ids[i])); } - // Trigger loading - getLoaderManager().restartLoader(LOADER_ID, null, mLoaderCallbacks); + if (Shared.ENABLE_OMC_API_FEATURES) { + RefreshTask refreshTask = new RefreshTask(mState, this, + (Boolean refreshed) -> { + new Handler(Looper.getMainLooper()) + .post(() -> mRefreshLayout.setRefreshing(false)); + }); + refreshTask.setTimeout(REFRESH_SPINNER_TIMEOUT); + refreshTask.executeOnExecutor(mActivity.getExecutorForCurrentDirectory()); + } else { + // If Refresh API isn't available, we will explicitly reload the loader + getLoaderManager().restartLoader(LOADER_ID, null, mLoaderCallbacks); + } } private final class ModelUpdateListener implements EventListener<Model.Update> { @@ -1286,6 +1299,8 @@ public class DirectoryFragment extends Fragment mAdapter.notifyDataSetChanged(); mModel.update(result); + mRefreshLayout.setEnabled( + result.cursor.getExtras().getBoolean(EXTRA_REFRESH_SUPPORTED, false)); updateLayout(mState.derivedMode); @@ -1316,10 +1331,10 @@ public class DirectoryFragment extends Fragment mLocalState.mLastSortDimensionId = curSortedDimension.getId(); mLocalState.mLastSortDirection = curSortedDimension.getSortDirection(); - if (mRefreshLayout.isRefreshing()) { + if (!Shared.ENABLE_OMC_API_FEATURES && mRefreshLayout.isRefreshing()) { new Handler().postDelayed( () -> mRefreshLayout.setRefreshing(false), - REFRESH_SPINNER_DISMISS_DELAY); + REFRESH_SPINNER_TIMEOUT); } } @@ -1329,7 +1344,9 @@ public class DirectoryFragment extends Fragment + DocumentInfo.debugString(mLocalState.mDocument)); mModel.onLoaderReset(); - mRefreshLayout.setRefreshing(false); + if (!Shared.ENABLE_OMC_API_FEATURES) { + mRefreshLayout.setRefreshing(false); + } } } } |