Android 3.0 开始提出 Loader 和 LoaderManager 的概念,通过 LoaderManager 类可以很轻松的从 Fragment 或 Activity 中进行异步加载数据。
这和 AsyncTask 很类似,但是 AsyncTask 没有 LoaderManager 的统一管理,并且不方便实现 MVC 的开发模式,对于和 UI 相关的数据加载就不要使用 AsyncTask 使用 Loader 最佳!

官方示例:

当然我们实际开发中,需要自己去实现一个更加酷的 Loader,来满足我们的开发需要。

BaseDataLoader.java – 一个基础 Loader,提取于 AsyncTaskLoader.html 的示例代码,并做了自己的处理。

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
package cn.gavinliu.loader;

import android.content.AsyncTaskLoader;
import android.content.Context;

/**
* 这是一个基础的数据加载Loader
*
* @author Gavinliu
* @param <T>
*
*/
public abstract class BaseDataLoader<T> extends AsyncTaskLoader<T> {

private T mData;

public BaseDataLoader(Context context) {
super(context);
}

/**
* Handles a request to start the Loader.
*/
@Override
protected void onStartLoading() {
if (mData != null) {
// If we currently have a result available, deliver it
// immediately.
deliverResult(mData);
}

registerObserver();

if (takeContentChanged() || mData == null || isConfigChanged()) {
// If the data has changed since the last time it was loaded
// or is not currently available, start a load.
forceLoad();
}
}

/**
* Called when there is new data to deliver to the client. The super class
* will take care of delivering it; the implementation here just adds a
* little more logic.
*/
@Override
public void deliverResult(T data) {
if (isReset()) {
// An async query came in while the loader is stopped. We
// don't need the result.
if (mData != null) {
onReleaseResources(mData);
}
}
T oldApps = mData;
mData = data;

if (isStarted()) {
// If the Loader is currently started, we can immediately
// deliver its results.
super.deliverResult(data);
}

// At this point we can release the resources associated with
// 'oldApps' if needed; now that the new result is delivered we
// know that it is no longer in use.
if (oldApps != null) {
onReleaseResources(oldApps);
}
}

/**
* Handles a request to stop the Loader.
*/
@Override
protected void onStopLoading() {
// Attempt to cancel the current load task if possible.
cancelLoad();
}

/**
* Handles a request to cancel a load.
*/
@Override
public void onCanceled(T data) {
super.onCanceled(data);

// At this point we can release the resources associated with 'apps'
// if needed.
onReleaseResources(data);
}

/**
* Handles a request to completely reset the Loader.
*/
@Override
protected void onReset() {
super.onReset();

// Ensure the loader is stopped
onStopLoading();

// At this point we can release the resources associated with 'apps'
// if needed.
if (mData != null) {
onReleaseResources(mData);
mData = null;
}

unregisterObserver();
}

protected boolean isConfigChanged() {
return false;
}

protected void registerObserver() {
}

protected void unregisterObserver() {
}

protected void onReleaseResources(T mData) {
}

}

MainActivity.java – 使用示例

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
package cn.gavinliu.loader;

import android.app.Activity;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.Context;
import android.content.Loader;
import android.os.Bundle;

public class MainActivity extends Activity implements LoaderCallbacks<String> {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

getLoaderManager().initLoader(0, null, this);

}

@Override
public Loader<String> onCreateLoader(int id, Bundle args) {
System.out.println("onCreateLoader");
mLoader = new MyLoader(getApplicationContext());
return mLoader;
}

@Override
public void onLoadFinished(Loader<String> loader, String data) {
System.out.println("onLoadFinished");
System.out.println("----->" + data);
}

@Override
public void onLoaderReset(Loader<String> loader) {
System.out.println("onLoaderReset");
}

private MyLoader mLoader;

static class MyLoader extends BaseDataLoader<String> {
String mData;

public MyLoader(Context context) {
super(context);
}

@Override
public String loadInBackground() {
System.out.println("LoadInBackground");
return "Load Success";
}

}

}