当前位置: 代码迷 >> Android >> Android Adapter体系引见
  详细解决方案

Android Adapter体系引见

热度:43   发布时间:2016-05-01 13:47:50.0
Android Adapter体系介绍
Adapter是将数据绑定到UI界面上的桥接类。Adapter负责创建显示每个项目的子View和提供对下层数据的访问。
支持Adapter绑定的UI控件必须扩展AdapterView抽象类。创建自己的继承自AdapterView的控件和创建新的Adapter类来绑定它们是可能的。

一些Android提供的Adapter介绍
在多数情况下,你不需要白手创建自己的Adapter。Android提供了一系列Adapter来将数据绑定到UI Widget上。
因为Android负责提供数据和选择用于显示每个项目的View,所以Adapter能快速地修改要绑定的控件的外观和功能。下面的列表显示了两个最有用和最通用的本地Adapter:
? ArrayAdapter
ArrayAdapter是一个绑定View到一组对象的通用类。默认情况下,ArrayAdapter绑定每个对象的toString值到在layout中预先定义的TextView控件上。可变通的,构造函数允许你使用更加复杂的layout或者通过重写getView方法来扩展类从而使用TextView的替代物(如ImageView或嵌套的layout)。

? SimpleCursorAdapter
SimpleCursorAdapter绑定View到Content Provider查询返回的游标上。指定一个XML layout定义,然后将数据集中的每一列的值绑定到layout中的一个View上。

接下来的章节将深入挖掘这些Adapter类的细节。例子中,提供了绑定数据到ListView上,尽管这个逻辑会和其他一些AdapterView类(如Spinner和Gallery)工作的一样。
使用Adapter进行数据绑定
将Adapter应用到继承自AdapterView类上,你需要调用View的setAdapter方法,传入一个Adapter实例,如下面的片段所示:

ArrayList<String> myStringArray = new ArrayList<String>();

ArrayAdapter<String> myAdapterInstance;

int layoutID = android.R.layout.simple_list_item_1;

myAdapterInstance = new ArrayAdapter<String>(this, layoutID, myStringArray);

myListView.setAdapter(myAdapterInstance);

这个片段显示了最简单的情况,将数组中的字符串绑定到ListView中用于显示每个项目的简单TextView控件上。

接下来的第一个例子显示了如何绑定一组复杂的对象到ListView上,使用一个自定义的layout。第二个例子显示了如何使用SimpleCursorAdapter来绑定查询结果到ListView中的自定义layout上。

在 android开发中列表的使用是十分常见的。google对列表的封装使列表既有显示传统文本列表的能力,也有加入了诸如选择项、复选项等处理事件的能力。这里写一些我这几天对这个问题的理解。

在 android的api中,LIST和adapter都被放在了android.widget包内。包内的具体结构我这里先不展示了,主要侧重列表和 adapter。adapter的作用就是将要在列表内显示的数据和列表本身结合起来。列表本身只完成显示的作用,其实他就是继承自VIEWGROUP 类。但是他又有一个独特的函数就是setAdapter()就是完成了view和adapter的结合。adapter如同其本身含义,其实就是一个适配器,他可以对要显示的数据进行统一的封装,主要是将数据变成view提供给list。

我们先来看看adapter的体系:

public interface Adapter----0层(表示继承体系中的层次)
public interface ExpandableListAdapter---(无所谓层次因为没有其他接口继承实现它)
这是adapter的始祖,其他个性化的adapter均实现它并加入自己的接口。
public interface ListAdapter----1层
public interface SpinnerAdapter----1层
public interface WrapperListAdapter----2层(实现ListAdapter)

以上接口层面上的体系已经完了。可以看出来作为widget view的桥梁adapter其实只分为2种:ListAdapter和SpinnerAdapter以及ExpandableListAdapter。也就是说所有widget也就是基于list和spinne与ExpandableList三种view形式的。

由于在实际使用时,我们需要将数据加入到Adapter,而以接口形式呈现的adapter无法保存数据,于是Adapter就转型为类的模式。
public abstract class BaseAdapter----2层(实现了ListAdapter和SpinnerAdapter)
以抽象类的形式出现构造了类型态下的顶层抽象,包容了List和Spinner
public class ArrayAdapter----3层
public class SimpleAdapter---3层
public class CursorAdapter----3层(CursorAdapter其后还有子类这里先不探讨)

