blob: 7bb662c72cf5d04232e01379439aed0b5c66a172 [file] [log] [blame]
Jeff Sharkeya5defe32013-08-05 17:56:48 -07001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.documentsui;
18
19import android.content.AsyncTaskLoader;
20import android.content.Context;
21import android.database.ContentObserver;
Jeff Sharkeya5defe32013-08-05 17:56:48 -070022import android.os.CancellationSignal;
23import android.os.OperationCanceledException;
24
25/**
26 * Loader that derives its data from a Uri. Watches for {@link ContentObserver}
27 * changes while started, manages {@link CancellationSignal}, and caches
28 * returned results.
29 */
Steve McKayfefcd702015-08-20 16:19:38 +000030public abstract class UriDerivativeLoader<Param, Res> extends AsyncTaskLoader<Res> {
Jeff Sharkey46899c82013-08-18 22:26:48 -070031 final ForceLoadContentObserver mObserver;
Jeff Sharkeya5defe32013-08-05 17:56:48 -070032
Steve McKayfefcd702015-08-20 16:19:38 +000033 private final Param mParam;
Jeff Sharkeya5defe32013-08-05 17:56:48 -070034
Steve McKayfefcd702015-08-20 16:19:38 +000035 private Res mResult;
Jeff Sharkeya5defe32013-08-05 17:56:48 -070036 private CancellationSignal mCancellationSignal;
37
38 @Override
Steve McKayfefcd702015-08-20 16:19:38 +000039 public final Res loadInBackground() {
Jeff Sharkeya5defe32013-08-05 17:56:48 -070040 synchronized (this) {
41 if (isLoadInBackgroundCanceled()) {
42 throw new OperationCanceledException();
43 }
44 mCancellationSignal = new CancellationSignal();
45 }
46 try {
Jeff Sharkey46899c82013-08-18 22:26:48 -070047 return loadInBackground(mParam, mCancellationSignal);
Jeff Sharkeya5defe32013-08-05 17:56:48 -070048 } finally {
49 synchronized (this) {
50 mCancellationSignal = null;
51 }
52 }
53 }
54
Steve McKayfefcd702015-08-20 16:19:38 +000055 public abstract Res loadInBackground(Param param, CancellationSignal signal);
Jeff Sharkeya5defe32013-08-05 17:56:48 -070056
57 @Override
58 public void cancelLoadInBackground() {
59 super.cancelLoadInBackground();
60
61 synchronized (this) {
62 if (mCancellationSignal != null) {
63 mCancellationSignal.cancel();
64 }
65 }
66 }
67
68 @Override
Steve McKayfefcd702015-08-20 16:19:38 +000069 public void deliverResult(Res result) {
Jeff Sharkeya5defe32013-08-05 17:56:48 -070070 if (isReset()) {
71 closeQuietly(result);
72 return;
73 }
Steve McKayfefcd702015-08-20 16:19:38 +000074 Res oldResult = mResult;
Jeff Sharkeya5defe32013-08-05 17:56:48 -070075 mResult = result;
76
77 if (isStarted()) {
78 super.deliverResult(result);
79 }
80
81 if (oldResult != null && oldResult != result) {
82 closeQuietly(oldResult);
83 }
84 }
85
Steve McKayfefcd702015-08-20 16:19:38 +000086 public UriDerivativeLoader(Context context, Param param) {
Jeff Sharkeya5defe32013-08-05 17:56:48 -070087 super(context);
88 mObserver = new ForceLoadContentObserver();
Jeff Sharkey46899c82013-08-18 22:26:48 -070089 mParam = param;
Jeff Sharkeya5defe32013-08-05 17:56:48 -070090 }
91
92 @Override
93 protected void onStartLoading() {
Jeff Sharkeya5defe32013-08-05 17:56:48 -070094 if (mResult != null) {
95 deliverResult(mResult);
96 }
97 if (takeContentChanged() || mResult == null) {
98 forceLoad();
99 }
100 }
101
102 @Override
103 protected void onStopLoading() {
104 cancelLoad();
105 }
106
107 @Override
Steve McKayfefcd702015-08-20 16:19:38 +0000108 public void onCanceled(Res result) {
Jeff Sharkeya5defe32013-08-05 17:56:48 -0700109 closeQuietly(result);
110 }
111
112 @Override
113 protected void onReset() {
114 super.onReset();
115
116 // Ensure the loader is stopped
117 onStopLoading();
118
119 closeQuietly(mResult);
120 mResult = null;
121
Jeff Sharkey46899c82013-08-18 22:26:48 -0700122 getContext().getContentResolver().unregisterContentObserver(mObserver);
Jeff Sharkeya5defe32013-08-05 17:56:48 -0700123 }
124
Steve McKayfefcd702015-08-20 16:19:38 +0000125 private void closeQuietly(Res result) {
Jeff Sharkeya5defe32013-08-05 17:56:48 -0700126 if (result instanceof AutoCloseable) {
127 try {
128 ((AutoCloseable) result).close();
129 } catch (RuntimeException rethrown) {
130 throw rethrown;
131 } catch (Exception ignored) {
132 }
133 }
134 }
135}