Android_ListView_Adapter使用和数据动态加载

来源:互联网 发布:网络电视打不开 编辑:程序博客网 时间:2024/05/13 05:51

1.ListView概述

引用:ListView是比较常用的控件,其存在的最根本的原因在于它的高效,ListView通过对象的复用从而减少内存的消耗,也减少了对象的创建从而也减少的cpu的消耗(在Androidk中创建View对象经常伴随着解析xml)。ListView的本质是一张bitmap(当然所有的控件文字等在屏幕上看到的最终都会变成bitmap),ListView会按照需求,根据Adapter提供的信息把需要的Item画出来显示在屏幕上,当屏幕滚动的时候会重新计算Item的位置并绘制出新的bitmap显示在屏幕上。这样听起来感觉可能不是很高效,但这样带的好处就是,每用为一第个Item 创建一个View对象,样式一样的对象可以共用一个View对象,减少了内存的消耗。而且ListView是事件驱动的,只有当需要的时候才会重新绘制,并且只会 绘制当前屏幕上所显示的Items.

2.ListView有关的三要素

(1).ListVeiw

用来展示列表的View,如果继承了ListActivity则使用getListView()得到listView对象

(2).Adapter

用来把数据映射到ListView上的中介,常用的有ArrayAdapter,SimpleAdapter,CursorAdapter和SimpleCursorAdapter.BaseAdapter

1).ArrayAdapter

构造函数objects接收一个集合或者数组,将会按照集合的元素(或者数组的子集)逐条在ListView列出,一个一行;

[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. //ArrayAdapter Constructor  
  2. {  
  3.     new ArrayAdapter(Context context, //The current context.  
  4.             int resource,   /* 
  5.                                 The resource ID for a layout file containing a layout to use when instantiating views 
  6.                                 例如:android.R.layout.simple_list_item_single_choice 
  7.                             */  
  8.             List<T> objects)      //数据对象  
  9. }  

2).CursorAdapter

Adapter that exposes data from a Cursor to a  ListView widget. The Cursor must include  a column named "_id" or this class will not work;

3).SimpleAdapter

有最好的扩充性,通过自定义xml样式文件,达到自定义的列表文件

[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. //SimpleAdapter Constructor  
  2. {  
  3.     SimpleAdapter (Context context, // 上下文  
  4.             List<? extends Map<String, ?>> data,  
  5.                             /* 
  6.                              * A List of Maps.每个list元素就是一列 
  7.                              * Map集合中的key集合,应该包含后面参数(from)中每个元素 
  8.                              */  
  9.             int resource,   //为view layout定义的一列,其中应该包含后面参数(to)中每个元素  
  10.             String[] from,  //从data引出的某些列名  
  11.             int[] to)       //从resource对应的layout文件中,找到相应的id而组成的数组  
  12. }  

4).SimpleCursorAdapter

可以理解为SimpleAdapter对数据库的简单结合,可以方面的把数据库的内容以列表的形式展示出来。

5).BaseAdapter