基本体系有了之后,让我们看看顶层Adapter里有哪些方法(只列举常用的):

abstract Object getItem(int position)
abstract int getCount()
abstract long getItemId(int position)
abstract int getItemViewType(int position)
abstract View getView(int position,View convertVeiw,ViewGroup parent)

以上是比较重要的方法,ArrayAdapter他们也是重新实现以上方法的。在实际的开发过程中,往往我们要自己做属于自己的Adapter,以上方法都是需要重新实现的。

ArrayAdapter和SimpleCursorAdapter例子

      使用ArrayAdapter定制To-Do List   
      这个例子将扩展To-Do List工程,以一个ToDoItem对象来储存每一个项目,包含每个项目的创建日期。    

      你将扩展ArrayAdapter类来绑定一组ToDoItem对象到ListView上,并定制用于显示每一个ListView项目的layout。     

      1. 返回到To-Do List工程。创建一个新的ToDoItem类来保存任务和任务的创建日期。重写toString方法来返回一个项目数据的概要。      
      package com.paad.todolist;
      import java.text.SimpleDateFormat;
      import java.util.Date;
     public class ToDoItem {
             String task;
             Date created;
             public String getTask()
              {
                 return task;
                }
             public Date getCreated()
            {
                 return created;
             }
           public ToDoItem(String _task)
             {
                this(_task, new Date(java.lang.System.currentTimeMillis()));
             }
              public ToDoItem(String _task, Date _created)
             {
                  task = _task;
                  created = _created;
              }
              @Override
                public String toString()
                {
                 SimpleDateFormat sdf = new SimpleDateFormat(“dd/MM/yy”);
                 String dateString = sdf.format(created); return “(“ + dateString + “) “ + task;
                }
                 }    

      2. 打开ToDoList Activity,修改ArrayList和ArrayAdapter变量的类型,储存ToDoItem对象而不是字符串。然后,你将修改onCreate方法来更新相应的变量初始化。你还需要更新onKeyListener处理函数来支持ToDoItem对象。     

   1. private ArrayList<ToDoItem> todoItems; 
   2. private ListView myListView;  
   3. private EditText myEditText;  
   4. private ArrayAdapter<ToDoItem> aa;  
   5. @Override public void onCreate(Bundle icicle) { 
   6.  super.onCreate(icicle); // Inflate your view setContentView(R.layout.main); //   
   7.  Get references to UI widgets myListView = (ListView)findViewById(R.id.myListView); 
   8.     myEditText = (EditText)findViewById(R.id.myEditText);  
   9.     todoItems = new ArrayList<ToDoItem>();  
  10.     int resID = R.layout.todolist_item; aa = new ArrayAdapter<ToDoItem>(this, resID, todoItems);  
  11.     myListView.setAdapter(aa); 
  12.  myEditText.setOnKeyListener(new OnKeyListener() {  
  13. public boolean onKey(View v, int keyCode, KeyEvent event) { 
  14.  if (event.getAction() == KeyEvent.ACTION_DOWN) 
  15.    if (keyCode == KeyEvent.KEYCODE_DPAD_CENTER) {  
  16.    ToDoItem newItem; newItem = new ToDoItem(myEditText.getText().toString()); todoItems.add(0, newItem); 
  17.     myEditText.setText(“”);  
  18.     aa.notifyDataSetChanged(); cancelAdd(); return true;  
  19.       }  
  20.     return false;  
  21.     } 
  22.   }); 
  23.  registerForContextMenu(myListView);  
  24. }  



3. 如果你运行Activity,它将显示每个to-do项目,如图5-3所示。

图5-3

4. 现在,你可以创建一个自定义的layout来显示每一个to-do项目。修改在第4章中创建的自定义layout,包含另外一个TextView,它将用于显示每个to-do项目的创建日期。

