1 AdapterView和Adapter
AdapterView的子类有ListView,GridView,可通过继承自它们来自定义此类型的view,并通过实现AdapterView.OnItemClickListener接口来响应AdapterView中每一项上的点击事件,布局文件中对应等标签为:<ListView>、<GridView>。
Adapter充当数据源与AdapterView之间的桥梁,Adapter将数据与其布局绑定,并将每条数据转换为AdapterView中的一条项目。
2 Adapter
Adaper的子类有ArrayAdapter,SimpleCursorAdapter等,当数据源比较复杂时,可以通过继承BaseAdapter类来实现。
(1)ArrayAdapter:数据源为数组时使用此适配器;
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, myStringArray);
// 构造函数的参数:context,每个项目的布局,数据数组
ListView listView = (ListView) findViewById(R.id.listview);
listView.setAdapter(adapter);
(2)SimpleCursorAdapter:数据来自Cursor类时使用此适配器;当使用ContentResolver或从SQLite请求数据时,就将返回cursor对象。
String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER};
int[] toViews = {R.id.display_name, R.id.phone_number};
// SimpleCursorAdapter会使用提供的布局,将每个fromColumns项插入对应的toViews视图,为Cursor中的每个行创建一个视图
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.person_name_and_number, cursor, fromColumns, toViews, 0);
ListView listView = getListView();
listView.setAdapter(adapter);
3 ListView的优化
(1)使用convertView和ViewHolder
(2)getView()方法里不要有耗时任务
(3)异步加载数据
(4)滑动时停止加载(避免滑动时加载数据造成开销太大,停止滑动时再加载数据),分页加载(每次只加载一部分数据),通过实现AbsListView.OnScrollListener接口,并实现onScrollStateChanged(),onScroll()方法来实现;
(5)硬件加速:<listview>设置属性android:hardwareAccelerate="true";
android:scrollingCache="false"默认开启,会消耗大量内存
android:animationCache="false"
(6)item层级不要太高
4 convertView和ViewHolder
ListView的getView()方法中,会调用inflater.inflater(...)来加载每个item的布局来获得view,重用convertview可避免每次获得view都去新建一个view;
当需要获取某个view时,使用findViewById()耗时较大,可使用内部静态内ViewHolder,并用过setTag,getTag来获取view。
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
//判断是否有缓存
if (convertView == null) {
//通过LayoutInflate实例化布局
viewHolder = new ViewHolder();
convertView = mInflater.inflate(R.layout.item_layout, parent, false);
viewHolder.ivIcon = (ImageView) convertView.findViewById(R.id.iv_icon);
viewHolder.tvTitle = (TextView) convertView.findViewById(R.id.tv_title);
viewHolder.tvContent = (TextView) convertView.findViewById(R.id.tv_content);
convertView.setTag(viewHolder);
} else {
//通过tag找到缓存的布局
viewHolder = (ViewHolder) convertView.getTag();
}
return convertView;
}
内部静态类ViewHolder:
static class ViewHolder {
TextView text;
TextView timestamp;
ImageView icon;
ProgressBar progress;
int position;
}
5 异步加载
(1)新建一个线程,使用Handler方式来执行加载数据的任务;
(2)使用AysncTask类,在doInBackground()中加载数据,并重写onPostExecute(Bitmap result);
(3)使用加载器;
6 加载器
1 加载器相关API
LoaderManager:用于管理一个或多个 Loader 实例;
LoaderManager.LoaderCallbacks:回调接口,用于客户端通过LoaderManager管理Loader时会回调该接口中的方法;
Loader:执行异步数据加载的加载器类;
AsyncTaskLoader:提供AysncTask来执行工作的抽象加载器;
CursorLoader:AsyncTaskLoader的子类,它将查询ContentResolver并返回一个Cursor;
此外,您可以通过继承自AsyncTaskLoader来异步加载自定义的数据源。
2 LoaderManager 将自动管理加载器的生命周期。LoaderManager 将根据需要启动和停止加载,并维护加载器的状态及其相关内容。LoaderManager 将自动管理加载器的生命周期。您不必直接使用Loader的引用。当特定事件发生时,通常会使用LoaderManager.LoaderCallbacks方法干预加载进程。
3 LoaderManager常用方法
(1)启动加载器:getLoaderManager().initLoader(0,null, this);
第1个参数是标识加载器的唯一ID,第2个参数是可选参数,第三个参数是LoaderManager.LoaderCallbacks实现,LoaderManager将调用此实现来报告加载器事件。将触发LoaderManager.LoaderCallbacks的方法onCreateLoader();
(2)重启加载器:getLoaderManager().restartLoader(0,null, this);
4 LoaderManager.LoaderCallbacks 包括以下方法:
onCreateLoader():针对指定的 ID 进行实例化并返回新的Loader,可以在此方法中创建新加载器;
onLoadFinished() :将在先前创建的加载器完成加载时调用;
onLoaderReset():将在先前创建的加载器重置且其数据因此不可用时调用;