Android Loader(四) 自定义Loader从网络中获取文本数据

来源:互联网 发布:京华科讯软件 编辑:程序博客网 时间:2024/05/29 16:21

Android Loader(三) 结合CursorLoader分析Loader相关源码

根据文档,自定义Loader需要实现的方法有,onStartLoading(),onStopLoading(), onForceLoad(), onReset()。

实现自定义Loader,很少直接继承Loader,可以继承Loader的子类AsyncTaskLoader,AsyncTaskLoader已经帮我们写好了 onForceLoad异步加载数据的逻辑,由于是从网络获取文本数据,采用Http的get协议访问比较合适,由于HttpGET是短连接,所以onStopLoading和onReset可以不用重写,考虑重写onStartLoading的逻辑即可。

加载数据的Loader: NetworkLoader.java

public class NetworkLoader extends AsyncTaskLoader<String> {private String result;public NetworkLoader(Context context) {super(context);}@Overrideprotected void onStartLoading() {super.onStartLoading();if (result != null) {deliverResult(result);} else {forceLoad();}}@Overridepublic String loadInBackground() {String url = "http://gc.ditu.aliyun.com/geocoding?a=苏州市";return doGet(url);}private String doGet(String url) {BufferedReader in = null;try {HttpClient client = new DefaultHttpClient();HttpGet request = new HttpGet(url);HttpResponse response = client.execute(request);in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));StringBuffer sb = new StringBuffer("");String line = "";String NL = System.getProperty("line.separator");while ((line = in.readLine()) != null) {sb.append(line + NL);}in.close();String page = sb.toString();return page;} catch (Exception e) {e.printStackTrace();} finally {if (in != null) {try {in.close();} catch (IOException e) {e.printStackTrace();}}}return url;}}
onStartLoading方法进行判断,如果需要获取的数据已经存在,则直接调用deliverResult,前篇已经分析过,deliverResult会触发onLoadeFinished回调。如果没有数据,则进行异步加载数据过程,forceLoad内部会启动内部的AsyncTask,最终调用loadInBackground,耗时的加载网络数据的操作写在这里就可以。本例是通过一个URL获取一串字符串,这里URL地址找了个公开的测试接口。

再来看使用这个Loader的Fragment:

MsgFragment.java:

public class MsgFragment<T extends String> extends Fragment implementsLoaderManager.LoaderCallbacks<String> {private TextView content; @Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {View v = inflater.inflate(R.layout.main, null);content = (TextView) v.findViewById(R.id.content);return v;}@Overridepublic void onActivityCreated(Bundle savedInstanceState) {super.onActivityCreated(savedInstanceState);getLoaderManager().initLoader(0, null, this);}@Overridepublic Loader<String> onCreateLoader(int id, Bundle args) {return new NetworkLoader(getActivity());}@Overridepublic void onLoadFinished(Loader<String> loader, String data) {content.setText(data);}@Overridepublic void onLoaderReset(Loader<String> loader) {}}
这里在onLoadFinished中处理获取的字符串数据。

接下来就是Activity的代码;

MainActivity.java:

public class MainActivity extends ActionBarActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);FragmentManager fm = getFragmentManager();        if (fm.findFragmentById(android.R.id.content) == null) {            MsgFragment list = new MsgFragment();            fm.beginTransaction().add(android.R.id.content, list).commit();        }}}

布局文件就是一个简单的TextView。

Manifest:

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.example.httploader"    android:versionCode="1"    android:versionName="1.0" >    <uses-sdk        android:minSdkVersion="11"        android:targetSdkVersion="21" />    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>    <application        android:allowBackup="true"        android:icon="@drawable/ic_launcher"        android:label="@string/app_name"        android:theme="@style/AppTheme" >        <activity            android:name=".MainActivity"            android:label="@string/app_name" >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>    </application></manifest>
工程目录:

最终效果:




0 0