Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14792 manas 1
/**
2
 * Copyright 2010-present Facebook.
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
 
17
package com.facebook.widget;
18
 
19
import android.content.Context;
20
import android.os.Handler;
21
import android.support.v4.content.Loader;
22
import com.facebook.*;
23
import com.facebook.internal.CacheableRequestBatch;
24
import com.facebook.model.GraphObject;
25
import com.facebook.model.GraphObjectList;
26
 
27
class GraphObjectPagingLoader<T extends GraphObject> extends Loader<SimpleGraphObjectCursor<T>> {
28
    private final Class<T> graphObjectClass;
29
    private boolean skipRoundtripIfCached;
30
    private Request originalRequest;
31
    private Request currentRequest;
32
    private Request nextRequest;
33
    private OnErrorListener onErrorListener;
34
    private SimpleGraphObjectCursor<T> cursor;
35
    private boolean appendResults = false;
36
    private boolean loading = false;
37
 
38
    public interface OnErrorListener {
39
        public void onError(FacebookException error, GraphObjectPagingLoader<?> loader);
40
    }
41
 
42
    public GraphObjectPagingLoader(Context context, Class<T> graphObjectClass) {
43
        super(context);
44
 
45
        this.graphObjectClass = graphObjectClass;
46
    }
47
 
48
    public OnErrorListener getOnErrorListener() {
49
        return onErrorListener;
50
    }
51
 
52
    public void setOnErrorListener(OnErrorListener listener) {
53
        this.onErrorListener = listener;
54
    }
55
 
56
    public SimpleGraphObjectCursor<T> getCursor() {
57
        return cursor;
58
    }
59
 
60
    public void clearResults() {
61
        nextRequest = null;
62
        originalRequest = null;
63
        currentRequest = null;
64
 
65
        deliverResult(null);
66
    }
67
 
68
    public boolean isLoading() {
69
        return loading;
70
    }
71
 
72
    public void startLoading(Request request, boolean skipRoundtripIfCached) {
73
        originalRequest = request;
74
        startLoading(request, skipRoundtripIfCached, 0);
75
    }
76
 
77
    public void refreshOriginalRequest(long afterDelay) {
78
        if (originalRequest == null) {
79
            throw new FacebookException(
80
                    "refreshOriginalRequest may not be called until after startLoading has been called.");
81
        }
82
        startLoading(originalRequest, false, afterDelay);
83
    }
84
 
85
    public void followNextLink() {
86
        if (nextRequest != null) {
87
            appendResults = true;
88
            currentRequest = nextRequest;
89
 
90
            currentRequest.setCallback(new Request.Callback() {
91
                @Override
92
                public void onCompleted(Response response) {
93
                    requestCompleted(response);
94
                }
95
            });
96
 
97
            loading = true;
98
            CacheableRequestBatch batch = putRequestIntoBatch(currentRequest, skipRoundtripIfCached);
99
            Request.executeBatchAsync(batch);
100
        }
101
    }
102
 
103
    @Override
104
    public void deliverResult(SimpleGraphObjectCursor<T> cursor) {
105
        SimpleGraphObjectCursor<T> oldCursor = this.cursor;
106
        this.cursor = cursor;
107
 
108
        if (isStarted()) {
109
            super.deliverResult(cursor);
110
 
111
            if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed()) {
112
                oldCursor.close();
113
            }
114
        }
115
    }
116
 
117
    @Override
118
    protected void onStartLoading() {
119
        super.onStartLoading();
120
 
121
        if (cursor != null) {
122
            deliverResult(cursor);
123
        }
124
    }
125
 
126
    private void startLoading(Request request, boolean skipRoundtripIfCached, long afterDelay) {
127
        this.skipRoundtripIfCached = skipRoundtripIfCached;
128
        appendResults = false;
129
        nextRequest = null;
130
        currentRequest = request;
131
        currentRequest.setCallback(new Request.Callback() {
132
            @Override
133
            public void onCompleted(Response response) {
134
                requestCompleted(response);
135
            }
136
        });
137
 
138
        // We are considered loading even if we have a delay.
139
        loading = true;
140
 
141
        final RequestBatch batch = putRequestIntoBatch(request, skipRoundtripIfCached);
142
        Runnable r = new Runnable() {
143
            @Override
144
            public void run() {
145
                Request.executeBatchAsync(batch);
146
            }
147
        };
148
        if (afterDelay == 0) {
149
            r.run();
150
        } else {
151
            Handler handler = new Handler();
152
            handler.postDelayed(r, afterDelay);
153
        }
154
    }
155
 
156
    private CacheableRequestBatch putRequestIntoBatch(Request request, boolean skipRoundtripIfCached) {
157
        // We just use the request URL as the cache key.
158
        CacheableRequestBatch batch = new CacheableRequestBatch(request);
159
        // We use the default cache key (request URL).
160
        batch.setForceRoundTrip(!skipRoundtripIfCached);
161
        return batch;
162
    }
163
 
164
    private void requestCompleted(Response response) {
165
        Request request = response.getRequest();
166
        if (request != currentRequest) {
167
            return;
168
        }
169
 
170
        loading = false;
171
        currentRequest = null;
172
 
173
        FacebookRequestError requestError = response.getError();
174
        FacebookException exception = (requestError == null) ? null : requestError.getException();
175
        if (response.getGraphObject() == null && exception == null) {
176
            exception = new FacebookException("GraphObjectPagingLoader received neither a result nor an error.");
177
        }
178
 
179
        if (exception != null) {
180
            nextRequest = null;
181
 
182
            if (onErrorListener != null) {
183
                onErrorListener.onError(exception, this);
184
            }
185
        } else {
186
            addResults(response);
187
        }
188
    }
189
 
190
    private void addResults(Response response) {
191
        SimpleGraphObjectCursor<T> cursorToModify = (cursor == null || !appendResults) ? new SimpleGraphObjectCursor<T>() :
192
                new SimpleGraphObjectCursor<T>(cursor);
193
 
194
        PagedResults result = response.getGraphObjectAs(PagedResults.class);
195
        boolean fromCache = response.getIsFromCache();
196
 
197
        GraphObjectList<T> data = result.getData().castToListOf(graphObjectClass);
198
        boolean haveData = data.size() > 0;
199
 
200
        if (haveData) {
201
            nextRequest = response.getRequestForPagedResults(Response.PagingDirection.NEXT);
202
 
203
            cursorToModify.addGraphObjects(data, fromCache);
204
            if (nextRequest != null) {
205
                cursorToModify.setMoreObjectsAvailable(true);
206
            } else {
207
                cursorToModify.setMoreObjectsAvailable(false);
208
            }
209
        }
210
 
211
        if (!haveData) {
212
            cursorToModify.setMoreObjectsAvailable(false);
213
            cursorToModify.setFromCache(fromCache);
214
 
215
            nextRequest = null;
216
        }
217
 
218
        // Once we get any set of results NOT from the cache, stop trying to get any future ones
219
        // from it.
220
        if (!fromCache) {
221
            skipRoundtripIfCached = false;
222
        }
223
 
224
        deliverResult(cursorToModify);
225
    }
226
 
227
    interface PagedResults extends GraphObject {
228
        GraphObjectList<GraphObject> getData();
229
    }
230
}