android点滴(17)之Loader

Android数据加载详解:利用Loader实现异步数据加载
本文深入解析了Android中Loader的使用方法,详细介绍了Loader的特性和应用实例,包括如何在Activity或Fragment中实现异步数据加载,以及如何使用Loader Manager进行生命周期管理。通过具体代码示例,展示了如何创建和初始化Loader,以及如何在数据变化时更新UI。本文旨在帮助开发者更好地理解和掌握Loader这一强大的异步数据加载机制。

Introduced in Android 3.0, loaders make it easy to asynchronously load data in an activity or fragment. Loaders have these characteristics:

  • They are available to every Activity and Fragment.
  • They provide asynchronous loading of data.
  • They monitor the source of their data and deliver new results when the content changes.
  • They automatically reconnect to the last loader's cursor when being recreated after a configuration change. Thus, they don't need to re-query their data

Loader API Summary

There are multiple classes and interfaces that may be involved in using loaders in an application. They are summarized in this table:

Class/InterfaceDescription
LoaderManagerAn abstract class associated with an Activity or Fragment for managing one or moreLoader instances. This helps an application manage longer-running operations in conjunction with the Activity or Fragment lifecycle; the most common use of this is with aCursorLoader, however applications are free to write their own loaders for loading other types of data. 

There is only one LoaderManager per activity or fragment. But a LoaderManager can have multiple loaders.
LoaderManager.LoaderCallbacksA callback interface for a client to interact with the LoaderManager. For example, you use the onCreateLoader() callback method to create a new loader.
LoaderAn abstract class that performs asynchronous loading of data. This is the base class for a loader. You would typically use CursorLoader, but you can implement your own subclass. While loaders are active they should monitor the source of their data and deliver new results when the contents change.
AsyncTaskLoaderAbstract loader that provides an AsyncTask to do the work.
CursorLoaderA subclass of AsyncTaskLoader that queries the ContentResolver and returns a Cursor. This class implements the Loader protocol in a standard way for querying cursors, building on AsyncTaskLoader to perform the cursor query on a background thread so that it does not block the application's UI. Using this loader is the best way to asynchronously load data from a ContentProvider, instead of performing a managed query through the fragment or activity's APIs.

The classes and interfaces in the above table are the essential components you'll use to implement a loader in your application. You won't need all of them for each loader you create, but you'll always need a reference to the LoaderManager in order to initialize a loader and an implementation of a Loader class such as CursorLoader. The following sections show you how to use these classes and interfaces in an application. 

 

package com.api.loader.activity;

import android.app.Activity;
import android.app.FragmentManager;
import android.app.ListFragment;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.CursorLoader;
import android.content.Loader;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract.Contacts;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.SearchView;
import android.widget.SimpleCursorAdapter;

public class MyLoaderActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//        setContentView(R.layout.main);
        
        FragmentManager fm = getFragmentManager();
        
        if (fm.findFragmentById(android.R.id.content) == null) {
            CursorLoaderListFragment list = new CursorLoaderListFragment();
            fm.beginTransaction().add(android.R.id.content, list).commit();
        }
        
    }
    
    public static class CursorLoaderListFragment extends ListFragment implements
        LoaderCallbacks<Cursor>,SearchView.OnQueryTextListener{

        // These are the Contacts rows that we will retrieve.
        static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {
            Contacts._ID,
            Contacts.DISPLAY_NAME,
            Contacts.CONTACT_STATUS,
            Contacts.CONTACT_PRESENCE,
            Contacts.PHOTO_ID,
            Contacts.LOOKUP_KEY,
        };

        
        SimpleCursorAdapter adapter = null;
        private String mCurFilter = null;
        
        @Override
        public void onActivityCreated(Bundle savedInstanceState) {
            
            super.onActivityCreated(savedInstanceState);
            
            setEmptyText("There is no data here!");
            
            setHasOptionsMenu(true);

            adapter = new SimpleCursorAdapter(getActivity(),
                    android.R.layout.simple_list_item_2, nullnew String[] {
                            Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS },
                    new int[] { android.R.id.text1, android.R.id.text2 });
            
            setListAdapter(adapter);
            
            setListShown(false);
            
            getLoaderManager().initLoader(0, nullthis);
        }
        
        @Override
        public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
            MenuItem item = menu.add("Search");
            item.setIcon(android.R.drawable.ic_menu_search);
            item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
            SearchView sv = new SearchView(getActivity());
            sv.setOnQueryTextListener(this);
            item.setActionView(sv);            
            super.onCreateOptionsMenu(menu, inflater);
        }
        
        @Override
        public Loader<Cursor> onCreateLoader(int id, Bundle args) {
            Uri baseUri;
            if (mCurFilter != null) {
                baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
                        Uri.encode(mCurFilter));
            } else {
                baseUri = Contacts.CONTENT_URI;
            }

            // Now create and return a CursorLoader that will take care of
            
// creating a Cursor for the data being displayed.
            String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND ("
                    + Contacts.HAS_PHONE_NUMBER + "=1) AND ("
                    + Contacts.DISPLAY_NAME + " != '' ))";
            return new CursorLoader(getActivity(), baseUri,
                    CONTACTS_SUMMARY_PROJECTION, select, null,
                    Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
        }

        @Override
        public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
            adapter.swapCursor(data);

            // The list should now be shown.
            if (isResumed()) {
                setListShown(true);
            } else {
                setListShownNoAnimation(true);
            }
        }

        @Override
        public void onLoaderReset(Loader<Cursor> loader) {
            adapter.swapCursor(null);
        }

        @Override
        public boolean onQueryTextSubmit(String query) {
            return true;
        }

        @Override
        public boolean onQueryTextChange(String newText) {
            mCurFilter  = !TextUtils.isEmpty(newText) ? newText : null;
            getLoaderManager().restartLoader(0, nullthis);
            return true;
        }
        
    }

 

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package
="com.api.loader.activity"
    android:versionCode
="1"
    android:versionName
="1.0" >

    <uses-sdk android:minSdkVersion="14" />
    <uses-permission android:name="android.permission.READ_CONTACTS"/>
    <application
        
android:icon="@drawable/ic_launcher"
        android:label
="@string/app_name" >
        <activity
            
android:label="@string/app_name"
            android:name
=".MyLoaderActivity" >
            <intent-filter >
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest> 

 

 

 

 

 

转载于:https://www.cnblogs.com/cody1988/archive/2012/04/09/2439195.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值