Java代码

   1. import java.text.SimpleDateFormat;   
   2.  
   3. import android.content.Context;   
   4.  
   5. import java.util.*;    
   6.  
   7. import android.view.*;   
   8.  
   9.  import android.widget.*;    
  10.  
  11. public class ToDoItemAdapter extends ArrayAdapter<ToDoItem> { int resource; public ToDoItemAdapter(Context _context,int _resource, List<ToDoItem> _items) {    
  12.  
  13. super(_context, _resource, _items); resource = _resource;   
  14.  
  15.  }    
  16.  
  17.  @Override public View getView(int position, View convertView,  ViewGroup parent) {    
  18.  
  19.   LinearLayout todoView; ToDoItem item = getItem(position);    
  20.  
  21.   String taskString = item.getTask();    
  22.  
  23.   Date createdDate = item.getCreated();    
  24.  
  25.   SimpleDateFormat sdf = new SimpleDateFormat(“dd/MM/yy”);    
  26.  
  27.   String dateString = sdf.format(createdDate); if (convertView == null) { todoView = new LinearLayout(getContext());    
  28.  
  29.   String inflater = Context.LAYOUT_INFLATER_SERVICE;    
  30.  
  31.   LayoutInflater vi; vi = (LayoutInflater)getContext().getSystemService(inflater); vi.inflate(resource, todoView, true);    
  32.  
  33. }    
  34.  
  35. else {   
  36.  
  37.  todoView = (LinearLayout) convertView;    
  38.  
  39. }    
  40.  
  41.   TextView dateView = (TextView)todoView.findViewById (R.id.rowDate);    
  42.  
  43.  TextView taskView = (TextView)todoView.findViewById(R.id.row);      dateView.setText(dateString);   
  44.  
  45.     taskView.setText(taskString);   
  46.  
  47.     return todoView;    
  48.  
  49.   }    
  50.  
  51. }  

import java.text.SimpleDateFormat; 

import android.content.Context; 

import java.util.*;  

import android.view.*; 

import android.widget.*;  

public class ToDoItemAdapter extends ArrayAdapter<ToDoItem> { int resource; public ToDoItemAdapter(Context _context,int _resource, List<ToDoItem> _items) {  

super(_context, _resource, _items); resource = _resource; 

}  

@Override public View getView(int position, View convertView,  ViewGroup parent) {  

  LinearLayout todoView; ToDoItem item = getItem(position);  

  String taskString = item.getTask();  

  Date createdDate = item.getCreated();  

  SimpleDateFormat sdf = new SimpleDateFormat(“dd/MM/yy”);  

  String dateString = sdf.format(createdDate); if (convertView == null) { todoView = new LinearLayout(getContext());  

  String inflater = Context.LAYOUT_INFLATER_SERVICE;  

  LayoutInflater vi; vi = (LayoutInflater)getContext().getSystemService(inflater); vi.inflate(resource, todoView, true);  

}  

else { 

todoView = (LinearLayout) convertView;  

}  

  TextView dateView = (TextView)todoView.findViewById (R.id.rowDate);  

TextView taskView = (TextView)todoView.findViewById(R.id.row);      dateView.setText(dateString); 

    taskView.setText(taskString); 

    return todoView;  

  }  

}





5. 创建一个新的类(ToDoItemAdapter),使用指定的ToDoItem变量来扩展一个ArrayAdapter。重写getView方法来将ToDoItem对象中的task和date属性指定给第4步创建的layout中的View。



Java代码

   1. import java.text.SimpleDateFormat;   
   2.  
   3. import android.content.Context;   
   4.  
   5. import java.util.*;    
   6.  
   7. import android.view.*;   
   8.  
   9.  import android.widget.*;    
  10.  
  11. public class ToDoItemAdapter extends ArrayAdapter<ToDoItem> { int resource; public ToDoItemAdapter(Context _context,int _resource, List<ToDoItem> _items) {    
  12.  
  13. super(_context, _resource, _items); resource = _resource;   
  14.  
  15.  }    
  16.  
  17.  @Override public View getView(int position, View convertView,  ViewGroup parent) {    
  18.  
  19.   LinearLayout todoView; ToDoItem item = getItem(position);    
  20.  
  21.   String taskString = item.getTask();    
  22.  
  23.   Date createdDate = item.getCreated();    
  24.  
  25.   SimpleDateFormat sdf = new SimpleDateFormat(“dd/MM/yy”);    
  26.  
  27.   String dateString = sdf.format(createdDate); if (convertView == null) { todoView = new LinearLayout(getContext());    
  28.  
  29.   String inflater = Context.LAYOUT_INFLATER_SERVICE;    
  30.  
  31.   LayoutInflater vi; vi = (LayoutInflater)getContext().getSystemService(inflater); vi.inflate(resource, todoView, true);    
  32.  
  33. }    
  34.  
  35. else {   
  36.  
  37.  todoView = (LinearLayout) convertView;    
  38.  
  39. }    
  40.  
  41.   TextView dateView = (TextView)todoView.findViewById (R.id.rowDate);    
  42.  
  43.  TextView taskView = (TextView)todoView.findViewById(R.id.row);      dateView.setText(dateString);   
  44.  
  45.     taskView.setText(taskString);   
  46.  
  47.     return todoView;    
  48.  
  49.   }    
  50.  
  51. }  

