1/*
2 * Copyright (C) 2017 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.settingslib.utils;
18
19import android.content.AsyncTaskLoader;
20import android.content.Context;
21
22/**
23 * This class fills in some boilerplate for AsyncTaskLoader to actually load things.
24 *
25 * Subclasses need to implement {@link AsyncLoader#loadInBackground()} to perform the actual
26 * background task, and {@link AsyncLoader#onDiscardResult(T)} to clean up previously loaded
27 * results.
28 *
29 * This loader is based on the MailAsyncTaskLoader from the AOSP EmailUnified repo.
30 *
31 * @param <T> the data type to be loaded.
32 */
33public abstract class AsyncLoader<T> extends AsyncTaskLoader<T> {
34    private T mResult;
35
36    public AsyncLoader(final Context context) {
37        super(context);
38    }
39
40    @Override
41    protected void onStartLoading() {
42        if (mResult != null) {
43            deliverResult(mResult);
44        }
45
46        if (takeContentChanged() || mResult == null) {
47            forceLoad();
48        }
49    }
50
51    @Override
52    protected void onStopLoading() {
53        cancelLoad();
54    }
55
56    @Override
57    public void deliverResult(final T data) {
58        if (isReset()) {
59            if (data != null) {
60                onDiscardResult(data);
61            }
62            return;
63        }
64
65        final T oldResult = mResult;
66        mResult = data;
67
68        if (isStarted()) {
69            super.deliverResult(data);
70        }
71
72        if (oldResult != null && oldResult != mResult) {
73            onDiscardResult(oldResult);
74        }
75    }
76
77    @Override
78    protected void onReset() {
79        super.onReset();
80
81        onStopLoading();
82
83        if (mResult != null) {
84            onDiscardResult(mResult);
85        }
86        mResult = null;
87    }
88
89    @Override
90    public void onCanceled(final T data) {
91        super.onCanceled(data);
92
93        if (data != null) {
94            onDiscardResult(data);
95        }
96    }
97
98    /**
99     * Called when discarding the load results so subclasses can take care of clean-up or
100     * recycling tasks. This is not called if the same result (by way of pointer equality) is
101     * returned again by a subsequent call to loadInBackground, or if result is null.
102     *
103     * Note that this may be called concurrently with loadInBackground(), and in some circumstances
104     * may be called more than once for a given object.
105     *
106     * @param result The value returned from {@link AsyncLoader#loadInBackground()} which
107     *               is to be discarded.
108     */
109    protected abstract void onDiscardResult(T result);
110}
111