Android Fragment实践(三)— 使用Fragment + Loader实现异步加载

 1. 简介:

我们经常在Fragment中进行异步加载的操作。在Android中的Fragment中,提供了异步加载管理器LoaderManager,可以进行对异步加载进行管理。从而简化了应用程序开发复杂度。

2. Fragment中的Loader相关组件和类图:

类图如下:

说明:

(1)LoaderTask:是继承自AsyncTask,并且实现了Runnable,它具备了异步任务的能力;

(2)AsyncTaskLoader:继承自Loader,而且有LoaderTask类的数据成员,所以,它可以进行异步加载;

(3)LoaderManager:为了更方便的进行Loader的管理,Android系统提供了这个加载管理器;每一个Activity 和 Fragments 只能存在一个LoaderManager;

(4)LoaderInfo:需要加载的数据的信息;是一个基础类,可以由用户自行扩展适合自己的类;

(5)LoaderCallbacks: 由于是异步加载,所以,提供了callback回调函数。需要用户来实现相关函数;包括初始化、创建、重新启动、销毁、结束等一系列实用接口等。

(6)Fragment:Fragment基类,提供了mLoaderManager,通过这个数据成员来进行异步加载的管理。用户可以继承自Fragment,来实现Fragment中的异步加载功能。

通过以上架构,用户就可以实现Fragment中的异步加载功能。

3. 举例:应用列表的显示,利用Fragment和Loader来实现。

实现思路:

(1)应用程序列表的存储:

        定义一个AppModel,来存储一个应用程序信息;

List<ApplicationInfo> apps = mPm
                .getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES
                        | PackageManager.GET_DISABLED_COMPONENTS);

(2)异步加载这些信息:

      自定义一个AsyncTaskLoader

public class AppListLoader extends AsyncTaskLoader<List<AppModel>>

(3)界面相关:

      自定义的Fragment和数据适配器adapter

public class DetailsFragment extends ListFragment implements OnQueryTextListener,LoaderCallbacks<List<AppModel>>

 3.1 核心代码(AppListLoader.java):

public class AppListLoader extends AsyncTaskLoader<List<AppModel>> {
    Context mContext;
    final InterestingConfigChanges mLastConfig = new InterestingConfigChanges();
    final PackageManager mPm;

    List<AppModel> mApps;
    AppReceiver mPackageObserver;

    public AppListLoader(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
        mPm = getContext().getPackageManager();
        mContext = context;
    }

    @Override
    public List<AppModel> loadInBackground() {
        // TODO Auto-generated method stub
        @SuppressLint("WrongConstant") List<ApplicationInfo> apps = mPm
                .getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES
                        | PackageManager.GET_DISABLED_COMPONENTS);
        if (apps == null)
            apps = new ArrayList<ApplicationInfo>();
        final Context mContext = getContext();
        List<AppModel> entries = new ArrayList<AppModel>(apps.size());
        for (ApplicationInfo info : apps) {
            AppModel entry = new AppModel(this, info);
            entry.loadLable(mContext);
            entries.add(entry);
        }
        Collections.sort(entries, ALPHA_COMPARATOR);
        return entries;
    }

    @Override
    public void deliverResult(
            List<AppModel> data) {
        // TODO Auto-generated method stub
        if (isReset()) {
            if (data != null) {
                //释放资源处理
            }
        }

        List<AppModel> oladApps=data;
        mApps=data;
        if(isStarted()){
            super.deliverResult(data);
        }


        if(oladApps!=null){
            //释放资源
        }
    }


    protected void onStartLoading() {
        if(mApps!=null)
            deliverResult(mApps);

        if(mPackageObserver==null)
            mPackageObserver=new AppReceiver(this);

        boolean configChange=mLastConfig.applyNewConfig(getContext().getResources());

        if(takeContentChanged()|| mApps== null || configChange){
            forceLoad();
        }
    };

    @Override
    public void onCanceled(
            List<AppModel> data) {
        // TODO Auto-generated method stub
        super.onCanceled(data);
        cancelLoad();
    }

    @Override
    protected void onReset() {
        // TODO Auto-generated method stub
        super.onReset();
        onStopLoading();

        if(mApps!=null){
            //释放资源
            mApps=null;
        }

        if(mPackageObserver!=null){
            getContext().unregisterReceiver(mPackageObserver);
            mPackageObserver=null;
        }
    }
}