import java.text.SimpleDateFormat; 

import android.content.Context; 

import java.util.*;  

import android.view.*; 

import android.widget.*;  

public class ToDoItemAdapter extends ArrayAdapter<ToDoItem> { int resource; public ToDoItemAdapter(Context _context,int _resource, List<ToDoItem> _items) {  

super(_context, _resource, _items); resource = _resource; 

}  

@Override public View getView(int position, View convertView,  ViewGroup parent) {  

  LinearLayout todoView; ToDoItem item = getItem(position);  

  String taskString = item.getTask();  

  Date createdDate = item.getCreated();  

  SimpleDateFormat sdf = new SimpleDateFormat(“dd/MM/yy”);  

  String dateString = sdf.format(createdDate); if (convertView == null) { todoView = new LinearLayout(getContext());  

  String inflater = Context.LAYOUT_INFLATER_SERVICE;  

  LayoutInflater vi; vi = (LayoutInflater)getContext().getSystemService(inflater); vi.inflate(resource, todoView, true);  

}  

else { 

todoView = (LinearLayout) convertView;  

}  

  TextView dateView = (TextView)todoView.findViewById (R.id.rowDate);  

TextView taskView = (TextView)todoView.findViewById(R.id.row);      dateView.setText(dateString); 

    taskView.setText(taskString); 

    return todoView;  

  }  

}





6. 最后,用ToDoItemAdapter替换ArrayAdapter的定义。



private ToDoItemAdapter aa;



在onCreate中,使用new ToDoItemAdapter来替换ArrayAdapter<String>的实例化。



aa = new ToDoItemAdapter(this, resID, todoItems);



7. 如果你运行Activity,它看起来如图5-4的截图。






图5-4



使用 SimpleCursorAdapter



SimpleCursorAdapter允许你绑定一个游标的列到ListView上,并使用自定义的layout显示每个项目。



SimpleCursorAdapter的创建,需要传入当前的上下文、一个layout资源,一个游标和两个数组:一个包含使用的列的名字,另一个(相同大小)数组包含View中的资源ID,用于显示相应列的数据值。



下面的框架代码显示了如何构造一个SimpleCursorAdapter来显示联系人信息:

Java代码

   1. String uriString = “content://contacts/people/”;    
   2. Cursor myCursor = managedQuery(Uri.parse(uriString), null, null, null, null);    
   3. String[] fromColumns = new String[] {   
   4.     People.NUMBER,    
   5.     People.NAME   
   6. };   
   7.  int[] toLayoutIDs = new int[] {    
   8.      R.id.nameTextView,   
   9.      R.id.numberTextView   
  10. };    
  11.    
  12. SimpleCursorAdapter myAdapter; myAdapter = new SimpleCursorAdapter(this,R.layout.simplecursorlayout,myCursor,fromColumns,toLayoutIDs) 

String uriString = “content://contacts/people/”;  
Cursor myCursor = managedQuery(Uri.parse(uriString), null, null, null, null);  
String[] fromColumns = new String[] { 
    People.NUMBER,  
    eople.NAME 
}; 
int[] toLayoutIDs = new int[] {  
     R.id.nameTextView, 
     R.id.numberTextView 
};  
 
SimpleCursorAdapter myAdapter; myAdapter = new SimpleCursorAdapter(this,R.layout.simplecursorlayout,myCursor,fromColumns,toLayoutIDs)



SimpleCursorAdapter在本章前面的创建选择联系人的例子中使用过。你将在第6章学习到更多关于Content Provider和Cursor的内容,那里你也将找到更多SimpleCursorAdapter的例子。
  相关解决方案