[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. /** 
  2.  * 自定义适配器,常见将Cursor或者其他的数据存储在一个集合中,效率提高! 
  3.  * 
  4.  */  
  5. private class MyAdapter extends BaseAdapter {  
  6.     private List<String> list;  
  7.     //为该适配器设置展现的数据,当我们为该适配器指定了新的数据后,应该调用notifyDataSetChanged()方法后才能完成数据的动态加载  
  8.     public void setList( List<String> list){  
  9.         this.list = list;  
  10.     }  
  11.     @Override  
  12.     public int getCount() {  
  13.         return list.size();  
  14.     }  
  15.   
  16.     @Override  
  17.     public Object getItem(int position) {  
  18.         return list.get(position);  
  19.     }  
  20.   
  21.     @Override  
  22.     public long getItemId(int position) {  
  23.         return position;  
  24.     }  
  25.   
  26.     //重要方法,用于展现该listview的item条目  
  27.     @Override  
  28.     public View getView(int position, View convertView, ViewGroup parent) {  
  29.         /* 
  30.          * convertView为一个item条目对象,每个item滑过之后,创建的item对象有被重新销毁,为此安卓提供一种机制, 
  31.          * 创建的条目不被销毁而是供后来展现的item重复使用,大大提高了效率 
  32.          */  
  33.         TextView textView = null;  
  34.         if (convertView == null) {  //如果没有可供重复使用的item View对象  
  35.             textView = new TextView(getActivity());  
  36.             /* 
  37.              * 里面包含一种高效的处理机制,当每个item比较复杂,如果重复的执行类型转换、查找控件等操作,将会很大浪费, 
  38.              * 可以定义一个类,专门用来存放控件对象的引用。后面的例子键会介绍到 
  39.              */  
  40.         } else {  
  41.             textView = (TextView) convertView;  //如果已经加载将重复使用  
  42.         }  
  43.         textView.setText(list.get(position));  
  44.         textView.setPadding(20202020);  
  45.         textView.setBackgroundColor(Color.GREEN);  
  46.         return textView;  
  47.     }  
  48. }  

(3).Data数据

List集合或者一个Cursor实例对象。但是如果查询数据库,将会很耗时,因此将使用loaderManager进行统一的管理,异步完成Cursor到数据集合的转化,可参考使用LoaderManager管理Loader实现异步动态加载数据一文。

3.ListView的id说明

(1).ListActivity子类

如果java类继承了ListActivity,那么表明该类只能存在一个ListView控件,可以通过getListView()方法取得默认的控件,但是在相应的xml文件中,定义的ListView必须指明固定的id,android:id="@android:id/list"

(2).Activity子类

如果java类继承了Activity,那么id就没有特定的要求,xml支持自定义id

4.ListView的滚动事件

(1).AbsListView.OnScrollListener事件类型

事件常量常量值描述SCROLL_STATE_IDLE

0

当前item处于空闲状态,没有发生滚动

SCROLL_STATE_TOUCH_SCROLL

1

item正在滚动,但是手指还停留在屏幕上

SCROLL_STATE_FLING

2

类似惯性,当前item正在滚动

 (2).OnScrollListener方法

[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. listView.setOnScrollListener(new AbsListView.OnScrollListener() {  
  2.       
  3.     @Override  
  4.     public void onScrollStateChanged(AbsListView view, int scrollState) {  
  5.         //监听listView的状态是否改变  
  6.     }  
  7.       
  8.     @Override  
  9.     public void onScroll(AbsListView view, int firstVisibleItem,  
  10.             int visibleItemCount, int totalItemCount) {  
  11.         //在滚动的过程中会触发该事件  
  12.     }  
  13. });  

(3).下拉刷新底部

[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. listView.setOnScrollListener(new OnScrollListener() {  
  2.     private boolean isBottom = false;   //用于标记是否到达顶端  
  3.     //listview的状态发送改变时执行  
  4.     @Override  
  5.     public void onScrollStateChanged(AbsListView view, int scrollState) {  
  6.         System.out.println("scrollState:"+scrollState);  
  7.         if(isBottom && scrollState==OnScrollListener.SCROLL_STATE_IDLE){  
  8.             System.out.println("数据加载");  
  9.             //简单模拟数据加载过程  
  10.             for(int j=0; j<10; j++){  
  11.                 Map<String, String> map = new HashMap<String, String>();  
  12.                 map.put("id", String.valueOf((i++)));  
  13.                 map.put("name""newName="+i);  
  14.                 map.put("age", String.valueOf(i));  
  15.                 adapter.getList().add(map);  
  16.             }  
  17.             adapter.notifyDataSetChanged();  
  18.             isBottom = false;  
  19.         }  
  20.     }  
  21.     //在滚动的过程中不断执行  
  22.     @Override  
  23.     public void onScroll(AbsListView view, int firstVisibleItem,  
  24.             int visibleItemCount, int totalItemCount) {  
  25.         System.out.println(firstVisibleItem+":"+visibleItemCount+":"+totalItemCount);  
  26.         if(firstVisibleItem+visibleItemCount == totalItemCount){  
  27.             isBottom = true;  
  28.         }else{  
  29.             isBottom = false;  
  30.         }  
  31.     }  
  32. });  

5.ListView数据的动态刷新

(1).通过重启loader

ListView动态更新应用很广,比如执行添加或者删除后,数据的动态更新展现。为了达到这种目的,不得不提到适配器的notifyDataSetChanged()方法,有时可能读者在使用的过程中,会发现即便调用了该方法数据并没有实时的更新,先别急,后面将分析原因。

下面一个应用,在主Activity中EditText中添加一条数据,在其内部的ListFragment动态更新数据。

[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. public class MainActivity extends Activity {  
  2.   
  3.     private FragmentManager manager;  
  4.     private Button button;  
  5.     @Override  
  6.     protected void onCreate(Bundle savedInstanceState) {  
  7.         super.onCreate(savedInstanceState);  
  8.         setContentView(R.layout.activity_main);  
  9.         manager = getFragmentManager();  
  10.         button = (Button) findViewById(R.id.confirm);  
  11.   
  12.         //将ListFragment添加进主Activity中,如果没有使用布局加载一个ListView对象  
  13.         if (manager.findFragmentByTag("right") == null) {  
  14.             manager.beginTransaction()  
  15.                 .replace(R.id.right, new RightFrag(), "right")  
  16.                 .addToBackStack("right")  
  17.             .commit();  //事务提交  
  18.         }  
  19.           
  20.         button.setOnClickListener(new View.OnClickListener() {  
  21.             @Override  
  22.             public void onClick(View v) {  
  23.                 //使用内容提供者,添加数据  
  24.                 Uri uri = Uri.parse("content://com.baidu.provider/music");  
  25.                 ContentValues values = new ContentValues();  
  26.                 values.put("name", ((EditText) findViewById(R.id.name)).getText().toString());  
  27.                 Uri u = getContentResolver().insert(uri, values);  
  28.                   
  29.                 //判断数据是否添加成功  
  30.                 if (u != null) {  
  31.                     Toast.makeText(MainActivity.this"添加成功!"1).show();  
  32.                     /* 
  33.                      * 重启loader对象,完成数据的动态加载, 
  34.                      *  读者可能遇到一个问题,数据时重新加载了,但是listView的item重新回到了第一个item位置, 
  35.                      *  这是因为我们在重启的过程中,又为该listView设置了适配器,只要不重新设置,item的位置不会改变 
  36.                      */  
  37.                     getLoaderManager().restartLoader(  
  38.                             1,              //该loaderManger管理下的Id为1的loader  
  39.                             null,           //传递参数bundle,常为null  
  40.                             (RightFrag) (getFragmentManager().findFragmentByTag("right")));  
  41.                             //LoaderManager.LoaderCallbacks的回掉函数,由于该ListFragment实现了该接口  
  42.                 } else {  
  43.                     Toast.makeText(MainActivity.this"添加失败"1).show();  
  44.                 }  
  45.             }  
  46.         });  
  47.     }  
  48. }  
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. public class RightFrag extends ListFragment implements LoaderCallbacks<Cursor> {  
  2.     private LoaderManager manager;  
  3.     private MyAdapter adapter;  
  4.     private List<String> list;    //用于存放数据库数据,这里每个item只简单展现一条文本数据  
  5.   
  6.     //完成一些初始化操作  
  7.     @Override  
  8.     public void onCreate(Bundle savedInstanceState) {  
  9.         super.onCreate(savedInstanceState);  
  10.         manager = getLoaderManager();  
  11.         list = new ArrayList<String>();  
  12.           
  13.         adapter = new MyAdapter();  //创建自定义适配器  
  14.         /* 
  15.          * 为该listView设置adapter,如果普通的listView使用setAdapter()方法 
  16.          * 如果该方法在Cursor数据查询完成后设置,listView的将会查询回到第一个。 
  17.          */  
  18.         setListAdapter(adapter);      
  19.         manager.initLoader(1nullthis);  //初始化一个loader对象  
  20.     }  
  21.     /*完成layout布局文件的加载并返回, 
  22.      * 该方法不用重写,由于ListFragment已经默认返回一个listView对象 
  23.     @Override 
  24.     public View onCreateView(LayoutInflater inflater, ViewGroup container, 
  25.             Bundle savedInstanceState) { 
  26.         View view = inflater.inflate(R.layout.list, null); 
  27.         return view; 
  28.     }*/  
  29.   
  30.     //使用内容提供者,返回loader对象  
  31.     @Override  
  32.     public Loader<Cursor> onCreateLoader(int id, Bundle args) {  
  33.         Uri uri = Uri.parse("content://com.baidu.provider/music");  
  34.         //CursorLoader是AsyncTaskLoader的子类,异步查询  
  35.         return new CursorLoader(getActivity(), uri, new String[] { "name" },  
  36.                 nullnullnull);  
  37.     }  
  38.   
  39.     @Override  
  40.     public void onLoadFinished(Loader<Cursor> loader, Cursor data) {  
  41.         /* 
  42.          * 将list数据清空 
  43.          * 如果数据量很大,这种操作就有问题,如果只有增加,我们就不要清空, 
  44.          *  只需要记录上次查询的id,这次查询满足_id > id即可,提高效率 
  45.          */  
  46.         list.clear();  
  47.         while (data.moveToNext()) {  
  48.             list.add(data.getString(data.getColumnIndex("name")));  
  49.         }  
  50.         /* 
  51.          * 使用该方法应该注意,如果数据库的数据发送改变,listView不能动态更新, 
  52.          *  只有适配器的对应的list数据发生了改变,调用该方法才能达到更新的效果 
  53.          */  
  54.         adapter.notifyDataSetChanged();  
  55.     }  
  56.   
  57.     @Override  
  58.     public void onLoaderReset(Loader<Cursor> loader) {  
  59.     }  
  60.     /** 
  61.      * 自定义适配器,常见将Cursor或者其他的数据存储在一个集合中,效率提高! 
  62.      * 
  63.      */  
  64.     private class MyAdapter extends BaseAdapter {  
  65.         @Override  
  66.         public int getCount() {  
  67.             return list.size();  
  68.         }  
  69.       
  70.         @Override  
  71.         public Object getItem(int position) {  
  72.             return list.get(position);  
  73.         }  
  74.       
  75.         @Override  
  76.         public long getItemId(int position) {  
  77.             return position;  
  78.         }  
  79.       
  80.         @Override  
  81.         public View getView(int position, View convertView, ViewGroup parent) {  
  82.             /* 
  83.              * convertView为一个item条目对象,每个item滑过之后,创建的item对象有被重新销毁,为此安卓提供一种机制, 
  84.              * 创建的条目不被销毁而是供后来展现的item重复使用,大大提高了效率 
  85.              */  
  86.             View view = null;  
  87.             if (convertView == null) {  //如果没有可供重复使用的item View对象  
  88.                 view = getActivity().getLayoutInflater().inflate(R.layout.item, null);  
  89.                 //如果view的布局很复杂,可以将内部的控件保存下来  
  90.                 TextView textView = (TextView) view.findViewById(R.id.text);  
  91.                   
  92.                 ViewSet set = new ViewSet();  
  93.                 set.textView = textView;  
  94.                 view.setTag(set);  
  95.             } else {  
  96.                 view = convertView; //如果已经加载将重复使用  
  97.             }  
  98.             //不用重复的查找控件  
  99.             ViewSet views = (ViewSet) view.getTag();  
  100.             views.textView.setText(list.get(position));  
  101.             return view;  
  102.         }  
  103.     }  
  104.     //保存item控件  
  105.     static class ViewSet{  
  106.         TextView textView;  
  107.     }  
  108. }  

(2).使用观察者模式

利用观察者模式,用于观察数据的变化。在设计内容提供者时,查询数据应该注册一个观察者,观察数据的变化。当在增删改时,再通知这种改变。该方法比上面重启loader要高效,应为使用的是同一个cursor对象。

[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. public void setNotificationUri(ContentResolver cr, Uri notifyUri) {    
  2.     mContentResolver = cr;    
  3.     mNotifyUri = notifyUri;    
  4.     mSelfObserver = new SelfContentObserver(this);   
  5.     //内部实际上也是注册了一个观察者  
  6.     mContentResolver.registerContentObserver(mNotifyUri, true, mSelfObserver);    
  7. }  
上面方法时cursor.setNotificationUri() 内部实现,即注册了一个观察者,当数据发生改版时,再通知。
[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. public class DBProvider extends ContentProvider{  
  2.     private ContentResolver contentResolver;  
  3.     @Override  
  4.     public Cursor query(Uri uri, String[] projection, String selection,  
  5.             String[] selectionArgs, String sortOrder) {  
  6.         switch (MATCHER.match(uri)) {  
  7.         case 2:  
  8.             SQLiteDatabase db = myDB.getWritableDatabase();  
  9.             Cursor cursor = db.query("music", projection, selection, nullnullnullnull);  
  10.             /* 
  11.              * cursor设置uri监听数据变化,使用了监听者模式 
  12.              * 内部实际上为contentResolver注册了一个观察者 
  13.              */  
  14.             cursor.setNotificationUri(contentResolver, uri);  
  15.             return cursor;  
  16.         }  
  17.         return null;  
  18.     }     
  19.     @Override  
  20.     public Uri insert(Uri uri, ContentValues values) {  
  21.         switch (MATCHER.match(uri)) {  
  22.         case 2:  
  23.             SQLiteDatabase db = myDB.getWritableDatabase();  
  24.             long id = db.insert("music"null, values);  
  25.             if(id > 0){  
  26.                 //数据发生改变,发出通知  
  27.                 contentResolver.notifyChange(uri, null);  
  28.             }  
  29.             return ContentUris.withAppendedId(uri, id);  
  30.         }  
  31.         return null;  
  32.     }  
  33.     //...  
  34. }  

 6.简单适配器的使用

[java] view plain copy 在CODE上查看代码片派生到我的代码片
  1. /** 
  2.  * ListViewTest.java 
  3.  * @author Administrator 
  4.  * 
  5.  */  
  6. public class MainActivity extends ListActivity {  
  7.     private ListView listView;  
  8.     private List<Map<String, String>> resource;  
  9.   
  10.     @Override  
  11.     protected void onCreate(Bundle savedInstanceState) {  
  12.         super.onCreate(savedInstanceState);  
  13.         setContentView(R.layout.activity_main);  
  14.           
  15.         get();  
  16.         listView = this.getListView();//由于继承了ListActivity,可以直接得到listView控件,但是前提xml文件中需指定默认id  
  17.           
  18. ////////method1()     
  19.         listView.setAdapter(new SimpleAdapter(MainActivity.this, resource,  
  20.                 R.layout.item, new String[] { "name""info" }, new int[] {  
  21.                         R.id.name, R.id.info }));  
  22.         listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);    //设定后才可选中  
  23. ////////method2()  
  24.         listView.setAdapter(new ArrayAdapter<String>(this,  
  25.                 android.R.layout.simple_list_item_single_choice, new String[] {  
  26.                         "河南""湖北""北京""上海""河南""湖北""北京""上海""河南",  
  27.                         "湖北""北京""上海""河南""湖北""北京""上海" }));  
  28.         listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);  
  29.     }  
  30.     public void get() {  
  31.         resource = new ArrayList<Map<String, String>>();  
  32.   
  33.         Map<String, String> map1 = new HashMap<String, String>();  
  34.         map1.put("name""小李飞刀");  
  35.         map1.put("info""good!");  
  36.         resource.add(map1);  
  37.   
  38.         Map<String, String> map2 = new HashMap<String, String>();  
  39.         map2.put("name""北京爱情故事");  
  40.         map2.put("info""ok!");  
  41.         resource.add(map2);  
  42.   
  43.         Map<String, String> map3 = new HashMap<String, String>();  
  44.         map3.put("name""亮剑");  
  45.         map3.put("info""22~~~~~~~~");  
  46.         resource.add(map3);  
  47.     }  
  48. }  
[html] view plain copy 在CODE上查看代码片派生到我的代码片
  1. <!-- activity_main.xml -->  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     xmlns:tools="http://schemas.android.com/tools"  
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="match_parent"  
  6.     android:orientation="vertical" >  
  7.       
  8.     <LinearLayout android:orientation="horizontal"  
  9.         android:layout_width="match_parent"  
  10.         android:layout_height="wrap_content">  
  11.         <TextView android:layout_height="wrap_content"  
  12.             android:layout_width="match_parent"  
  13.             android:layout_weight="1"  
  14.             android:text="@string/name"  
  15.             android:layout_marginLeft="3sp"/>  
  16.         <TextView android:layout_height="wrap_content"  
  17.             android:layout_width="match_parent"  
  18.             android:layout_weight="1"  
  19.             android:text="@string/age"  
  20.             android:layout_marginLeft="3sp"/>  
  21.     </LinearLayout>  
  22.         <!-- 一定要注意ListView空间的id,详细说明要看本页说明 -->  
  23.     <ListView  
  24.         android:id="@android:id/list"     
  25.         android:layout_width="fill_parent"  
  26.         android:layout_height="match_parent"  
  27.         />  
  28. </LinearLayout>  
[html] view plain copy 在CODE上查看代码片派生到我的代码片
  1. <!-- item.xml -->  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     xmlns:tools="http://schemas.android.com/tools"  
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="match_parent"  
  6.     android:orientation="vertical" >  
  7.   
  8.     <TextView  
  9.         android:id="@+id/name"  
  10.         android:layout_width="match_parent"  
  11.         android:layout_height="wrap_content"  
  12.         android:textSize="20sp"  
  13.         android:layout_marginLeft="3sp" />  
  14.   
  15.     <TextView  
  16.         android:id="@+id/info"  
  17.         android:layout_width="match_parent"  
  18.         android:layout_height="wrap_content"  
  19.         android:textSize="15sp"  
  20.         android:layout_marginLeft="10sp" />  
  21.   
  22. </LinearLayout> 
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 鞋胶把手粘住了怎么办 凉鞋魔术贴长了怎么办 新买的狗一直叫怎么办 刚买的幼犬老叫怎么办 狗狗什么都不吃怎么办 新买的吊扇风小怎么办 夜市卖果汁没电怎么办 榻榻米太长2米45怎么办 木质桌子黏黏的怎么办 白色塑料桌子染色了怎么办 3dmax模型变透明了怎么办 刚养的兔子不吃怎么办 熊猫兔不吃下喝怎么办 熊猫兔感冒了一直打喷嚏怎么办 兔子后腿骨断了怎么办 兔子的腿肿了怎么办 仓鼠喝了牛奶该怎么办 宠物兔不吃不喝怎么办 兔子把木屑吃了怎么办? 小车司机碰瓷大车司机怎么办 在淘宝买到假的护肤品怎么办 淘宝购物发现是假的怎么办 电脑键盘灯不亮不能打字怎么办 海棠兔屁股有屎怎么办 大冒险告白被接受了怎么办剧透微博 大冒险被告白了怎么办 腐书网 大冒险告白被接受了怎么办 006 大冒险告白被接受了怎么办广播剧 coolpad手机解锁图案忘了怎么办 装死兔严重掉毛怎么办 兔子嘴巴磕破了怎么办 嘴巴里面摔烂了怎么办 兔子的鼻子损了怎么办 两个人嘴巴被粘牙糖粘住怎么办 小鸟被老鼠粘粘住了怎么办 小猫被老鼠粘粘住怎么办 羊子嘴巴烂了怎么办 小孩突然嘴肿了怎么办 电视机图像颜色变了 怎么办 冰沙床垫结块了怎么办 冰沙床垫融化了怎么办