代码说明:

(1)AppListLoader继承自AsyncTaskLoader,通过调用AndroidSDK提供的PackageManager的getInstalledApplications来获取应用列表;

(2)deliverResult:将结果发送到loader的监听器中。

 3.2 核心代码(DetailsFragment.java):

public class DetailsFragment extends ListFragment implements OnQueryTextListener,LoaderCallbacks<List<AppModel>>{

	MyFragmentDemoActivity.AppListAdapter mAdapter;
	String mCurFilter;
	@Override
	public void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setHasOptionsMenu(true);

	}

	......
	/**
	 * 创建loader
	 */

	public Loader<List<AppModel>> onCreateLoader(
			int id, Bundle args) {
		// TODO Auto-generated method stub
		return new AppListLoader(getActivity());
	}

	/**
	 * Load 完成后
	 */
	public void onLoadFinished(
			Loader<List<AppModel>> arg0,
			List<AppModel> arg1) {
		// TODO Auto-generated method stub
		mAdapter.setData(arg1);
		if (isResumed()) {
			setListShown(true);
		} else {
			setListShownNoAnimation(true);
		}
	}

	/**
	 * Loader 重置时
	 */
	public void onLoaderReset(
			Loader<List<AppModel>> arg0) {
		// TODO Auto-generated method stub
		mAdapter.setData(null);
	}
}

说明:

(1)自定义的Fragmeng继承自,实现了LoaderCallbacks;

(2)在onCreateLoader中,创建了AppListLoader;

(3)在onLoadFinished中,进行资源的释放和清理。

4 源代码传送门:

Fragment+Loader实现异步加载:

https://download.csdn.net/download/liranke/86334527

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,我可以为您解答。首先,您需要在布局文件中添加一个FragmentTabHost控件,用于显示底部标签栏。然后,您需要在Activity中继承FragmentActivity类,并在onCreate方法中初始化FragmentTabHost控件。最后,您需要创建多个Fragment类,用于显示不同的内容,并通过FragmentTabHost控件将它们与底部标签栏关联起来。 以下是一份示例代码,供您参考: 1. 布局文件 ```xml <android.support.v4.app.FragmentTabHost android:id="@android:id/tabhost" android:layout_width="match_parent" android:layout_height="match_parent"> <FrameLayout android:id="@android:id/tabcontent" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"/> <TabWidget android:id="@android:id/tabs" android:layout_width="match_parent" android:layout_height="wrap_content"/> </android.support.v4.app.FragmentTabHost> ``` 2. Activity类 ```java public class MainActivity extends FragmentActivity { private FragmentTabHost mTabHost; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTabHost = findViewById(android.R.id.tabhost); mTabHost.setup(this, getSupportFragmentManager(), android.R.id.tabcontent); mTabHost.addTab(mTabHost.newTabSpec("tab1").setIndicator("Tab 1"), Tab1Fragment.class, null); mTabHost.addTab(mTabHost.newTabSpec("tab2").setIndicator("Tab 2"), Tab2Fragment.class, null); mTabHost.addTab(mTabHost.newTabSpec("tab3").setIndicator("Tab 3"), Tab3Fragment.class, null); } } ``` 3. Fragment类 ```java public class Tab1Fragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_tab1, container, false); } } public class Tab2Fragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_tab2, container, false); } } public class Tab3Fragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_tab3, container, false); } } ``` 请注意,上述代码中的布局文件和Fragment类仅仅是示例,您需要根据自己的需求进行相应的修改。另外,由于使用FragmentTabHost控件,因此需要引入support-v4库。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

liranke

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值