1/*
2 * Copyright (C) 2016 Google Inc.
3 * Licensed to The Android Open Source Project.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18package com.android.storagemanager.utils;
19
20import android.content.AsyncTaskLoader;
21import android.content.Context;
22
23/**
24 * This class fills in some boilerplate for AsyncTaskLoader to actually load things.
25 *
26 * Subclasses need to implement {@link AsyncLoader#loadInBackground()} to perform the actual
27 * background task, and {@link AsyncLoader#onDiscardResult(T)} to clean up previously loaded
28 * results.
29 *
30 * This loader is based on the MailAsyncTaskLoader from the AOSP EmailUnified repo.
31 */
32public abstract class AsyncLoader<T> extends AsyncTaskLoader<T> {
33    private T mResult;
34
35    public AsyncLoader(final Context context) {
36        super(context);
37    }
38
39    @Override
40    protected void onStartLoading() {
41        if (mResult != null) {
42            deliverResult(mResult);
43        }
44
45        if (takeContentChanged() || mResult == null) {
46            forceLoad();
47        }
48    }
49
50    @Override
51    protected void onStopLoading() {
52        cancelLoad();
53    }
54
55    @Override
56    public void deliverResult(final T data) {
57        if (isReset()) {
58            if (data != null) {
59                onDiscardResult(data);
60            }
61            return;
62        }
63
64        final T oldResult = mResult;
65        mResult = data;
66
67        if (isStarted()) {
68            super.deliverResult(data);
69        }
70
71        if (oldResult != null && oldResult != mResult) {
72            onDiscardResult(oldResult);
73        }
74    }
75
76    @Override
77    protected void onReset() {
78        super.onReset();
79
80        onStopLoading();
81
82        if (mResult != null) {
83            onDiscardResult(mResult);
84        }
85        mResult = null;
86    }
87
88    @Override
89    public void onCanceled(final T data) {
90        super.onCanceled(data);
91
92        if (data != null) {
93            onDiscardResult(data);
94        }
95    }
96
97    /**
98     * Called when discarding the load results so subclasses can take care of clean-up or
99     * recycling tasks. This is not called if the same result (by way of pointer equality) is
100     * returned again by a subsequent call to loadInBackground, or if result is null.
101     *
102     * Note that this may be called concurrently with loadInBackground(), and in some circumstances
103     * may be called more than once for a given object.
104     *
105     * @param result The value returned from {@link AsyncLoader#loadInBackground()} which
106     *               is to be discarded.
107     */
108    protected abstract void onDiscardResult(final T result);
109}
110