Loader&AsyncTaskLoader&CursorLoader&CancellationSignal&LoaderManager

Loader

执行异步加载数据的抽象类。当Loaders是激活状态,他们会监视数据源而且当他们的内容发生变化时传递新的结果.在线程上注意:loaders客户端对Loader进行任何调用应该在他们进程中的主线程中(就是说调用者在A线程,处理过程在B线程)。Loader的子类(比如AsyncTaskLoader)通常会在一个单独线程执行任务,但是结果会传递到主线程。子类通常必须至少实现onStartLoading(),onStopLoading(),onForceLoad(),onReset().更多的实现不应该直接继承自该类,而是继承制AsyncTaskLoader

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/**
ContentObserver的一个实现:当observer告诉它内容已经改变的时候,这个类控制链接到Loader来使loader重新加载数据.
一般不需要用这个类;它会被CursorLoader使用:当cursor的返回数据改变的时候来控制执行更新
*/

public final class ForceLoadContentObserver extends ContentObserver {
public ForceLoadContentObserver() {
super(new Handler());
}

@Override
public boolean deliverSelfNotifications() {
return true;
}

@Override
public void onChange(boolean selfChange) {
onContentChanged();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
public interface OnLoadCompleteListener<D> {
public void onLoadComplete(Loader<D> loader, D data);
}

/**
Loaders可以跨多个activities来使用,若以直接存储context比较危险
从getContext方法返回的Context在跨Activity实例之间使用是安全的
*/

public Loader(Context context) {
mContext = context.getApplicationContext();//它是获取了Application context
}

/**
这个方法会在关联到fragment/activity上时由LoaderManager自动调用,当使用一个LoaderManager控制Loader时,你不能调用这个方法,否则会和Loader的管理冲突。
如果之前的加载已经完成而且仍然有效,结果可能立刻传递到回调接口。loader会监视数据源同时提供以后数据源变化的回调
调用stopLoading来停止传递回调
*/

public final void startLoading() {
mStarted = true;
mReset = false;
mAbandoned = false;
onStartLoading();
}

/**
尝试取消当前的加载任务。必须在进程的主线程
取消不是一个立即执行的操作,因为加载是在一个后台线程。如果当前有一个加载,这个方法要求取消加载;一旦后台线程已经完成它的remaining状态会被清除。如果其他load在这个时候要求加载,它会在取消操作完成之前保持阻塞。
当返回true,任务仍然在运行,当任务执行完毕OnLoadCanceledListener会被调用
*/

public boolean cancelLoad() {
return onCancelLoad();
}

/**
强制一个异步加载。和startLoading()不同,这个会忽略之前加载的数据,加载一个新的。
你通常应该只有在isStarted()返回true的时候才调用这个方法
*/

public void forceLoad() {
onForceLoad();
}
/**
这个方法会在取消关联到fragment/activity上时由LoaderManager自动调用,当使用一个LoaderManager控制Loader时,你不能调用这个方法,否则会和Loader的管理冲突
停止传递更新数据直到下一次startLoading被调用。实现应该不使他们的数据在这一点上无效,客户端仍然可以自由的使用loader最后提交的数据。但是如果数据改变他们通常停止提交新的数据;他们还会检测变化,但是一定不能把他们提交到客户端直到startLoading()被调用
*/

public void stopLoading() {
mStarted = false;
onStopLoading();
}

/**
这个方法会在重启一个Loader时由LoaderManager自动调用
这个必须在reset之前调用。来保留当前的数据但是不提交任何新的数据
*/

public void abandon() {
mAbandoned = true;
onAbandon();
}

/**
这个方法会在销毁一个Loader时由LoaderManager自动调用,,当使用一个LoaderManager控制Loader时,你不能调用这个方法,否则会和Loader的管理冲突

重新设置Loader的状态。loader应该在这个点释放所有资源,因为它可能永远不再被调用。但是startLoading()也许会在之后调用在这个点上它必须能够再次启动运行。
*/

public void reset() {
onReset();
mReset = true;
mStarted = false;
mAbandoned = false;
mContentChanged = false;
mProcessingChange = false;
}

/**
* 取当前标志,这个标志表明当loader已经停止的时候loader的内容是否已更改.如果已经更改,返回true同时标志清除。
*/

public boolean takeContentChanged() {
boolean res = mContentChanged;
mContentChanged = false;
mProcessingChange |= res;
return res;
}

/**
保证你实际上已经完全处理了takeContentChanged返回的内容更改。和rollbackContentChanged()一块使用来处理load取消的情形。当你已经完全处理了一个没有取消的load时调用这个方法。
*/

public void commitContentChanged() {
mProcessingChange = false;
}

/**This is
* to handle the case where a data load due to a content change has been
* canceled before its data was delivered back to the loader.
* report你已经放弃处理由takeContentChanged()返回的内容更改并且回滚到一个正在等待的内容更改的状态。这个用来处理当因为内容改变在它的的数据传回loader之前已经取消数据加载的情况
*/

public void rollbackContentChanged() {
if (mProcessingChange) {
mContentChanged = true;
}
}

/**
* 当ForceLoadContentObserver检测到改变的时候调用。默认的实现检查loader当前是否启动;如果是启动状态,仅调用forceLoad();否则的话设置一个标示使takeContentChanged()返回true。

必须从进程的主线程调用。

*/

public void onContentChanged() {
if (mStarted) {
forceLoad();
} else {
// This loader has been stopped, so we don't want to load
// new data right now... but keep track of it changing to
// refresh later if we start again.
// 这个loader已经停止,我们不想立刻加载新数据。。。
mContentChanged = true;
}
}

AsyncTaskLoader

抽象的Loader,提供一个AsyncTask来完成任务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
final class LoadTask extends AsyncTask<Void, Void, D> implements Runnable {
private final CountDownLatch mDone = new CountDownLatch(1);

// 设置为true意味着任务已经提交给handler在晚些时候执行。Used to throttle updates.
boolean waiting;

/* 在一个工作线程运行 */
@Override
protected D doInBackground(Void... params) {
try {
D data = AsyncTaskLoader.this.onLoadInBackground();
return data;
} catch (OperationCanceledException ex) {
if (!isCancelled()) {
// onLoadInBackground抛出一个取消异常。这是有问题的,因为这意味着LoaderManager没有取消Loader而且希望收到结果。
// Loader的状态不会再更新来影响任务被取消的现实。所以按未经处理的异常处理
throw ex;
}
return null;
}
}

/* 在UI线程运行*/
@Override
protected void onPostExecute(D data) {
try {
AsyncTaskLoader.this.dispatchOnLoadComplete(this, data);
} finally {
mDone.countDown();
}
}

/* 在UI线程运行*/
@Override
protected void onCancelled(D data) {
try {
AsyncTaskLoader.this.dispatchOnCancelled(this, data);
} finally {
mDone.countDown();
}
}

/*
当等待的任务提交给一个handler,在UI线程运行
当任务执行被延迟(waiting是true)这个方法才会被调用
*/

@Override
public void run() {
waiting = false;
AsyncTaskLoader.this.executePendingTask();
}

/* 用于测试目的,等待任务完成。*/
public void waitForLoader() {
try {
mDone.await();
} catch (InterruptedException e) {
}
}
}

void executePendingTask() {
if (mCancellingTask == null && mTask != null) {
if (mTask.waiting) {
mTask.waiting = false;
mHandler.removeCallbacks(mTask);
}
if (mUpdateThrottle > 0) {
long now = SystemClock.uptimeMillis();
if (now < (mLastLoadCompleteTime+mUpdateThrottle)) {
// 现在做另外一个加载还不是时候
mTask.waiting = true;
mHandler.postAtTime(mTask, mLastLoadCompleteTime+mUpdateThrottle);
return;
}
}
mTask.executeOnExecutor(mExecutor, (Void[]) null);
}
}

public AsyncTaskLoader(Context context) {
this(context, AsyncTask.THREAD_POOL_EXECUTOR);
}

/** {@hide} */
public AsyncTaskLoader(Context context, Executor executor) {
super(context);
mExecutor = executor;
}
@Override
protected void onForceLoad() {
super.onForceLoad();
cancelLoad();
mTask = new LoadTask();
executePendingTask();
}


@Override
protected boolean onCancelLoad() {
if (mTask != null) {
if (mCancellingTask != null) {
// 有一个准备好的任务已经在等待前一个任务取消;just drop it.
if (DEBUG) Slog.v(TAG,
"cancelLoad: still waiting for cancelled task; dropping next");
if (mTask.waiting) {
mTask.waiting = false;
mHandler.removeCallbacks(mTask);
}
mTask = null;
return false;
} else if (mTask.waiting) {
// 有一个task,但是它正在等待执行,扔掉它。
if (DEBUG) Slog.v(TAG, "cancelLoad: task is waiting, dropping it");
mTask.waiting = false;
mHandler.removeCallbacks(mTask);
mTask = null;
return false;
} else {
boolean cancelled = mTask.cancel(false);
if (cancelled) {
mCancellingTask = mTask;
cancelLoadInBackground();
}
mTask = null;
return cancelled;
}
}
return false;
}


void dispatchOnCancelled(LoadTask task, D data) {
onCanceled(data);
if (mCancellingTask == task) {
rollbackContentChanged();
mLastLoadCompleteTime = SystemClock.uptimeMillis();
mCancellingTask = null;
deliverCancellation();
executePendingTask();
}
}

void dispatchOnLoadComplete(LoadTask task, D data) {
if (mTask != task) {
// 完成旧任务,试着去取消。
dispatchOnCancelled(task, data);
} else {
if (isAbandoned()) {
// 这个cursor已经被放弃;只是取消新的数据
onCanceled(data);
} else {
commitContentChanged();
mLastLoadCompleteTime = SystemClock.uptimeMillis();
mTask = null;
deliverResult(data);
}
}
}


/**
在任务线程被调用执行真正的加载操作并返回加载操作的结果

这个方法的实现不应该直接传递结果,应该从这个方法返回结果这个方法最终结束的时候会在UI线程调用deliverResult。
如果方法的实现需要在UI线程处理结果,应该实现deliverResult。

为了支持取消操作,这个方法应该间断性的检测isLoadInBackgroundCanceled的值并且在它返回的时候中断掉。
子类可以直接通过重写cancelLoadInBackground来中断加载,而不是轮询isLoadInBackgroundCanceled

如果加载取消了,这个方法也许会正常返回也许会抛出OperationCanceledException。不管哪种情况,Loader都会调用onCanceled来执行取消之后的清理操作和处理结果如果有的话。
*/

public abstract D loadInBackground();

/**
这个方法是为加载框架预留的,子类应该重写loadInBackground而不是这个方法
*/

protected D onLoadInBackground() {
return loadInBackground();
}

/**
在主线程调用终止加载过程

重写这个方法来终止当前loadInBackground的调用

这个方法应该在loadInBackground还没开始或者已经结束之后啥都不做。
*/

public void cancelLoadInBackground() {
}

/**
锁定当前线程直到loader完成当前的加载操作。如果没有加载操作在运行会直接返回。
不要在UI线程调用:在UI线程调用会引起死锁
只是用来测试,不要在UI线程调用
* @hide
*/

public void waitForLoader() {
LoadTask task = mTask;
if (task != null) {
task.waitForLoader();
}
}

CursorLoader

查询ContentResolver并返回一个Cursor的loader.这个类通过标准的方式实现Loader协议来查询cursors,建造AsyncTaskLoader在后台线程来执行cursor.一个CursorLoader必须以完整信息构建来执行查询操作,要不然通过CursorLoader(Context, Uri, String[], String, String[], String),要不然通过创建一个空的实例CursorLoader(Context),并且调用setUri,setSelection,setSelectionArgs,setSortOrder,setProjection

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/* 在任务线程运行 */
@Override
public Cursor loadInBackground() {
synchronized (this) {
if (isLoadInBackgroundCanceled()) {
throw new OperationCanceledException();
}
mCancellationSignal = new CancellationSignal();
}
try {
Cursor cursor = getContext().getContentResolver().query(mUri, mProjection, mSelection,
mSelectionArgs, mSortOrder, mCancellationSignal);
if (cursor != null) {
try {
// Ensure the cursor window is filled.
cursor.getCount();
cursor.registerContentObserver(mObserver);
} catch (RuntimeException ex) {
cursor.close();
throw ex;
}
}
return cursor;
} finally {
synchronized (this) {
mCancellationSignal = null;
}
}
}


@Override
public void cancelLoadInBackground() {
super.cancelLoadInBackground();

synchronized (this) {
if (mCancellationSignal != null) {
mCancellationSignal.cancel();
}
}
}

/* UI线程运行 */
@Override
public void deliverResult(Cursor cursor) {
if (isReset()) {
// 当loader停止的时候一个异步查询到来
if (cursor != null) {
cursor.close();
}
return;
}
Cursor oldCursor = mCursor;
mCursor = cursor;

if (isStarted()) {
super.deliverResult(cursor);
}

if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed()) {
oldCursor.close();
}
}

public CursorLoader(Context context) {
super(context);
mObserver = new ForceLoadContentObserver();
}

/**
开始一个异步的加载。当结果准备好,回调接口会在UI线程调用。如果之前的加载已经完成而且仍然有效,结果会立刻传递到回调。
必须在UI线程调用
*/

@Override
protected void onStartLoading() {
if (mCursor != null) {
deliverResult(mCursor);
}
if (takeContentChanged() || mCursor == null) {
forceLoad();
}
}

@Override
protected void onStopLoading() {
// 如果可能尝试取消当前的加载任务。
cancelLoad();
}

@Override
public void onCanceled(Cursor cursor) {
if (cursor != null && !cursor.isClosed()) {
cursor.close();
}
}

@Override
protected void onReset() {
super.onReset();

// 确保加载停止
onStopLoading();

if (mCursor != null && !mCursor.isClosed()) {
mCursor.close();
}
mCursor = null;
}

CancellationSignal

提供在过程中可以取消操作的能力

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
public boolean isCanceled() {
synchronized (this) {
return mIsCanceled;
}
}

public void throwIfCanceled() {
if (isCanceled()) {
throw new OperationCanceledException();
}
}

/**
取消相应操作并且调用取消listener。
如果操作还没开始,它会尽可能早点取消
*/

public void cancel() {
final OnCancelListener listener;
final ICancellationSignal remote;
synchronized (this) {
if (mIsCanceled) {
return;
}
mIsCanceled = true;
mCancelInProgress = true;
listener = mOnCancelListener;
remote = mRemote;
}

try {
if (listener != null) {
listener.onCancel();
}
if (remote != null) {
try {
remote.cancel();
} catch (RemoteException ex) {
}
}
} finally {
synchronized (this) {
mCancelInProgress = false;
notifyAll();
}
}
}

/**
这个方法是用来作为一个cancellation signal的接受者,比如一个数据库或一个content provider在执行一个长时间的操作时,执行取消请求。
这个方法不是给应用程序使用的
如果cancel已经被被调用,提供的listener会立刻被调用
这个方法确保listener在移除之后不被调用
如果传入的listener为null,会移除当前listener
*/

public void setOnCancelListener(OnCancelListener listener) {
synchronized (this) {
waitForCancelFinishedLocked();

if (mOnCancelListener == listener) {
return;
}
mOnCancelListener = listener;
if (!mIsCanceled || listener == null) {
return;
}
}
listener.onCancel();
}

/**
如果cancel已经被调用,提供的远程ICancellationSignal会被立刻调用
* @hide
*/

public void setRemote(ICancellationSignal remote) {
synchronized (this) {
waitForCancelFinishedLocked();

if (mRemote == remote) {
return;
}
mRemote = remote;
if (!mIsCanceled || remote == null) {
return;
}
}
try {
remote.cancel();
} catch (RemoteException ex) {
}
}

private void waitForCancelFinishedLocked() {
while (mCancelInProgress) {
try {
wait();
} catch (InterruptedException ex) {
}
}
}

/**
* Creates a transport that can be returned back to the caller of
* a Binder function and subsequently used to dispatch a cancellation signal.
*
* @hide
*/

public static ICancellationSignal createTransport() {
return new Transport();
}

/**
* Given a locally created transport, returns its associated cancellation signal.
*
* @param transport The locally created transport, or null if none.
* @return The associated cancellation signal, or null if none.
*
* @hide
*/

public static CancellationSignal fromTransport(ICancellationSignal transport) {
if (transport instanceof Transport) {
return ((Transport)transport).mCancellationSignal;
}
return null;
}

/**
* Listens for cancellation.
*/

public interface OnCancelListener {
/**
* Called when {@link CancellationSignal#cancel} is invoked.
*/

void onCancel();
}

private static final class Transport extends ICancellationSignal.Stub {
final CancellationSignal mCancellationSignal = new CancellationSignal();

@Override
public void cancel() throws RemoteException {
mCancellationSignal.cancel();
}
}

LoaderManager

关联一个Activity或Fragment的接口,管理一个或多个关联到本身上的一个或多个Loader实例,这个结合Activity或Fragment的生命周期帮助应用程序管理长时间运行的操作。最常和CursorLoader一块使用,应用程序可以随意写自己的loaders来加载其他类型的数据
  • See the blog post
  • Fragments For All for more details.
    *
  • {@sample development/samples/ApiDemos/src/com/example/android/apis/app/LoaderCursor.java
  • fragment_cursor}
    */
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
/**
和manager相关的客户端回调接口
*/

public interface LoaderCallbacks<D> {
public Loader<D> onCreateLoader(int id, Bundle args);

/** See {@link FragmentManager#beginTransaction()
* FragmentManager.openTransaction()} for further discussion on this.
当之前创建的一个loader已经完成它的加载时调用。注意:正常情况下应用程序不会允许在这个方法提交fragment transactions,因为它有可能在activity状态保存之后发生
* At this point
* you should remove all use of the old data (since it will be released
* soon), but should not do your own release of the data since its Loader
* owns it and will take care of that. The Loader will take care of
* management of its data so you don't have to.
*这个方法确保在这个Loader提供的最后的数据释放之前调用。基于这点你应该删除所有使用的旧数据(因为它会马上被释 放)
但是需要注意
特别的:
Loader会监视数据改变,通过新的调用提交给你。你不应该自己监视数据。比如:如果数据是个Cursor而且把它放到 CursorAdapter中,使用CursorAdapter#CursorAdapter(android.content.Context,
* android.database.Cursor, int)构造,没有传入CursorAdapter#FLAG_AUTO_REQUERY或 CursorAdapter#FLAG_REGISTER_CONTENT_OBSERVER(也就是这个参数传入的是0)。这会防止CursorAdapter监 视Cursor,这是不必要的因为当一个修改发生你会得到一个新的Cursor
* <li>
一旦Loader知道应用程序不再使用数据它就会释放数据。比如,如果数据是CursorLoader的Cursor,你不能调用 close().如果Cursor在CursorLoader中被替换,你应该使用swapCursor(Cursor)来使old Cursor不关闭。
* </ul>
*/

public void onLoadFinished(Loader<D> loader, D data);

/**
*在前一个创建的loader被重置调用,并且使它的数据不可用。应用程序应该在这时候删除它对Loader数据的所有引用
*/

public void onLoaderReset(Loader<D> loader);
}

/**
如果loader已经不再存在,一个新的会被创建而且(如果activity/fragment当前已经开始)启动loader。否则最后创建的loader会被重用。
在任何情况下,给定的回调是和loader相关的,而且会在loader状态改变的时候调用。如果在调用这点上,调用者在开始状态,被requested的loader已经存在而且生成了数据,然后onLoadFinished会被立刻调用(而不是这个方法),所以必须注意这种情况。
*/

public abstract <D> Loader<D> initLoader(int id, Bundle args,
LoaderManager.LoaderCallbacks<D> callback);

/**
在这个manager里启动一个新的或重启一个已经存在的Loader,注册回调,并且(如果activity/fragment当前已经开始)开始启动。
如果之前有相同id的loader已经启动,它会在新的loader完成工作之后自动销毁。
The callback will be delivered before the old loader
* is destroyed.
*/

public abstract <D> Loader<D> restartLoader(int id, Bundle args,
LoaderManager.LoaderCallbacks<D> callback);

/**
停止并移除给定id的loader. 如果loader之前通过#onLoadFinished(Loader, Object)给客户端提交过数据,a call
* will be made to {@link LoaderCallbacks#onLoaderReset(Loader)}.
*/

public abstract void destroyLoader(int id);

public abstract <D> Loader<D> getLoader(int id);


class LoaderManagerImpl extends LoaderManager {
static final String TAG = "LoaderManager";
static boolean DEBUG = false;

// 这些是当前激活的loaders。在这的都是那些从他们开始启动加载到他们被应用程序明确停止或重启
final SparseArray<LoaderInfo> mLoaders = new SparseArray<LoaderInfo>(0);

// 这些是之前运行的loaders.这个列表在内部主要用来避免在一个应用程序仍然使用loader的时候摧毁它。
// 它运行一个应用程序来重启一个loader,但是继续使用它之前运行的loader直到新的loader的数据可用
final SparseArray<LoaderInfo> mInactiveLoaders = new SparseArray<LoaderInfo>(0);

final String mWho;

Activity mActivity;
boolean mStarted;
boolean mRetaining;
boolean mRetainingStarted;

boolean mCreatingLoader;

final class LoaderInfo implements Loader.OnLoadCompleteListener<Object>,
Loader.OnLoadCanceledListener<Object> {
final int mId;
final Bundle mArgs;
LoaderManager.LoaderCallbacks<Object> mCallbacks;
Loader<Object> mLoader;
boolean mHaveData;
boolean mDeliveredData;
Object mData;
boolean mStarted;
boolean mRetaining;
boolean mRetainingStarted;
boolean mReportNextStart;
boolean mDestroyed;
boolean mListenerRegistered;

LoaderInfo mPendingLoader;

public LoaderInfo(int id, Bundle args, LoaderManager.LoaderCallbacks<Object> callbacks) {
mId = id;
mArgs = args;
mCallbacks = callbacks;
}

void start() {
if (mRetaining && mRetainingStarted) {
// Our owner is started, but we were being retained from a
// previous instance in the started state... so there is really
// nothing to do here, since the loaders are still started.
//
mStarted = true;
return;
}

if (mStarted) {
return;
}

mStarted = true;

if (mLoader == null && mCallbacks != null) {
mLoader = mCallbacks.onCreateLoader(mId, mArgs);
}
if (mLoader != null) {
if (mLoader.getClass().isMemberClass()
&& !Modifier.isStatic(mLoader.getClass().getModifiers())) {
throw new IllegalArgumentException(
"Object returned from onCreateLoader must not be a non-static inner member class: "
+ mLoader);
}
if (!mListenerRegistered) {
mLoader.registerListener(mId, this);
mLoader.registerOnLoadCanceledListener(this);
mListenerRegistered = true;
}
mLoader.startLoading();
}
}

void retain() {
mRetaining = true;
mRetainingStarted = mStarted;
mStarted = false;
mCallbacks = null;
}

void finishRetain() {
if (mRetaining) {
mRetaining = false;
if (mStarted != mRetainingStarted) {
if (!mStarted) {
// This loader was retained in a started state, but
// at the end of retaining everything our owner is
// no longer started... so make it stop.
stop();
}
}
}

if (mStarted && mHaveData && !mReportNextStart) {
// This loader has retained its data, either completely across
// a configuration change or just whatever the last data set
// was after being restarted from a stop, and now at the point of
// finishing the retain we find we remain started, have
// our data, and the owner has a new callback... so
// let's deliver the data now.
callOnLoadFinished(mLoader, mData);
}
}

void reportStart() {
if (mStarted) {
if (mReportNextStart) {
mReportNextStart = false;
if (mHaveData) {
callOnLoadFinished(mLoader, mData);
}
}
}
}

void stop() {
if (DEBUG) Log.v(TAG, " Stopping: " + this);
mStarted = false;
if (!mRetaining) {
if (mLoader != null && mListenerRegistered) {
// Let the loader know we're done with it
mListenerRegistered = false;
mLoader.unregisterListener(this);
mLoader.unregisterOnLoadCanceledListener(this);
mLoader.stopLoading();
}
}
}

void cancel() {
if (DEBUG) Log.v(TAG, " Canceling: " + this);
if (mStarted && mLoader != null && mListenerRegistered) {
if (!mLoader.cancelLoad()) {
onLoadCanceled(mLoader);
}
}
}

void destroy() {
if (DEBUG) Log.v(TAG, " Destroying: " + this);
mDestroyed = true;
boolean needReset = mDeliveredData;
mDeliveredData = false;
if (mCallbacks != null && mLoader != null && mHaveData && needReset) {
if (DEBUG) Log.v(TAG, " Reseting: " + this);
String lastBecause = null;
if (mActivity != null) {
lastBecause = mActivity.mFragments.mNoTransactionsBecause;
mActivity.mFragments.mNoTransactionsBecause = "onLoaderReset";
}
try {
mCallbacks.onLoaderReset(mLoader);
} finally {
if (mActivity != null) {
mActivity.mFragments.mNoTransactionsBecause = lastBecause;
}
}
}
mCallbacks = null;
mData = null;
mHaveData = false;
if (mLoader != null) {
if (mListenerRegistered) {
mListenerRegistered = false;
mLoader.unregisterListener(this);
mLoader.unregisterOnLoadCanceledListener(this);
}
mLoader.reset();
}
if (mPendingLoader != null) {
mPendingLoader.destroy();
}
}

@Override
public void onLoadCanceled(Loader<Object> loader) {
if (DEBUG) Log.v(TAG, "onLoadCanceled: " + this);

if (mDestroyed) {
if (DEBUG) Log.v(TAG, " Ignoring load canceled -- destroyed");
return;
}

if (mLoaders.get(mId) != this) {
// This cancellation message is not coming from the current active loader.
// We don't care about it.
if (DEBUG) Log.v(TAG, " Ignoring load canceled -- not active");
return;
}

LoaderInfo pending = mPendingLoader;
if (pending != null) {
// There is a new request pending and we were just
// waiting for the old one to cancel or complete before starting
// it. So now it is time, switch over to the new loader.
if (DEBUG) Log.v(TAG, " Switching to pending loader: " + pending);
mPendingLoader = null;
mLoaders.put(mId, null);
destroy();
installLoader(pending);
}
}

@Override
public void onLoadComplete(Loader<Object> loader, Object data) {
if (DEBUG) Log.v(TAG, "onLoadComplete: " + this);

if (mDestroyed) {
if (DEBUG) Log.v(TAG, " Ignoring load complete -- destroyed");
return;
}

if (mLoaders.get(mId) != this) {
// This data is not coming from the current active loader.
// We don't care about it.
if (DEBUG) Log.v(TAG, " Ignoring load complete -- not active");
return;
}

LoaderInfo pending = mPendingLoader;
if (pending != null) {
// There is a new request pending and we were just
// waiting for the old one to complete before starting
// it. So now it is time, switch over to the new loader.
if (DEBUG) Log.v(TAG, " Switching to pending loader: " + pending);
mPendingLoader = null;
mLoaders.put(mId, null);
destroy();
installLoader(pending);
return;
}

// Notify of the new data so the app can switch out the old data before
// we try to destroy it.
if (mData != data || !mHaveData) {
mData = data;
mHaveData = true;
if (mStarted) {
callOnLoadFinished(loader, data);
}
}

//if (DEBUG) Log.v(TAG, " onLoadFinished returned: " + this);

// We have now given the application the new loader with its
// loaded data, so it should have stopped using the previous
// loader. If there is a previous loader on the inactive list,
// clean it up.
LoaderInfo info = mInactiveLoaders.get(mId);
if (info != null && info != this) {
info.mDeliveredData = false;
info.destroy();
mInactiveLoaders.remove(mId);
}

if (mActivity != null && !hasRunningLoaders()) {
mActivity.mFragments.startPendingDeferredFragments();
}
}

void callOnLoadFinished(Loader<Object> loader, Object data) {
if (mCallbacks != null) {
String lastBecause = null;
if (mActivity != null) {
lastBecause = mActivity.mFragments.mNoTransactionsBecause;
mActivity.mFragments.mNoTransactionsBecause = "onLoadFinished";
}
try {
if (DEBUG) Log.v(TAG, " onLoadFinished in " + loader + ": "
+ loader.dataToString(data));
mCallbacks.onLoadFinished(loader, data);
} finally {
if (mActivity != null) {
mActivity.mFragments.mNoTransactionsBecause = lastBecause;
}
}
mDeliveredData = true;
}
}
}

LoaderManagerImpl(String who, Activity activity, boolean started) {
mWho = who;
mActivity = activity;
mStarted = started;
}

void updateActivity(Activity activity) {
mActivity = activity;
}

private LoaderInfo createLoader(int id, Bundle args,
LoaderManager.LoaderCallbacks<Object> callback) {
LoaderInfo info = new LoaderInfo(id, args, (LoaderManager.LoaderCallbacks<Object>)callback);
Loader<Object> loader = callback.onCreateLoader(id, args);
info.mLoader = (Loader<Object>)loader;
return info;
}

private LoaderInfo createAndInstallLoader(int id, Bundle args,
LoaderManager.LoaderCallbacks<Object> callback) {
try {
mCreatingLoader = true;
LoaderInfo info = createLoader(id, args, callback);
installLoader(info);
return info;
} finally {
mCreatingLoader = false;
}
}

void installLoader(LoaderInfo info) {
mLoaders.put(info.mId, info);
if (mStarted) {
// The activity will start all existing loaders in it's onStart(),
// so only start them here if we're past that point of the activitiy's
// life cycle
info.start();
}
}

/**
用一个特殊的ID初始化一个Loader,如果这个ID已经有Loader和它相关联,那么它保持不变而且任何之前的回调都被新的替换。如果没有和ID相关联的Loader,会产生一个新的并且启动。
这个方法通常在一个组件初始化的时候使用来确保它依赖的Loader被创建。这样如果已经有一个,会使它重用一个已经存在的Loader的数据。比如当一个Activity在configuration改变之后re-created,它就不必再re-create它的loaders.
注意:在这种情况下如果一个存在的Loader已经被使用,那么给定的args会被忽略,因为你会继续使用之前的Loader
*/

@SuppressWarnings("unchecked")
public <D> Loader<D> initLoader(int id, Bundle args, LoaderManager.LoaderCallbacks<D> callback) {
if (mCreatingLoader) {
throw new IllegalStateException("Called while creating a loader");
}

LoaderInfo info = mLoaders.get(id);

if (info == null) {
// Loader不存在,创建
info = createAndInstallLoader(id, args, (LoaderManager.LoaderCallbacks<Object>)callback);
} else {
// 重用存在的Loader
info.mCallbacks = (LoaderManager.LoaderCallbacks<Object>)callback;
}

if (info.mHaveData && mStarted) {
// 如果loader已经生产数据,现在提交
info.callOnLoadFinished(info.mLoader, info.mData);
}

return (Loader<D>)info.mLoader;
}

/**
调用来重建有特殊ID的Loader.如果当前有一个和这个Id相关联的Loader,它会在适当的时候canceled/stopped/destroyed。一个新的带有给定参数的Loader会被创建,然后它的数据会在可用的时候传给你。
这个方法减少了一些Loaders的生成。如果太多的相同ID的Loaders被创建,但是没有生成他们的数据,那么这个方法会被重新调用而且返回一个新的Loader,但是直到之前的Loader全部完成才会启动。
调用这个方法之后,任何之前相同ID的Loaders都变无效的,而且不应该再接受他们的更新数据。
*/

@SuppressWarnings("unchecked")
public <D> Loader<D> restartLoader(int id, Bundle args, LoaderManager.LoaderCallbacks<D> callback) {
if (mCreatingLoader) {
throw new IllegalStateException("Called while creating a loader");
}

LoaderInfo info = mLoaders.get(id);
if (info != null) {
LoaderInfo inactive = mInactiveLoaders.get(id);
if (inactive != null) {
if (info.mHaveData) {
// 这个loader现在有数据... we are probably being
// called from within onLoadComplete, where we haven't
// yet destroyed the last inactive loader. So just do
// that now.
inactive.mDeliveredData = false;
inactive.destroy();
info.mLoader.abandon();
mInactiveLoaders.put(id, info);
} else {
// We already have an inactive loader for this ID that we are
// waiting for! What to do, what to do...
if (!info.mStarted) {
// The current Loader has not been started... we thus
// have no reason to keep it around, so bam, slam,
// thank-you-ma'am.
if (DEBUG) Log.v(TAG, " Current loader is stopped; replacing");
mLoaders.put(id, null);
info.destroy();
} else {
// Now we have three active loaders... we'll queue
// up this request to be processed once one of the other loaders
// finishes or is canceled.
if (DEBUG) Log.v(TAG, " Current loader is running; attempting to cancel");
info.cancel();
if (info.mPendingLoader != null) {
if (DEBUG) Log.v(TAG, " Removing pending loader: " + info.mPendingLoader);
info.mPendingLoader.destroy();
info.mPendingLoader = null;
}
if (DEBUG) Log.v(TAG, " Enqueuing as new pending loader");
info.mPendingLoader = createLoader(id, args,
(LoaderManager.LoaderCallbacks<Object>)callback);
return (Loader<D>)info.mPendingLoader.mLoader;
}
}
} else {
// Keep track of the previous instance of this loader so we can destroy
// it when the new one completes.
if (DEBUG) Log.v(TAG, " Making last loader inactive: " + info);
info.mLoader.abandon();
mInactiveLoaders.put(id, info);
}
}

info = createAndInstallLoader(id, args, (LoaderManager.LoaderCallbacks<Object>)callback);
return (Loader<D>)info.mLoader;
}

/**
销毁给定ID的loader,在这个方法返回之后,任何和这个ID相关联的Loader对象都会被销毁。任何和他们相关联的数据都会被销毁。当你这样做时,你最好不要使用它。
*/

public void destroyLoader(int id) {
if (mCreatingLoader) {
throw new IllegalStateException("Called while creating a loader");
}

int idx = mLoaders.indexOfKey(id);
if (idx >= 0) {
LoaderInfo info = mLoaders.valueAt(idx);
mLoaders.removeAt(idx);
info.destroy();
}
idx = mInactiveLoaders.indexOfKey(id);
if (idx >= 0) {
LoaderInfo info = mInactiveLoaders.valueAt(idx);
mInactiveLoaders.removeAt(idx);
info.destroy();
}
if (mActivity != null && !hasRunningLoaders()) {
mActivity.mFragments.startPendingDeferredFragments();
}
}

/**
返回最近和给定ID相关联的Loader对象。
*/

@SuppressWarnings("unchecked")
public <D> Loader<D> getLoader(int id) {
if (mCreatingLoader) {
throw new IllegalStateException("Called while creating a loader");
}

LoaderInfo loaderInfo = mLoaders.get(id);
if (loaderInfo != null) {
if (loaderInfo.mPendingLoader != null) {
return (Loader<D>)loaderInfo.mPendingLoader.mLoader;
}
return (Loader<D>)loaderInfo.mLoader;
}
return null;
}

void doStart() {
if (mStarted) {
RuntimeException e = new RuntimeException("here");
e.fillInStackTrace();
return;
}

mStarted = true;

// Call out to sub classes so they can start their loaders
// Let the existing loaders know that we want to be notified when a load is complete
for (int i = mLoaders.size()-1; i >= 0; i--) {
mLoaders.valueAt(i).start();
}
}

void doStop() {
if (!mStarted) {
RuntimeException e = new RuntimeException("here");
e.fillInStackTrace();
return;
}

for (int i = mLoaders.size()-1; i >= 0; i--) {
mLoaders.valueAt(i).stop();
}
mStarted = false;
}

void doRetain() {
if (!mStarted) {
RuntimeException e = new RuntimeException("here");
e.fillInStackTrace();
return;
}

mRetaining = true;
mStarted = false;
for (int i = mLoaders.size()-1; i >= 0; i--) {
mLoaders.valueAt(i).retain();
}
}

void finishRetain() {
if (mRetaining) {

mRetaining = false;
for (int i = mLoaders.size()-1; i >= 0; i--) {
mLoaders.valueAt(i).finishRetain();
}
}
}

void doReportNextStart() {
for (int i = mLoaders.size()-1; i >= 0; i--) {
mLoaders.valueAt(i).mReportNextStart = true;
}
}

void doReportStart() {
for (int i = mLoaders.size()-1; i >= 0; i--) {
mLoaders.valueAt(i).reportStart();
}
}

void doDestroy() {
if (!mRetaining) {
for (int i = mLoaders.size()-1; i >= 0; i--) {
mLoaders.valueAt(i).destroy();
}
mLoaders.clear();
}

for (int i = mInactiveLoaders.size()-1; i >= 0; i--) {
mInactiveLoaders.valueAt(i).destroy();
}
mInactiveLoaders.clear();
}


public boolean hasRunningLoaders() {
boolean loadersRunning = false;
final int count = mLoaders.size();
for (int i = 0; i < count; i++) {
final LoaderInfo li = mLoaders.valueAt(i);
loadersRunning |= li.mStarted && !li.mDeliveredData;
}
return loadersRunning;
}
}

Activity中LoaderManager使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
ArrayMap<String, LoaderManagerImpl> mAllLoaderManagers;


public LoaderManager getLoaderManager() {
if (mLoaderManager != null) {
return mLoaderManager;
}
mCheckedForLoaderManager = true;
mLoaderManager = getLoaderManager("(root)", mLoadersStarted, true);
return mLoaderManager;
}

LoaderManagerImpl getLoaderManager(String who, boolean started, boolean create) {
if (mAllLoaderManagers == null) {
mAllLoaderManagers = new ArrayMap<String, LoaderManagerImpl>();
}
LoaderManagerImpl lm = mAllLoaderManagers.get(who);
if (lm == null) {
if (create) {
lm = new LoaderManagerImpl(who, this, started);
mAllLoaderManagers.put(who, lm);
}
} else {
lm.updateActivity(this);
}
return lm;
}

static final class NonConfigurationInstances {
Object activity;
HashMap<String, Object> children;
ArrayList<Fragment> fragments;
ArrayMap<String, LoaderManagerImpl> loaders;
}

NonConfigurationInstances mLastNonConfigurationInstances;

protected void onCreate(Bundle savedInstanceState) {
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onCreate " + this + ": " + savedInstanceState);
if (mLastNonConfigurationInstances != null) {
mAllLoaderManagers = mLastNonConfigurationInstances.loaders;
}
//...其他一些与mLoaderManager无关的代码
}

protected void onStart() {
//...其他一些与mLoaderManager无关的代码

if (!mLoadersStarted) {
mLoadersStarted = true;
if (mLoaderManager != null) {
mLoaderManager.doStart();
} else if (!mCheckedForLoaderManager) {
mLoaderManager = getLoaderManager("(root)", mLoadersStarted, false);
}
mCheckedForLoaderManager = true;
}

//...其他一些与mLoaderManager无关的代码
}

NonConfigurationInstances retainNonConfigurationInstances() {
//...其他一些与mLoaderManager无关的代码
if (mAllLoaderManagers != null) {
// prune out any loader managers that were already stopped and so
// have nothing useful to retain.
final int N = mAllLoaderManagers.size();
LoaderManagerImpl loaders[] = new LoaderManagerImpl[N];
for (int i=N-1; i>=0; i--) {
loaders[i] = mAllLoaderManagers.valueAt(i);
}
for (int i=0; i<N; i++) {
LoaderManagerImpl lm = loaders[i];
if (lm.mRetaining) {
retainLoaders = true;
} else {
lm.doDestroy();
mAllLoaderManagers.remove(lm.mWho);
}
}
}

//...其他一些与mLoaderManager无关的代码

NonConfigurationInstances nci = new NonConfigurationInstances();

//...其他一些与mLoaderManager无关的代码

nci.loaders = mAllLoaderManagers;
return nci;
}

final void performStart() {
//...其他一些与mLoaderManager无关的代码
if (mAllLoaderManagers != null) {
final int N = mAllLoaderManagers.size();
LoaderManagerImpl loaders[] = new LoaderManagerImpl[N];
for (int i=N-1; i>=0; i--) {
loaders[i] = mAllLoaderManagers.valueAt(i);
}
for (int i=0; i<N; i++) {
LoaderManagerImpl lm = loaders[i];
lm.finishRetain();
lm.doReportStart();
}
}
}

final void performStop() {
//...其他一些与mLoaderManager无关的代码
if (mLoadersStarted) {
//...其他一些与mLoaderManager无关的代码
if (mLoaderManager != null) {
if (!mChangingConfigurations) {
mLoaderManager.doStop();
} else {
mLoaderManager.doRetain();
}
}
}

//...其他一些与mLoaderManager无关的代码
}

final void performDestroy() {

//...其他一些与mLoaderManager无关的代码

if (mLoaderManager != null) {
mLoaderManager.doDestroy();
}
}

final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config)
{


//...其他一些与NonConfigurationInstances无关的代码

mLastNonConfigurationInstances = lastNonConfigurationInstances;

//...其他一些与NonConfigurationInstances无关的代码
}

final void performResume() {
performRestart();

//...其他一些与NonConfigurationInstances无关的代码

mLastNonConfigurationInstances = null;

//...其他一些与NonConfigurationInstances无关的代码

onPostResume();

//...其他一些与NonConfigurationInstances无关的代码
}