怎么在回调函数里加载listview加载网络图片

Android上拉加载更多ListView——PulmListView
今天带大家实现一个上拉加载更多的ListView.GitHub传送门:, 欢迎大家fork&&star.
先带大家理一下思路, 如果我们要实现一个上拉加载更多的ListView, 我们需要实现的功能包括:
一个自定义的ListView, 并且该ListView能够判断当前是否已经处于最底部. 一个自定义的FooterView, 用于在ListView加载更多的过程中进行UI展示. 关联FooterView和ListView, 包括加载时机判断、FooterView的显示和隐藏. 提供一个加载更多的接口, 便于回调用户真正加载更多的功能实现. 提供一个加载更多结束的回调方法, 用于添加用户的最新数据并更新相关状态标记和UI显示.
针对上面的5个功能, 我们挨个分析对应的实现方法.
功能1(自定义ListView)
我们可以通过继承ListView, 实现一个自定义的PulmListView.
public class PulmListView extends ListView {
public PulmListView(Context context) {
this(context, null);
public PulmListView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
public PulmListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
只是实现ListView的三个构造函数还不够, 我们需要ListView能够判断当前的ListView是否滑动到最后一个元素.
判断是否滑动到最后一个元素, 我们可以通过为ListView设置OnScrollListener来实现.代码如下:
private void init() {
super.setOnScrollListener(new OnScrollListener() {
public void onScrollStateChanged(AbsListView view, int scrollState) {
// 调用用户设置的OnScrollListener
if (mUserOnScrollListener != null) {
mUserOnScrollListener.onScrollStateChanged(view, scrollState);
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
// 调用用户设置的OnScrollListener
if (mUserOnScrollListener != null) {
mUserOnScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
// firstVisibleItem是当前屏幕能显示的第一个元素的位置
// visibleItemCount是当前屏幕能显示的元素的个数
// totalItemCount是ListView包含的元素总数
int lastVisibleItem = firstVisibleItem + visibleItemC
if (!mIsLoading && !mIsPageFinished && lastVisibleItem == totalItemCount) {
if (mOnPullUpLoadMoreListener != null) {
mIsLoading =
mOnPullUpLoadMoreListener.onPullUpLoadMore();
从代码注释可以知道, 通过(firstVisibleItem + visibleItemCount)可以获取当前屏幕已经展示的元素个数, 如果已经展示的元素个数等于ListView的元素总数, 则此时可以认为ListView已经滑动到底部.
这里我们可以实现一个比较简单的FooterView, 即加载更多的UI布局.例如我们可以展示一个ProgressBar和一行文字, 具体代码如下:
* 加载更多的View布局,可自定义.
public class LoadMoreView extends LinearLayout {
public LoadMoreView(Context context) {
this(context, null);
public LoadMoreView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
public LoadMoreView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
private void init() {
LayoutInflater.from(getContext()).inflate(R.layout.lv_load_more, this);
第一,我们需要在ListView中通过一个变量保存FooterView, 并且在构造函数中将其实例化.
private View mLoadMoreV
private void init() {
mLoadMoreView = new LoadMoreView(getContext());
第二,我们需要控制FooterView的显示和隐藏.考虑一下FooterView的显示和隐藏的时机:
显示的时机: ListView处于最底部并且当前还有更多的数据需要加载. 隐藏的时机: ListView结束完加载更多的操作.
为了判断当前是否还有数据需要加载, 因此我们需要定义一个boolean变量mIsPageFinished, 表示数据加载是否结束.
为了保证同一时间只进行一次数据加载过程, 因此我们还需要定义一个boolean变量mIsLoading, 表示当前是否已经处于数据加载状态.
明确了FooterView的显示和隐藏时机, 也有了控制状态的变量, 代码也就比较容易实现了.
private void init() {
mIsLoading = // 初始化时没处于加载状态
mIsPageFinished = // 初始化时默认还有更多数据需要加载
mLoadMoreView = new LoadMoreView(getContext()); // 实例化FooterView
super.setOnScrollListener(new OnScrollListener() {
public void onScrollStateChanged(AbsListView view, int scrollState) {
// 调用用户设置的OnScrollListener
if (mUserOnScrollListener != null) {
mUserOnScrollListener.onScrollStateChanged(view, scrollState);
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
// 调用用户设置的OnScrollListener
if (mUserOnScrollListener != null) {
mUserOnScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
int lastVisibleItem = firstVisibleItem + visibleItemC
// 当处于ListView尾部且有更多数据需要加载且当前没有加载程序再进行中时, 执行加载更多操作
if (!mIsLoading && !mIsPageFinished && lastVisibleItem == totalItemCount) {
if (mOnPullUpLoadMoreListener != null) {
mIsLoading = // 将加载更多进行时状态设置为true
showLoadMoreView(); // 显示加载更多布局
mOnPullUpLoadMoreListener.onPullUpLoadMore(); // 调用用户设置的加载更多回调接口
private void showLoadMoreView() {
// 这里将加载更多的根布局id设置为id_load_more_layout, 便于用户自定制加载更多布局.
if (findViewById(R.id.id_load_more_layout) == null) {
addFooterView(mLoadMoreView);
* 加载更多结束后ListView回调方法.
* @param isPageFinished 分页是否结束
* @param newItems
分页加载的数据
* @param isFirstLoad
是否第一次加载数据(用于配置下拉刷新框架使用, 避免出现页面闪现)
public void onFinishLoading(boolean isPageFinished, List newItems, boolean isFirstLoad) {
mIsLoading = // 标记当前已经没有加载更多的程序在执行
setIsPageFinished(isPageFinished); // 设置分页是否结束标志并移除FooterView
private void setIsPageFinished(boolean isPageFinished) {
mIsPageFinished = isPageF
removeFooterView(mLoadMoreView);
功能4(上拉加载更多实现的回调接口)
这个比较简单, 我们定义一个interface, 便于回调用户真正的加载更多的实现方法.
* 上拉加载更多的回调接口
public interface OnPullUpLoadMoreListener {
void onPullUpLoadMore();
private OnPullUpLoadMoreListener mOnPullUpLoadMoreL
* 设置上拉加载更多的回调接口.
* @param l 上拉加载更多的回调接口
public void setOnPullUpLoadMoreListener(OnPullUpLoadMoreListener l) {
this.mOnPullUpLoadMoreListener =
功能5(加载更多的结束回调)
为了在PulmListView中维护数据集合, 必须自定义一个Adapter, 在Adapter中使用List存储数据集合, 并提交增删的方法.
自定义的Adapter:
* 抽象的Adapter.
public abstract class PulmBaseAdapter extends BaseAdapter {
protected List
public PulmBaseAdapter() {
this.items = new ArrayList&&();
public PulmBaseAdapter(List items) {
this.items =
public void addMoreItems(List newItems, boolean isFirstLoad) {
if (isFirstLoad) {
this.items.clear();
this.items.addAll(newItems);
notifyDataSetChanged();
public void removeAllItems() {
this.items.clear();
notifyDataSetChanged();
为什么在addMoreItems方法中要增加一个isFirstLoad变量呢?
是因为上拉加载更多通常要配合下拉刷新使用.而下拉刷新的过程中会牵扯到ListView的数据集合clear然后再addAll.如果没有isFirstLoad参数, 那用户下拉刷新去更新ListView的数据集合就必须分为两步:
removeAllItems并进行notifyDataSetChanged. addMoreItems并进行notifyDataSetChanged.
同一时间连续两次notifyDataSetChanged会导致屏幕闪屏, 因此这里提交了一个isFirstLoad方法.当是第一次加载数据时, 会先clear掉所有的数据, 然后再addAll, 最后再notify.
有了自定义的adapter, 就可以写加载更多结束的回调函数了:
* 加载更多结束后ListView回调方法.
* @param isPageFinished 分页是否结束
* @param newItems
分页加载的数据
* @param isFirstLoad
是否第一次加载数据(用于配置下拉刷新框架使用, 避免出现页面闪现)
public void onFinishLoading(boolean isPageFinished, List newItems, boolean isFirstLoad) {
mIsLoading =
setIsPageFinished(isPageFinished);
// 添加更新后的数据
if (newItems != null && newItems.size() & 0) {
PulmBaseAdapter adapter = (PulmBaseAdapter) ((HeaderViewListAdapter) getAdapter()).getWrappedAdapter();
adapter.addMoreItems(newItems, isFirstLoad);
这里需要注意, 当添加了FooterView或者HeaderView之后, 我们无法通过listview.getAdapter拿到我们自定义的adapter, 必须按照如下步骤:
PulmBaseAdapter adapter = (PulmBaseAdapter) ((HeaderViewListAdapter) getAdapter()).getWrappedAdapter();&nbsp&#8250&nbsp&nbsp&#8250&nbsp
ListView之BaseAdapter的基本使用以及ViewHolder模式
原文出处:&这篇文章适合初学者,高手绕道,当然不知道ViewHolder的“高手”可以停下来。 话说开发用了各种Adapter之后感觉用的最舒服的还是BaseAdapter,尽管使用起来比其他适配器有些麻烦,但是使用它却能实现很多自己喜欢的列表布局,比如ListView、GridView、Gallery、Spinner等等。它是直接继承自接口类Adapter的,使用BaseAdapter时需要重写很多方法,其中最重要的当属getView,因为这会涉及到ListView优化等问题,其他的方法可以参考链接的文章BaseAdapter与其他Adapter有些不一样,其他的Adapter可以直接在其构造方法中进行数据的设置,比如SimpleAdapter&adapter&=&new&SimpleAdapter(this,&getData(),&R.layout.list_item,&new&String[]{&img&,&title&,&info&,new&int[]{R.id.img,&R.id.title,&}});但是在BaseAdapter中需要实现一个继承自BaseAdapter的类,并且重写里面的很多方法,例如class&MyAdapter&extends&BaseAdapter
&&&&&&&&private&Context&
&&&&&&&&public&MyAdapter(Context&context)
&&&&&&&&&&&&this.context&=&
&&&&&&&&@Override
&&&&&&&&public&int&getCount()&{
&&&&&&&&&&&&//&How&many&items&are&in&the&data&set&represented&by&this&Adapter.(在此适配器中所代表的数据集中的条目数)
&&&&&&&&&&&&return&0;
&&&&&&&&@Override
&&&&&&&&public&Object&getItem(int&position)&{
&&&&&&&&&&&&//&Get&the&data&item&associated&with&the&specified&position&in&the&data&set.(获取数据集中与指定索引对应的数据项)
&&&&&&&&&&&&return&
&&&&&&&&@Override
&&&&&&&&public&long&getItemId(int&position)&{
&&&&&&&&&&&&//&Get&the&row&id&associated&with&the&specified&position&in&the&list.(取在列表中与指定索引对应的行id)
&&&&&&&&&&&&return&0;
&&&&&&&&@Override
&&&&&&&&public&View&getView(int&position,&View&convertView,&ViewGroup&parent)&{
&&&&&&&&&&&&//&Get&a&View&that&displays&the&data&at&the&specified&position&in&the&data&set.
&&&&&&&&&&&&return&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&}这里面没什么难度,但是这个getView方法必须好好处理,也是最麻烦的第一种:没有任何处理,不建议这样写。如果数据量少看将就,但是如果列表项数据量很大的时候,会每次都重新创建View,设置资源,严重影响性能,所以从一开始就不要用这种方式@Override
&&&&&&&&public&View&getView(int&position,&View&convertView,&ViewGroup&parent)&{
&&&&&&&&&&&&View&item&=&mInflater.inflate(R.layout.list_item,&null);
&&&&&&&&&&&&ImageView&img&=&(ImageView)item.findViewById(R.id.img)
&&&&&&&&&&&&TextView&title&=&(TextView)item.findViewById(R.id.title);
&&&&&&&&&&&&TextView&info&=&(TextView)item.findViewById();
&&&&&&&&&&&&img.setImageResource(R.drawable.ic_launcher);
&&&&&&&&&&&&title.setText(&Hello&);
&&&&&&&&&&&&info.setText(&world&);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&return&
&&&&&&&&}第二种ListView优化:通过缓存convertView,这种利用缓存contentView的方式可以判断如果缓存中不存在View才创建View,如果已经存在可以利用缓存中的View,提升了性能public&View&getView(int&position,&View&convertView,&ViewGroup&parent)&{
&&&&&&&&&&&&if(convertView&==&null)
&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&convertView&=&mInflater.inflate(R.layout.list_item,&null);
&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&ImageView&img&=&(ImageView)convertView.findViewById(R.id.img)
&&&&&&&&&&&&TextView&title&=&(TextView)convertView.findViewById(R.id.title);
&&&&&&&&&&&&TextView&info&=&(TextView)ConvertView.findViewById();
&&&&&&&&&&&&img.setImageResource(R.drawable.ic_launcher);
&&&&&&&&&&&&title.setText(&Hello&);
&&&&&&&&&&&&info.setText(&world&);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&return&convertV
&&&&&&&&}第三种ListView优化:通过convertView+ViewHolder来实现,ViewHolder就是一个静态类,使用 ViewHolder 的关键好处是缓存了显示数据的视图(View),加快了 UI 的响应速度。当我们判断 convertView == null &的时候,如果为空,就会根据设计好的List的Item布局(XML),来为convertView赋值,并生成一个viewHolder来绑定converView里面的各个View控件(XML布局里面的那些控件)。再用convertView的setTag将viewHolder设置到Tag中,以便系统第二次绘制ListView时从Tag中取出。(看下面代码中)如果convertView不为空的时候,就会直接用convertView的getTag(),来获得一个ViewHolder。//在外面先定义,ViewHolder静态类
static&class&ViewHolder
&&&&public&ImageView&
&&&&public&TextView&
&&&&public&TextView&
//然后重写getView
public&View&getView(int&position,&View&convertView,&ViewGroup&parent)&{
&&&&ViewHolder&
&&&&if(convertView&==&null)
&&&&&&&&holder&=&new&ViewHolder();
&&&&&&&&convertView&=&mInflater.inflate(R.layout.list_item,&null);
&&&&&&&&holder.img&=&(ImageView)item.findViewById(R.id.img)
&&&&&&&&holder.title&=&(TextView)item.findViewById(R.id.title);
&&&&&&&&&=&(TextView)item.findViewById();
&&&&&&&&convertView.setTag(holder);
&&&&&&&&holder&=&(ViewHolder)convertView.getTag();
&&&&&&&&holder.img.setImageResource(R.drawable.ic_launcher);
&&&&&&&&holder.title.setText(&Hello&);
&&&&&&&&.setText(&World&);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&return&convertV
}到这里,可能会有人问ViewHolder静态类结合缓存convertView与直接使用convertView有什么区别吗,是否重复了在这里,官方给出了解释提升Adapter的两种方法To work efficiently the adapter implemented here uses two techniques:-It reuses the convertView passed to getView() to avoid inflating View when it is not necessary(译:重用缓存convertView传递给getView()方法来避免填充不必要的视图)-It uses the ViewHolder pattern to avoid calling findViewById() when it is not necessary(译:使用ViewHolder模式来避免没有必要的调用findViewById():因为太多的findViewById也会影响性能)ViewHolder类的作用-The ViewHolder pattern consists in storing a data structure in the tag of the viewreturned by getView().This data structures contains references to the views we want to bind data to,thus avoiding calling to findViewById() every time getView() is invoked(译:ViewHolder模式通过getView()方法返回的视图的标签(Tag)中存储一个数据结构,这个数据结构包含了指向我们要绑定数据的视图的引用,从而避免每次调用getView()的时候调用findViewById())实例一:用BaseAdapter来自定义ListView布局main.xml&?xml&version=&1.0&&encoding=&utf-8&?&
&LinearLayout&xmlns:android=&/apk/res/android&
&&&&android:layout_width=&fill_parent&
&&&&android:layout_height=&fill_parent&
&&&&android:orientation=&vertical&&&
&&&&&ListView
&&&&&&&&android:id=&@+id/lv&
&&&&&&&&android:layout_width=&fill_parent&
&&&&&&&&android:layout_height=&wrap_content&
&&&&&&&&android:fastScrollEnabled=&true&
&&&&&&&&/&
&/LinearLayout&list_item.xml&?xml&version=&1.0&&encoding=&utf-8&?&
&LinearLayout&xmlns:android=&/apk/res/android&
&&&&android:layout_width=&match_parent&
&&&&android:layout_height=&match_parent&
&&&&android:orientation=&horizontal&&&
&&&&&ImageView
&&&&&&&&android:id=&@+id/img&
&&&&&&&&android:layout_width=&wrap_content&
&&&&&&&&android:layout_height=&wrap_content&
&&&&&&&&/&
&&&&&LinearLayout
&&&&&&&&android:layout_width=&fill_parent&
&&&&&&&&android:layout_height=&wrap_content&
&&&&&&&&android:orientation=&vertical&
&&&&&&&&&TextView
&&&&&&&&&&&&android:id=&@+id/tv&
&&&&&&&&&&&&android:layout_width=&wrap_content&
&&&&&&&&&&&&android:layout_height=&wrap_content&
&&&&&&&&&&&&android:textSize=&20sp&
&&&&&&&&/&
&&&&&&&&&TextView
&&&&&&&&&&&&android:id=&@+id/info&
&&&&&&&&&&&&android:layout_width=&wrap_content&
&&&&&&&&&&&&android:layout_height=&wrap_content&
&&&&&&&&&&&&android:textSize=&14sp&
&&&&&&&&&&&&/&
&&&&&/LinearLayout&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&/LinearLayout&Activitypackage&com.loulijun.demo17;
import&java.util.ArrayL
import&java.util.HashM
import&java.util.L
import&java.util.M
import&android.app.A
import&android.content.C
import&android.os.B
import&android.view.LayoutI
import&android.view.V
import&android.view.ViewG
import&android.widget.BaseA
import&android.widget.ImageV
import&android.widget.ListV
import&android.widget.TextV
public&class&Demo17Activity&extends&Activity&{
&&&&private&ListView&
&&&&private&List&Map&String,&Object&&&
&&&&@Override
&&&&public&void&onCreate(Bundle&savedInstanceState)&{
&&&&&&&&super.onCreate(savedInstanceState);
&&&&&&&&setContentView(R.layout.main);
&&&&&&&&lv&=&(ListView)findViewById(R.id.lv);
&&&&&&&&//获取将要绑定的数据设置到data中
&&&&&&&&data&=&getData();
&&&&&&&&MyAdapter&adapter&=&new&MyAdapter(this);
&&&&&&&&lv.setAdapter(adapter);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&private&List&Map&String,&Object&&&getData()
&&&&&&&&List&Map&String,&Object&&&list&=&new&ArrayList&Map&String,&Object&&();
&&&&&&&&Map&String,&Object&&
&&&&&&&&for(int&i=0;i&10;i++)
&&&&&&&&&&&&map&=&new&HashMap&String,&Object&();
&&&&&&&&&&&&map.put(&img&,&R.drawable.ic_launcher);
&&&&&&&&&&&&map.put(&title&,&&跆拳道&);
&&&&&&&&&&&&map.put(&info&,&&快乐源于生活...&);
&&&&&&&&&&&&list.add(map);
&&&&&&&&return&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&//ViewHolder静态类
&&&&static&class&ViewHolder
&&&&&&&&public&ImageView&
&&&&&&&&public&TextView&
&&&&&&&&public&TextView&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&public&class&MyAdapter&extends&BaseAdapter
&&&&&&&&private&LayoutInflater&mInflater&=&
&&&&&&&&private&MyAdapter(Context&context)
&&&&&&&&&&&&//根据context上下文加载布局,这里的是Demo17Activity本身,即this
&&&&&&&&&&&&this.mInflater&=&LayoutInflater.from(context);
&&&&&&&&@Override
&&&&&&&&public&int&getCount()&{
&&&&&&&&&&&&//How&many&items&are&in&the&data&set&represented&by&this&Adapter.
&&&&&&&&&&&&//在此适配器中所代表的数据集中的条目数
&&&&&&&&&&&&return&data.size();
&&&&&&&&@Override
&&&&&&&&public&Object&getItem(int&position)&{
&&&&&&&&&&&&//&Get&the&data&item&associated&with&the&specified&position&in&the&data&set.
&&&&&&&&&&&&//获取数据集中与指定索引对应的数据项
&&&&&&&&&&&&return&data.getItem(postion);
&&&&&&&&@Override
&&&&&&&&public&long&getItemId(int&position)&{
&&&&&&&&&&&&//Get&the&row&id&associated&with&the&specified&position&in&the&list.
&&&&&&&&&&&&//获取在列表中与指定索引对应的行id
&&&&&&&&&&&&return&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&//Get&a&View&that&displays&the&data&at&the&specified&position&in&the&data&set.
&&&&&&&&//获取一个在数据集中指定索引的视图来显示数据
&&&&&&&&@Override
&&&&&&&&public&View&getView(int&position,&View&convertView,&ViewGroup&parent)&{
&&&&&&&&&&&&ViewHolder&holder&=&
&&&&&&&&&&&&//如果缓存convertView为空,则需要创建View
&&&&&&&&&&&&if(convertView&==&null)
&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&holder&=&new&ViewHolder();
&&&&&&&&&&&&&&&&//根据自定义的Item布局加载布局
&&&&&&&&&&&&&&&&convertView&=&mInflater.inflate(R.layout.list_item,&null);
&&&&&&&&&&&&&&&&holder.img&=&(ImageView)convertView.findViewById(R.id.img);
&&&&&&&&&&&&&&&&holder.title&=&(TextView)convertView.findViewById(R.id.tv);
&&&&&&&&&&&&&&&&&=&(TextView)convertView.findViewById();
&&&&&&&&&&&&&&&&//将设置好的布局保存到缓存中,并将其设置在Tag里,以便后面方便取出Tag
&&&&&&&&&&&&&&&&convertView.setTag(holder);
&&&&&&&&&&&&}else
&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&holder&=&(ViewHolder)convertView.getTag();
&&&&&&&&&&&&}
&&&&&&&&&&&&holder.img.setImageResource((Integer)&data.get(position).get(&img&));
&&&&&&&&&&&&holder.title.setText((String)data.get(position).get(&title&));
&&&&&&&&&&&&.setText((String)data.get(position).get(&info&));
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&return&convertV
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
}运行结果如下:实例二:Gallery上应用BaseAdaptermain.xml&?xml&version=&1.0&&encoding=&utf-8&?&
&LinearLayout&xmlns:android=&/apk/res/android&
&&&&android:layout_width=&fill_parent&
&&&&android:layout_height=&fill_parent&
&&&&android:orientation=&vertical&&&
&&&&&ImageView&
&&&&&&&&android:id=&@+id/img&
&&&&&&&&android:layout_width=&480px&
&&&&&&&&android:layout_height=&480px&
&&&&&&&&android:layout_gravity=&center&
&&&&&&&&/&
&&&&&Gallery&
&&&&&&&&android:id=&@+id/gallery&
&&&&&&&&android:layout_width=&fill_parent&
&&&&&&&&android:layout_height=&wrap_content&
&&&&&&&&android:spacing=&3dp&
&&&&&&&&android:layout_gravity=&bottom&
&&&&&&&&/&
&/LinearLayout&Activity:这部分里的getView没有优化,调试了很久还没调通,暂时还是用的最基本的方法。会专门找个时间把Gallery内存泄露的部分写一下,因为图片资源很多的时候会引起out of memory的错误package&com.loulijun.demo16;
import&android.app.A
import&android.content.C
import&android.os.B
import&android.view.V
import&android.view.ViewG
import&android.widget.AdapterV
import&android.widget.BaseA
import&android.widget.G
import&android.widget.ImageV
public&class&Demo16Activity&extends&Activity&{
&&&&private&Gallery&mG
&&&&private&ImageView&mI
&&&&//图片数组
&&&&private&int[]&pics&=&{
&&&&&&&&&&&&R.drawable.pic1,
&&&&&&&&&&&&R.drawable.pic2,
&&&&&&&&&&&&R.drawable.pic3,
&&&&&&&&&&&&R.drawable.pic4,
&&&&&&&&&&&&R.drawable.pic5,
&&&&&&&&&&&&R.drawable.pic6
&&&&@Override
&&&&public&void&onCreate(Bundle&savedInstanceState)&{
&&&&&&&&super.onCreate(savedInstanceState);
&&&&&&&&setContentView(R.layout.main);
&&&&&&&&mImg&=&(ImageView)findViewById(R.id.img);
&&&&&&&&mGallery&=&(Gallery)findViewById(R.id.gallery);
&&&&&&&&MyAdapter&adapter&=&new&MyAdapter(this);
&&&&&&&&mGallery.setAdapter(adapter);
&&&&&&&&mGallery.setOnItemClickListener(new&Gallery.OnItemClickListener()
&&&&&&&&&&&&@Override
&&&&&&&&&&&&public&void&onItemClick(AdapterView&?&&adapter,&View&view,&int&position,
&&&&&&&&&&&&&&&&&&&&long&arg3)&{
&&&&&&&&&&&&&&&&mImg.setImageResource(pics[position]);
&&&&&&&&&&&&}
&&&&&&&&&&&&
&&&&&&&&});
&&&&//内部类
&&&&class&MyAdapter&extends&BaseAdapter
&&&&&&&&//用来接收传递过来的Context上下文对象
&&&&&&&&private&Context&
&&&&&&&&//构造函数
&&&&&&&&public&MyAdapter(Context&context)
&&&&&&&&&&&&this.context&=&
&&&&&&&&@Override
&&&&&&&&public&int&getCount()&{
&&&&&&&&&&&&//返回图片数组大小
&&&&&&&&&&&&return&pics.
&&&&&&&&@Override
&&&&&&&&public&Object&getItem(int&position)&{
&&&&&&&&&&&&//根据选中项返回索引位置
&&&&&&&&&&&&return&
&&&&&&&&@Override
&&&&&&&&public&long&getItemId(int&position)&{
&&&&&&&&&&&&//根据选中项id返回索引位置
&&&&&&&&&&&&return&
&&&&&&&&//未优化的getView,这部分可以使用recycle()释放内存、或者BitmapFacotry.Options缩小,或者软引用,或者控制图片资源大小等等很多方法,找时间专门写
&&&&&&&&@Override
&&&&&&&&public&View&getView(int&position,&View&convertView,&ViewGroup&parent)&{
&&&&&&&&&&&&ImageView&img&=&new&ImageView(context);
&&&&&&&&&&&&img.setAdjustViewBounds(true);
&&&&&&&&&&&&img.setImageResource(pics[position]);
&&&&&&&&&&&&img.setScaleType(ImageView.ScaleType.FIT_XY);
&&&&&&&&&&&&img.setLayoutParams(new&Gallery.LayoutParams(120,120));
&&&&&&&&&&&&
&&&&&&&&&&&&return&
&&&&&&&&}&&&&
}运行效果:原理都是一样,只不过是布局加载的时候会有区别,不过就这个小区别也让人够恼火的了文章精选:
上一篇: 一、ViewHolder方式 如果你还没听说过ViewHolder,那么你该去好好看看官方文档了,而不是埋头写代码。 一个ListView的item布局中需要赋值的子元素太多为了避免重复的调用FindViewById方法,我们一般考虑使用ViewHolder方式来实现BaseAdapter。 如下: //在外
下一篇: 最近在做一个从图库选择图片或拍照,然后裁剪的功能.本来是没问题的,一直在用 Intent intent=new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI); 的方式来做,是调用系统图库来做,但是发现如果有图片是同步到go

我要回帖

更多关于 listview上拉加载更多 的文章

 

随机推荐