原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://terryblog.blog.51cto.com/1764499/794139
Loader的特点和使用场所
- Loader 可以在Activity 和Fragments 的界面下运行(本篇将结合上篇文章的Fragments的DEMO进行讲述如何在Fragments 下使用Loaders)。
- 它可以提供类似于AysncTask一样的异步请求数据加载的功能,实际上它就是来源于AysncTask 的扩展并增加了很多人性化的功能,例如加载进度框、更好的控制API等。
- 它拥有一个类似于Windows Phone 开发的MVVM一样的数据改变通知机制,当数据源做出改变时会及时通知。
- 当Cursor 发生变化时,会自动加载数据,因此并不需要再重新进行数据查询。
Loader API 使用参考
- LoaderManager
每一个Activity 和 Fragments 只能存在一个LoaderManager,负责管理界面中的Loader。 - LoaderManager.LoaderCallbacks
位于LoaderManager的子接口,提供众多的回调接口操作Loader ,如初始化、创建、重新启动、销毁、结束等一系列实用接口。 - Loader
与Fragments相似,是一个基础类,可以由用户自行扩展适合自己的类 - AsyncTaskLoader
提供了一个基于AsyncTask 工作机制的Loader,查看源码可以看到其继承于Loader,并且子类LoadTask 继承于AsyncTask<Void, Void, D>,并且实现了Runable 接口,功能十分强大。本DEMO就是基于AsyncTaskLoader篇写。 - CursorLoader
提供了一个基于AsyncTaskLoader工作机制的Loader,查看源码可以看到其继承于AsyncTaskLoader,一般继承OnQueryTextListener,可用于查询、更改数据源作用。
Loader 详细使用DEMO
基于上篇的Fragments 代码,添加Loaders功能,实现加载应用程序数据到界面上,DEMO的运行效果如下:
核心代码为
应用程序的数据对象类:
public static class AppEntry {
private final AppListLoader mLoader;
private final ApplicationInfo mInfo;
private final File mApkFile;
private String mLable;
private Drawable mIcon;
private boolean mMounted;
public AppEntry(AppListLoader loader, ApplicationInfo info) {
mLoader = loader;
mInfo = info;
mApkFile = new File(info.sourceDir);
}
public ApplicationInfo getApplicationInfo() {
return mInfo;
}
public String getLable() {
return mLable;
}
public Drawable getIcon() {
if (mIcon == null) {
if (mApkFile.exists()) {
mIcon = mInfo.loadIcon(mLoader.mPm);
return mIcon;
} else {
mMounted = false;
}
} else if (!mMounted) {
if (mApkFile.exists()) {
mMounted = true;
mIcon = mInfo.loadIcon(mLoader.mPm);
return mIcon;
}
} else {
return mIcon;
}
return mLoader.getContext().getResources().getDrawable(
android.R.drawable.sym_def_app_icon);
}
@Override
public String toString() {
// TODO Auto-generated method stub
return mLable.toString();
}
void loadLable(Context mContext) {
if (mLable == null || !mMounted) {
if (!mApkFile.exists()) {
mMounted = false;
mLable = mInfo.packageName;
} else {
mMounted = true;
CharSequence lable = mInfo.loadLabel(mContext
.getPackageManager());
mLable = lable != null ? lable.toString()
: mInfo.packageName;
}
}
}
private final AppListLoader mLoader;
private final ApplicationInfo mInfo;
private final File mApkFile;
private String mLable;
private Drawable mIcon;
private boolean mMounted;
public AppEntry(AppListLoader loader, ApplicationInfo info) {
mLoader = loader;
mInfo = info;
mApkFile = new File(info.sourceDir);
}
public ApplicationInfo getApplicationInfo() {
return mInfo;
}
public String getLable() {
return mLable;
}
public Drawable getIcon() {
if (mIcon == null) {
if (mApkFile.exists()) {
mIcon = mInfo.loadIcon(mLoader.mPm);
return mIcon;
} else {
mMounted = false;
}
} else if (!mMounted) {
if (mApkFile.exists()) {
mMounted = true;
mIcon = mInfo.loadIcon(mLoader.mPm);
return mIcon;
}
} else {
return mIcon;
}
return mLoader.getContext().getResources().getDrawable(
android.R.drawable.sym_def_app_icon);
}
@Override
public String toString() {
// TODO Auto-generated method stub
return mLable.toString();
}
void loadLable(Context mContext) {
if (mLable == null || !mMounted) {
if (!mApkFile.exists()) {
mMounted = false;
mLable = mInfo.packageName;
} else {
mMounted = true;
CharSequence lable = mInfo.loadLabel(mContext
.getPackageManager());
mLable = lable != null ? lable.toString()
: mInfo.packageName;
}
}
}
}
实现AsyncTaskLoader 加载数据
public static class AppListLoader extends AsyncTaskLoader<List<AppEntry>> {
final InterestingConfigChanges mLastConfig = new InterestingConfigChanges();
final PackageManager mPm;
List<AppEntry> mApps;
packageIntentReceiver mPackageObserver;
public AppListLoader(Context context) {
super(context);
// TODO Auto-generated constructor stub
mPm = getContext().getPackageManager();
}
@Override
public List<AppEntry> loadInBackground() {
// TODO Auto-generated method stub
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<AppEntry> entries = new ArrayList<AppEntry>(apps.size());
for (ApplicationInfo info : apps) {
AppEntry entry = new AppEntry(this, info);
entry.loadLable(mContext);
entries.add(entry);
}
Collections.sort(entries, ALPHA_COMPARATOR);
return entries;
}
@Override
public void deliverResult(
List<com.xuzhi.fragment.FragmentDemoActivity.AppEntry> data) {
// TODO Auto-generated method stub
if (isReset()) {
if (data != null) {
//释放资源处理
}
}
List<AppEntry> 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 packageIntentReceiver(this);
boolean configChange=mLastConfig.applyNewConfig(getContext().getResources());
if(takeContentChanged()|| mApps== null || configChange){
forceLoad();
}
};
@Override
public void onCanceled(
List<com.xuzhi.fragment.FragmentDemoActivity.AppEntry> 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;
}
}
final InterestingConfigChanges mLastConfig = new InterestingConfigChanges();
final PackageManager mPm;
List<AppEntry> mApps;
packageIntentReceiver mPackageObserver;
public AppListLoader(Context context) {
super(context);
// TODO Auto-generated constructor stub
mPm = getContext().getPackageManager();
}
@Override
public List<AppEntry> loadInBackground() {
// TODO Auto-generated method stub
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<AppEntry> entries = new ArrayList<AppEntry>(apps.size());
for (ApplicationInfo info : apps) {
AppEntry entry = new AppEntry(this, info);
entry.loadLable(mContext);
entries.add(entry);
}
Collections.sort(entries, ALPHA_COMPARATOR);
return entries;
}
@Override
public void deliverResult(
List<com.xuzhi.fragment.FragmentDemoActivity.AppEntry> data) {
// TODO Auto-generated method stub
if (isReset()) {
if (data != null) {
//释放资源处理
}
}
List<AppEntry> 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 packageIntentReceiver(this);
boolean configChange=mLastConfig.applyNewConfig(getContext().getResources());
if(takeContentChanged()|| mApps== null || configChange){
forceLoad();
}
};
@Override
public void onCanceled(
List<com.xuzhi.fragment.FragmentDemoActivity.AppEntry> 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;
}
}
}
实现数据源:
public static class AppListAdapter extends ArrayAdapter<AppEntry>{
private LayoutInflater mInflater;
public AppListAdapter(Context context) {
// TODO Auto-generated constructor stub
super(context, android.R.layout.simple_list_item_2);
mInflater=(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void setData(List<AppEntry> data){
clear();
if(data!=null){
addAll(data);
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View view;
if(convertView==null){
view=mInflater.inflate(R.layout.list_item_icon_text, parent,false);
}else{
view=convertView;
}
AppEntry item=getItem(position);
((ImageView)view.findViewById(R.id.icon)).setImageDrawable(item.getIcon());
((TextView)view.findViewById(R.id.text)).setText(item.getLable());
return view;
}
private LayoutInflater mInflater;
public AppListAdapter(Context context) {
// TODO Auto-generated constructor stub
super(context, android.R.layout.simple_list_item_2);
mInflater=(LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public void setData(List<AppEntry> data){
clear();
if(data!=null){
addAll(data);
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
View view;
if(convertView==null){
view=mInflater.inflate(R.layout.list_item_icon_text, parent,false);
}else{
view=convertView;
}
AppEntry item=getItem(position);
((ImageView)view.findViewById(R.id.icon)).setImageDrawable(item.getIcon());
((TextView)view.findViewById(R.id.text)).setText(item.getLable());
return view;
}
}
在Activity 或者Fragments 里面实现接口:
public static class DetailsFragment extends ListFragment implements OnQueryTextListener,LoaderCallbacks<List<AppEntry>>
实现接口里面的函数:
public boolean onQueryTextChange(String newText) {
// TODO Auto-generated method stub
return false;
}
public boolean onQueryTextSubmit(String query) {
// TODO Auto-generated method stub
return false;
}
public Loader<List<com.xuzhi.fragment.FragmentDemoActivity.AppEntry>> onCreateLoader(
int id, Bundle args) {
// TODO Auto-generated method stub
return new AppListLoader(getActivity());
}
/**
* Load 完成后
*/
public void onLoadFinished(
Loader<List<com.xuzhi.fragment.FragmentDemoActivity.AppEntry>> arg0,
List<com.xuzhi.fragment.FragmentDemoActivity.AppEntry> arg1) {
// TODO Auto-generated method stub
mAdapter.setData(arg1);
if (isResumed()) {
setListShown(true);
} else {
setListShownNoAnimation(true);
}
}
/**
* Loader 重置时
*/
public void onLoaderReset(
Loader<List<com.xuzhi.fragment.FragmentDemoActivity.AppEntry>> arg0) {
// TODO Auto-generated method stub
mAdapter.setData(null);
// TODO Auto-generated method stub
return false;
}
public boolean onQueryTextSubmit(String query) {
// TODO Auto-generated method stub
return false;
}
public Loader<List<com.xuzhi.fragment.FragmentDemoActivity.AppEntry>> onCreateLoader(
int id, Bundle args) {
// TODO Auto-generated method stub
return new AppListLoader(getActivity());
}
/**
* Load 完成后
*/
public void onLoadFinished(
Loader<List<com.xuzhi.fragment.FragmentDemoActivity.AppEntry>> arg0,
List<com.xuzhi.fragment.FragmentDemoActivity.AppEntry> arg1) {
// TODO Auto-generated method stub
mAdapter.setData(arg1);
if (isResumed()) {
setListShown(true);
} else {
setListShownNoAnimation(true);
}
}
/**
* Loader 重置时
*/
public void onLoaderReset(
Loader<List<com.xuzhi.fragment.FragmentDemoActivity.AppEntry>> arg0) {
// TODO Auto-generated method stub
mAdapter.setData(null);
}
得到LoaderManager初始化Loader,启动加载在Fragment 的onActivityCreated回调方法上添加,本DEMO的DetailsFragment类添加:
@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
mAdapter = new AppListAdapter(getActivity());
setListAdapter(mAdapter);
// Start out with a progress indicator.
setListShown(false);
// Prepare the loader. Either re-connect with an existing one,
// or start a new one.
getLoaderManager().initLoader(0, null, this);
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);
mAdapter = new AppListAdapter(getActivity());
setListAdapter(mAdapter);
// Start out with a progress indicator.
setListShown(false);
// Prepare the loader. Either re-connect with an existing one,
// or start a new one.
getLoaderManager().initLoader(0, null, this);
}
总结
Loader的使用分为以下几个步骤:
- 实现自己的异步Loader ,如本篇的AsyncTaskLoader或者CursorLoader或者自己继承Loader,第二步需要用到这个Loader
- 创建数据源->public static class AppListAdapter extends ArrayAdapter<AppEntry>
- 在Activity 或者Fragments 上实现OnQueryTextListener,LoaderManager.LoaderCallbacks接口
- 在onCreateLoader里面返回Loader,在onLoadfinished里面做清除动作,在 onQueryTextChange或者onQueryTextSubmit改变数据源,在onCreate里面让Loader去执行请求数据 getLoaderManager().initLoader(0, null, this);
源码下载:/Files/TerryBlog/FragmentLoader.zip
本文出自 “Terry_龙” 博客,请务必保留此出处http://terryblog.blog.51cto.com/1764499/794139
相关推荐
Levine所著的《Linkers & Loaders》是学习这一主题的重要文档,它详细讲解了ELF文件格式的原理,并通过实际案例帮助读者更深入地理解软件构建过程中的链接和加载机制。 链接器是处理编译器输出的程序,负责将多个...
loaders.css是一款使用纯CSS3 Loading加载指示器特效。该loading指示器特效共有11种不同的效果,都是使用CSS3 animation动画来完成。使用该Loading加载指示器特效需要在页面中引入loaders.css或loaders.min.css文件...
《Linkers and Loaders》是一本专注于链接器和加载器技术的英文图书,作者是John R. Levine。本书从历史角度出发,详细阐述了链接器和加载器的功能,以及它们如何处理编译后的代码和数据。在学习程序编译和运行过程...
"PHP建站必备"这一标签表明了ionCube Loaders对于那些使用PHP进行网站开发的人来说是至关重要的。许多商业级的PHP框架、CMS(内容管理系统)和电子商务解决方案,如Magento、Wordpress插件等,都可能使用ionCube编码...
**链接器(Linkers)**与**加载器(Loaders)**是计算机科学领域中两个重要的概念,它们在软件开发过程中扮演着关键角色。本书《链接器与加载器》旨在为读者提供关于链接器和加载器的深入理解,特别是对于那些希望...
4. **优化**:在某些情况下,链接器还可以进行一些简单的优化,比如去除未使用的函数或数据。 **加载器(Loaders)** 加载器在程序运行时发挥作用,负责将可执行文件从磁盘加载到内存,并准备执行。其主要职责包括...
cobbler相关程序文件
如果它是指Excel,那么可能意味着有人尝试将PHP与电子表格数据处理结合,或者使用IonCube加密的数据交换到Excel中。如果是指 "execl",那么可能是在谈论执行(execute)和离子立方(IonCube)的关系,这可能涉及到...
虽然IonCube Loaders提供了额外的安全层,但使用任何加密工具都有可能引入潜在的问题。例如,更新加密的代码可能需要重新安装Loader,这在多服务器环境中可能变得复杂。此外,加密代码可能会导致性能轻微下降,因为...
1. 下载:首先,你需要从官方渠道获取SourceGuardian 13.0(SG11)-loaders.linux-x86_64的压缩包文件。 2. 解压:将下载的压缩包解压到合适的目录,通常是在服务器的可执行文件路径下。 3. 配置:在PHP的配置文件...
标题中的"11.4_loaders.rar"似乎指的是一个关于SG11加密加载器的版本更新或特定章节的压缩文件,而"SG11加密"是这个话题的核心。描述提到SG11加密在不同的操作系统环境下需要加载对应的PHP扩展文件,这涉及到PHP的...
6. **PHP与移动平台的结合**:尽管IonCube主要应用于Web开发,但有时在混合开发场景(如PHP与Android的集成)中,可能会用到IonCube Loader来保护在移动设备上运行的PHP代码。 7. **安全与性能**:使用IonCube编码...
《Linkers and Loaders》是计算机科学领域一本经典著作,由美国计算机科学家Lawrence E. Graff著述。这本书深入浅出地探讨了链接器、加载器以及它们在程序执行过程中的作用,对理解操作系统如何管理和执行代码至关...
loadersCDN umd: : esm / mjs: ://unpkg.com/vue-loaders/dist/vue-loaders.esm.js umd: https://unpkg.com/vue-loaders/dist/loaders/ : https://unpkg.com/vue-loaders/dist/loaders/.js用法在开始使用加载...
**链接器与加载器(Linkers & Loaders):关键概念与架构问题** 在计算机科学领域,链接器(Linkers)和加载器(Loaders)是编译过程中的两个核心组件,它们负责将多个编译单元连接成一个可执行程序,并在运行时将...
因此,使用ionCube加密代码的同时,仍然需要遵循最佳的安全实践,如输入验证、输出过滤和安全编程。 此外,ionCube还支持其他功能,如限制代码的运行时间、IP地址访问控制、许可证验证等,这些都是为了进一步增强...
根据提供的文档内容,我们可以深入探讨有关汇编器(assemblers)与加载器(loaders)的相关知识点。本文将从历史背景、基本原理、符号表管理以及指令集几个方面进行详细解析。 ### 一、历史背景 #### A. 汇编器与...
总之,Greenplum的加载工具5.23.0在RHEL7 x86_64平台上提供了强大的数据管理能力,结合其高效的并行处理机制,使得大数据分析变得更加高效和便捷。正确理解和使用这些工具,是充分发挥Greenplum性能的关键。
ioncube_loaders_lin_x86-64.zip