A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始






~爱上海,爱黑马~




Android基础

    pull解析XML文件

    Android推荐使用pull解析XML文件,与SAX解析XML文件类似,都是事件驱动类型的解析方式。

    示例:获取天气信息。



    res\layout\activity_main.xml
  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2.     xmlns:tools="http://schemas.android.com/tools"
  3.     android:layout_width="match_parent"
  4.     android:layout_height="match_parent"
  5.     tools:context=".MainActivity" >

  6.     <Button
  7.         android:layout_width="wrap_content"
  8.         android:layout_height="wrap_content"
  9.         android:text="获取天气信息"
  10.         android:onClick="click"/>

  11. </RelativeLayout>
复制代码

    src/weather.xml
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <weather>
  3.         <city>
  4.                 <name>西安</name>
  5.                 <temp>22°</temp>
  6.                 <pm25>100</pm25>
  7.         </city>
  8.         <city>
  9.                 <name>上海</name>
  10.                 <temp>24°</temp>
  11.                 <pm25>120</pm25>
  12.         </city>
  13.         <city>
  14.                 <name>北京</name>
  15.                 <temp>30°</temp>
  16.                 <pm25>800</pm25>
  17.         </city>
  18. </weather>
复制代码

    src/cn.itcast.pullParser.domain/City.java
  1. package cn.itcast.pullparser.domain;

  2. public class City {

  3.         private String name;
  4.         private String temp;
  5.         private String pm25;
  6.         
  7.         public String getName() {
  8.                 return name;
  9.         }
  10.         public void setName(String name) {
  11.                 this.name = name;
  12.         }
  13.         public String getTemp() {
  14.                 return temp;
  15.         }
  16.         public void setTemp(String temp) {
  17.                 this.temp = temp;
  18.         }
  19.         public String getPm25() {
  20.                 return pm25;
  21.         }
  22.         public void setPm25(String pm25) {
  23.                 this.pm25 = pm25;
  24.         }
  25.         
  26.         @Override
  27.         public String toString() {
  28.                 return "City [name=" + name + ", temp=" + temp + ", pm25=" + pm25 + "]";
  29.         }
  30. }
复制代码

    src/cn.itcast.pullparser/MainActivity.java
  1. package cn.itcast.pullparser;

  2. import java.io.InputStream;
  3. import java.util.ArrayList;
  4. import java.util.List;

  5. import org.xmlpull.v1.XmlPullParser;

  6. import android.app.Activity;
  7. import android.os.Bundle;
  8. import android.util.Xml;
  9. import android.view.View;
  10. import cn.itcast.pullparser.domain.City;

  11. public class MainActivity extends Activity {

  12.         List<City> cityList;
  13.         
  14.         @Override
  15.         protected void onCreate(Bundle savedInstanceState) {
  16.                 super.onCreate(savedInstanceState);
  17.                 setContentView(R.layout.activity_main);
  18.         }
  19.         
  20.         public void click(View v){
  21.                 //获取xml文件
  22.                 InputStream is = getClassLoader().getResourceAsStream("weather.xml");
  23.                
  24.                 //获取pull解析器
  25.                 //XmlPullParser是一个接口,使用Xml.newPullParser()获取XmlPullParser对象
  26.                 XmlPullParser xp = Xml.newPullParser();
  27.                 //初始化
  28.                 //Android系统默认编码是“utf-8”
  29.                 try {
  30.                         xp.setInput(is,"utf-8");
  31.                         
  32.                         //开始解析
  33.                         //获取事件类型,通过对事件类型的判断,直到当前解析的是什么节点
  34.                         int type = xp.getEventType();
  35.                         
  36.                         City city = null;
  37.                         
  38.                         while(type != XmlPullParser.END_DOCUMENT){
  39.                                 
  40.                                 switch(type){
  41.                                         case XmlPullParser.START_TAG:
  42.                                                 //获取当前节点的名字
  43.                                                 if("weather".equals(xp.getName())){
  44.                                                         cityList = new ArrayList<City>();
  45.                                                 }else if("city".equals(xp.getName())){
  46.                                                         city = new City();
  47.                                                 }else if("name".equals(xp.getName())){
  48.                                                         //获取当前节点的下一个节点的文本
  49.                                                         String name = xp.nextText();
  50.                                                         city.setName(name);
  51.                                                 }else if("temp".equals(xp.getName())){
  52.                                                         String temp = xp.nextText();
  53.                                                         city.setTemp(temp);
  54.                                                 }else if("pm25".equals(xp.getName())){
  55.                                                         String pm25 = xp.nextText();
  56.                                                         city.setPm25(pm25);
  57.                                                 }
  58.                                                 break;
  59.                                         case XmlPullParser.END_TAG:
  60.                                                 if("city".equals(xp.getName())){
  61.                                                         cityList.add(city);
  62.                                                 }
  63.                                                 break;
  64.                                 }
  65.                                 
  66.                                 //把指针移动至下一个节点,并返回该节点的事件类型
  67.                                 type = xp.next();
  68.                         }
  69.                 } catch (Exception e) {
  70.                         e.printStackTrace();
  71.                 }
  72.                
  73.                 for(City c:cityList){
  74.                         System.out.println(c.toString());
  75.                 }
  76.         }
  77. }
复制代码
    运行结果:





    用debug查看pull解析流程

    首先,双击代码左侧,打一个断点。



    点击debug “01_pull解析XML文件”。



    等待debug初始化,跳出对话框,不要点“Force close”!等待一会,对话框就会消失。



    点击“获取天气信息”按钮。



    点击“yes”,程序进入debug模式。




    通过“step over”即可以查看代码执行的每一步。



    测试概念

    按岗位分:
        黑盒测试:测试业务逻辑。
        白盒测试:测试逻辑方法。

    按测试粒度分:
        方法测试 function   
        单元测试 unit:多个方法集成一个单元,测试。  
        集成测试 intergration:多个单元集成,测试。
        系统测试 system:服务器端、客户端端联动,测试整个系统。

    按暴力程度分:
        冒烟测试 smoke
        压力测试 pressure:针对服务器端的测试。
   
    目前的智能手机都有测试框架,例如,Android自带的monkey,不过需要在Android命令行中使用。

    示例:随机点击模拟器一千次。



进入测试状态...



    单元测试



    创建一个类,继承AndroidTestCase。



    src/cn.itcast.junit/Test.java
  1. package cn.itcast.junit;

  2. import cn.itcast.junit.tools.Tools;
  3. import android.test.AndroidTestCase;

  4. public class Test extends AndroidTestCase {

  5.         //定义在测试框架中的方法可以直接运行
  6.         public void test(){
  7.                 int result = Tools.damage(8, 3);
  8.                 //断言,对比实际结果与预期是否一致
  9.                 assertEquals(5, result);
  10.         }
  11. }
复制代码

    src/cn.itcast.junit.tools/Tools.java
  1. package cn.itcast.junit.tools;

  2. public class Tools {
  3.         public static int damage(int i,int j){
  4.                 return i + j;
  5.         }
  6. }
复制代码
   
    使用测试框架需要在清单文件中配置指令集和使用类库。



    两种方式启动测试:

    方法一:在代码区内选择需要测试的方法-->右击Run As-->Android JUnit Test。



    方法二:在Outline内选择需要测试的方法-->右击Run As-->Android JUnit Test。



    通过下图,可以看到,报错,结果与断言不相符。



    修改Tools.java中代码。



    通过下图,可以看到,测试运行成功,结果与断言相符。



    通过Console可以看到测试过程。



    虽然,测试过程中,Android项目并没有启动,整个测试过程可以看到模拟器上根本没有前台界面。但是,测试需要模拟器运行测试框架。因为,测试的项目是Android代码,必须运行在Android设备上,可以是模拟器也可以是真机。

    没有返回值的方法测试步骤相同,只是不需要断言。

    示例:





    测试后,报错,提示出现异常。



    修改代码,测试成功。





    创建数据库

    Android中存储数据用的最多的还是数据库,SQLite(Android自带的轻量级数据库)。

    数据库保存在内部存储空间。所以,在备份数据的时候,不会写在数据库里。一旦应用删除,数据库就没了,备份的数据也就全没了。

    示例:创建数据库



    创建一个类,MyOpenHelper,继承SQLiteOpenHelper。

    src/cn.itcast.sqlite/MyOpenHelper.java
  1. package cn.itcast.sqlite;

  2. import android.content.Context;
  3. import android.database.sqlite.SQLiteDatabase;
  4. import android.database.sqlite.SQLiteDatabase.CursorFactory;
  5. import android.database.sqlite.SQLiteOpenHelper;

  6. public class MyOpenHelper extends SQLiteOpenHelper {

  7.         public MyOpenHelper(Context context, String name, CursorFactory factory,
  8.                         int version) {
  9.                 //第一个参数:用来打开和创建数据库的上下文
  10.                 //第二个参数:数据库文件名字
  11.                 //第三个参数:游标工厂,用来创建游标对象的工厂。如果传null,表示使用默认的游标工厂
  12.                 //第四个参数:数据库的版本,最低为1,如果数据库做升级,版本值只能升,不能降
  13.                 super(context, name, factory, version);
  14.         }

  15.         //数据库创建时,此方法调用
  16.         @Override
  17.         public void onCreate(SQLiteDatabase db) {
  18.                
  19.         }

  20.         //数据库升级时,此方法调用
  21.         @Override
  22.         public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

  23.         }
  24. }
复制代码

    创建一个测试类,继承AndroidTestCase。

    src/cn.itcast.sqlite/MyOpenHelper.java
  1. package cn.itcast.sqlite;

  2. import android.database.sqlite.SQLiteDatabase;
  3. import android.test.AndroidTestCase;

  4. public class Test extends AndroidTestCase {

  5.         public void createDataBase(){
  6.                
  7.                 //创建数据库
  8.                 //1. 创建打开帮助器
  9.                 //测试框架提供了getContext()方法,获取虚拟上下文
  10.                 MyOpenHelper oh = new MyOpenHelper(getContext(), "people.db", null, 1);
  11.                
  12.                 //2. 创建并打开数据库
  13.                 //如果数据库不存在,先创建,后打开。如果数据库存在,直接打开
  14.                 //getWritableDatabase创建的数据库可读可写。
  15.                 //getReadableDatabase返回的数据库也是可读可写。但是,在某些情况下,例如,数据库满了(但是现在,手机内部存储器都比较大,基本上不会出现这种情况),getReadableDatabase就会返回一个只读的数据库。
  16.                 SQLiteDatabase db = oh.getWritableDatabase();
  17.         }
  18. }
复制代码
   
    配置清单文件:



    测试运行结果:



    生成数据库成功。



   导出people.db,拖入SQLite Expert,可以看到自动生成了一张表,此表不能修改,不用管它。



    创建表

    创建数据库完毕后会调用onCreate方法,数据库升级后会调用onUpgrade方法。

    示例:

    src/cn.itcast.sqlite/MyOpenHelper.java
  1. package cn.itcast.sqlite;

  2. import android.content.Context;
  3. import android.database.sqlite.SQLiteDatabase;
  4. import android.database.sqlite.SQLiteDatabase.CursorFactory;
  5. import android.database.sqlite.SQLiteOpenHelper;

  6. public class MyOpenHelper extends SQLiteOpenHelper {

  7.         public MyOpenHelper(Context context, String name, CursorFactory factory,
  8.                         int version) {
  9.                 super(context, name, factory, version);
  10.         }

  11.         //数据库创建完之后,才会调用这个函数
  12.         @Override
  13.         public void onCreate(SQLiteDatabase db) {
  14.                 System.out.println("数据库创建");
  15.         }

  16.         @Override
  17.         public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
  18.                 System.out.println("数据库升级");
  19.         }
  20. }
复制代码
   运行结果:

    首先,删除创建好的数据库,重新创建数据库。


   
    可以看到onCreate方法被调用。

   

    然后,升级数据库版本。



    可以看到onUpgrade方法被调用。



    示例:创建表

    src/cn.itcast.sqlite/MyOpenHelper.java
  1. package cn.itcast.sqlite;

  2. import android.content.Context;
  3. import android.database.sqlite.SQLiteDatabase;
  4. import android.database.sqlite.SQLiteDatabase.CursorFactory;
  5. import android.database.sqlite.SQLiteOpenHelper;

  6. public class MyOpenHelper extends SQLiteOpenHelper {

  7.         public MyOpenHelper(Context context, String name, CursorFactory factory,
  8.                         int version) {
  9.                 super(context, name, factory, version);
  10.         }

  11.         @Override
  12.         public void onCreate(SQLiteDatabase db) {
  13.                 //执行sql语句
  14.                 //Android所有自带的数据库主键都带下划线,入乡随俗
  15.                 //所有字段类型对于SQLite都是varchar类型,sql语句写数据类型是写给程序员看的
  16.                 db.execSQL("create table person(_id integer primary key autoincrement,name char(10),phone char(20),salary integer(10))");
  17.         }

  18.         @Override
  19.         public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
  20.                 System.out.println("数据库升级");
  21.         }
  22. }
复制代码
   
    src/cn.itcast.sqlite/Test.java
  1. package cn.itcast.sqlite;

  2. import android.database.sqlite.SQLiteDatabase;
  3. import android.test.AndroidTestCase;

  4. public class Test extends AndroidTestCase {

  5.         public void createDataBase(){
  6.                 MyOpenHelper oh = new MyOpenHelper(getContext(), "people.db", null, 1);
  7.                 SQLiteDatabase db = oh.getWritableDatabase();
  8.         }
  9. }
复制代码

    测试运行结果:

    首先,删除数据库,重新创建数据库,创建表。然后导出people.db,拖入SQLite Expert,刷新。可以看到,生成了新的person表。





    表格中的RecNo是不存在的字段,只是为了让开发人员能够方便地看到记录行数。

    使用SQL语句插入删除

    示例:

    src/cn.itcast.sqlite/Test.java
  1. package cn.itcast.sqlite;

  2. import android.database.sqlite.SQLiteDatabase;
  3. import android.test.AndroidTestCase;

  4. public class Test extends AndroidTestCase {

  5.         private MyOpenHelper oh;
  6.         private SQLiteDatabase db;

  7.         //测试框架初始化完毕后,测试方法执行前,此方法调用
  8.         @Override
  9.         protected void setUp() throws Exception {
  10.                 super.setUp();
  11.                 oh =  new MyOpenHelper(getContext(), "people.db", null, 1);
  12.                 db = oh.getWritableDatabase();
  13.         }
  14.         
  15.         public void createDataBase(){
  16.                 MyOpenHelper oh = new MyOpenHelper(getContext(), "people.db", null, 1);
  17.                 SQLiteDatabase db = oh.getWritableDatabase();
  18.         }
  19.         
  20.         public void insert(){
  21.                 db.execSQL("insert into person(name,phone,salary) values(?,?,?)",new Object[]{"云鹤",138438,"13000"});
  22.                 db.execSQL("insert into person(name,phone,salary) values(?,?,?)",new Object[]{"云鹤儿子",138438,"13000"});
  23.                 db.execSQL("insert into person(name,phone,salary) values(?,?,?)",new Object[]{"云鹤孙子",138438,"13000"});
  24.                 db.execSQL("insert into person(name,phone,salary) values(?,?,?)",new Object[]{"云鹤曾孙",138438,"13000"});
  25.                 db.execSQL("insert into person(name,phone,salary) values(?,?,?)",new Object[]{"王亚聪",138438,"13000"});
  26.         }
  27.         
  28.         public void delete(){
  29.                 db.execSQL("delete from person where name = ?",new Object[]{"王亚聪"});
  30.         }
  31.         
  32.         //测试方法执行完毕后,执行。
  33.         @Override
  34.         protected void tearDown() throws Exception {
  35.                 super.tearDown();
  36.                 db.close();
  37.         }
  38. }
复制代码
   测试运行结果:

    首先,测试insert方法,插入数据,然后导出people.db,拖入SQLite Expert,刷新。可以看到,插入数据成功。



    然后,测试delete方法,删除一条数据,导出people.db,拖入SQLite Expert,刷新。可以看到,删除数据成功。



    P.S.
    如果将代码调整,如下图,测试insert方法或delete方法,就会报空指针异常。





    原因分析:测试框架需要先被系统创建出来,然后再对它做各个参数的初始化,所有初始化做完之后,虚拟上下文才会存在。但是,private MyOpenHelper oh =  new MyOpenHelper(getContext(), "people.db", null, 1);这条语句是在测试框架构造方法被调用之前调用的,因此,虚拟上下文(getContext方法返回值)根本不存在,获取不到。所以,MyOpenHelper根本new不出来。如此,才会报空指针异常。但是,setUp方法是在测试框架初始化完毕后,测试方法执行前,此方法才被调用。因此,虚拟上下文已经存在,没有任何问题。

    使用SQL语句修改查询

    示例:

    src/cn.itcast.sqlite/Test.java
  1. package cn.itcast.sqlite;

  2. import android.database.Cursor;
  3. import android.database.sqlite.SQLiteDatabase;
  4. import android.test.AndroidTestCase;

  5. public class Test extends AndroidTestCase {

  6.         private MyOpenHelper oh;
  7.         private SQLiteDatabase db;

  8.         @Override
  9.         protected void setUp() throws Exception {
  10.                 super.setUp();
  11.                 oh =  new MyOpenHelper(getContext(), "people.db", null, 1);
  12.                 db = oh.getWritableDatabase();
  13.         }
  14.         
  15.         public void update(){
  16.                 db.execSQL("update person set salary = ? where name = ?",new Object[]{10000,"云鹤"});
  17.         }
  18.         
  19.         public void select(){
  20.                 Cursor cursor = db.rawQuery("select name,salary from person where name = ?", new String[]{"云鹤"});
  21.                 //从游标中取出数据,方法与结果集类似
  22.                 while(cursor.moveToNext()){
  23.                         //只能传入索引值,索引值根据sql语句中查询内容所在的顺序而定,例如,上面的sql语句,name在第一位,索引即为0
  24.                         String name = cursor.getString(0);
  25.                         //可以通过字段名称获取列索引,再通过列索引获取内容
  26.                         String salary = cursor.getString(cursor.getColumnIndex("salary"));
  27.                         System.out.println(name + ":" + salary);
  28.                 }
  29.         }
  30.         
  31.         @Override
  32.         protected void tearDown() throws Exception {
  33.                 super.tearDown();
  34.                 db.close();
  35.         }
  36. }
复制代码
    测试运行结果:

    测试update方法,更新一条数据,导出people.db,拖入SQLite Expert,刷新。可以看到,更新数据成功。



    测试select方法,查询数据,打印出来。可以看到,查询成功。



    使用API完成插入

    使用SQL语句不太方便,可以使用API完成增删改查操作。

    示例:

    src/cn.itcast.sqlite/Test.java
  1. package cn.itcast.sqlite;

  2. import android.content.ContentValues;
  3. import android.database.sqlite.SQLiteDatabase;
  4. import android.test.AndroidTestCase;

  5. public class Test extends AndroidTestCase {

  6.         private MyOpenHelper oh;
  7.         private SQLiteDatabase db;

  8.         @Override
  9.         protected void setUp() throws Exception {
  10.                 super.setUp();
  11.                 oh =  new MyOpenHelper(getContext(), "people.db", null, 1);
  12.                 db = oh.getWritableDatabase();
  13.         }
  14.         
  15.         public void insertApi(){
  16.                 ContentValues values = new ContentValues();
  17.                 values.put("name","亚聪和云鹤");
  18.                 values.put("phone","138888");
  19.                 values.put("salary","99999999");
  20.                 //第一个参数:表名
  21.                 //第二个参数:nullColumnHack,当第三个参数ContentValues对象为null,或者里面没有任何数据时,第二个参数才会有效。开发中,ContentValues都是有值的,所以直接传入null即可
  22.                 //第三个参数:通过键值对把要插入的数据封装至ContentValues对象中,键名必须是字段名
  23.                 //db.insert返回值为行id,如果为-1,表示插入失败
  24.                 long l1 = db.insert("person", null, values);

  25.                 //ContentValues下次使用的时候记得清空
  26.                 values.clear();
  27.                 values.put("name","亚聪和云鹤的儿子");
  28.                 values.put("phone","138888");
  29.                 values.put("salary","99999999");
  30.                 long l2 = db.insert("person", null, values);
  31.                
  32.                 System.out.println(l1 + ":" + l2);
  33.         }
  34.         
  35.         @Override
  36.         protected void tearDown() throws Exception {
  37.                 super.tearDown();
  38.                 db.close();
  39.         }
  40. }
复制代码
    测试运行结果:

    测试insertApi方法,插入一条数据,导出people.db,拖入SQLite Expert,刷新。可以看到,插入数据成功。





    使用API完成删改查

    示例:

    src/cn.itcast.sqlite/Test.java
  1. package cn.itcast.sqlite;

  2. import android.content.ContentValues;
  3. import android.database.Cursor;
  4. import android.database.sqlite.SQLiteDatabase;
  5. import android.test.AndroidTestCase;

  6. public class Test extends AndroidTestCase {

  7.         private MyOpenHelper oh;
  8.         private SQLiteDatabase db;

  9.         @Override
  10.         protected void setUp() throws Exception {
  11.                 super.setUp();
  12.                 oh =  new MyOpenHelper(getContext(), "people.db", null, 1);
  13.                 db = oh.getWritableDatabase();
  14.         }
  15.         
  16.         public void deleteApi(){
  17.                 //返回被删除的行的数量
  18.                 int i = db.delete("person", "name = ?", new String[]{"云鹤儿子"});
  19.                 System.out.println(i);
  20.         }
  21.         
  22.         public void updateApi(){
  23.                 ContentValues values = new ContentValues();
  24.                 values.put("salary",10500);
  25.                 int i = db.update("person", values, "name = ?", new String[]{"云鹤"});
  26.                 System.out.println(i);
  27.         }
  28.         
  29.         public void selectApi(){
  30.                 //第二个参数如果传入null,表示查询所有字段
  31.                 Cursor cursor = db.query("person", null, null, null, null, null, null, null);
  32.                 while(cursor.moveToNext()){
  33.                         String name = cursor.getString(1);
  34.                         String phone = cursor.getString(2);
  35.                         String salary = cursor.getString(3);
  36.                         System.out.println(name + ":" + phone + ":" + salary);
  37.                 }
  38.         }
  39.         
  40.         @Override
  41.         protected void tearDown() throws Exception {
  42.                 super.tearDown();
  43.                 db.close();
  44.         }
  45. }
复制代码
    测试运行结果:

    测试deleteApi方法,删除一条数据,导出people.db,拖入SQLite Expert,刷新。可以看到,删除数据成功。



    测试updateApi方法,更新一条数据,导出people.db,拖入SQLite Expert,刷新。可以看到,更新数据成功。



    测试selectApi方法,查询数据,打印出来。可以看到,查询成功。



    SQLite的事务

   示例:

    src/cn.itcast.sqlite/Test.java
  1. package cn.itcast.sqlite;

  2. import android.content.ContentValues;
  3. import android.database.sqlite.SQLiteDatabase;
  4. import android.test.AndroidTestCase;

  5. public class Test extends AndroidTestCase {

  6.         private MyOpenHelper oh;
  7.         private SQLiteDatabase db;

  8.         @Override
  9.         protected void setUp() throws Exception {
  10.                 super.setUp();
  11.                 oh =  new MyOpenHelper(getContext(), "people.db", null, 1);
  12.                 db = oh.getWritableDatabase();
  13.         }
  14.         
  15.         public void transaction(){
  16.                 try{
  17.                         //开启事务
  18.                         db.beginTransaction();
  19.                         ContentValues values = new ContentValues();
  20.                         values.put("salary", 11000);
  21.                         db.update("person", values, "name = ?", new String[]{"云鹤"});
  22.                         values.put("salary", 12500);
  23.                         db.update("person", values, "name = ?", new String[]{"云鹤孙子"});
  24.                         
  25.                         //如果下面这行代码执行,说明事务执行成功
  26.                         db.setTransactionSuccessful();
  27.                 }catch(Exception e){
  28.                         e.printStackTrace();
  29.                 }finally{
  30.                         //关闭事务,这时候就提交了,不用再次提交
  31.                         //关闭时候的时候,如果发现db.setTransactionSuccessful();语句未执行,那么就会回滚事务
  32.                         db.endTransaction();
  33.                 }
  34.         }
  35.         
  36.         @Override
  37.         protected void tearDown() throws Exception {
  38.                 super.tearDown();
  39.                 db.close();
  40.         }
  41. }
复制代码
   测试运行结果;

    测试transaction方法导出people.db,拖入SQLite Expert,刷新。可以看到,事务执行成功。



    如果对代码作如下修改,事务执行中出现异常。



    可以看到,报异常,并且数据未发生任何变化。





    把数据库中的数据显示至屏幕

    代码:



    src/cn.itcast.showdata/MyOpenHelper.java
  1. package cn.itcast.showdata;

  2. import android.content.Context;
  3. import android.database.sqlite.SQLiteDatabase;
  4. import android.database.sqlite.SQLiteOpenHelper;

  5. public class MyOpenHelper extends SQLiteOpenHelper {

  6.         public MyOpenHelper(Context context) {
  7.                 super(context, "people.db", null, 1);
  8.         }

  9.         @Override
  10.         public void onCreate(SQLiteDatabase db) {
  11.                 db.execSQL("create table person(_id integer primary key autoincrement,name char(10),phone char(20),salary integer(10))");
  12.         }

  13.         @Override
  14.         public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
  15.                 System.out.println("数据库升级");
  16.         }
  17. }
复制代码

   AndroidManifest.xml
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  3.     package="cn.itcast.showdata"
  4.     android:versionCode="1"
  5.     android:versionName="1.0" >

  6.     <uses-sdk
  7.         android:minSdkVersion="8"
  8.         android:targetSdkVersion="17" />
  9.    
  10.         <instrumentation
  11.         android:name="android.test.InstrumentationTestRunner"
  12.         android:targetPackage="cn.itcast.showdata"
  13.         ></instrumentation>
  14.    
  15.     <application
  16.         android:allowBackup="true"
  17.         android:icon="@drawable/ic_launcher"
  18.         android:label="@string/app_name"
  19.         android:theme="@style/AppTheme" >
  20.         <uses-library android:name="android.test.runner"/>
  21.         <activity
  22.             android:name="cn.itcast.showdata.MainActivity"
  23.             android:label="@string/app_name" >
  24.             <intent-filter>
  25.                 <action android:name="android.intent.action.MAIN" />

  26.                 <category android:name="android.intent.category.LAUNCHER" />
  27.             </intent-filter>
  28.         </activity>
  29.     </application>

  30. </manifest>
复制代码

    src/cn.itcast.showdata/Test.java
  1. package cn.itcast.showdata;

  2. import android.content.ContentValues;
  3. import android.database.sqlite.SQLiteDatabase;
  4. import android.test.AndroidTestCase;

  5. public class Test extends AndroidTestCase {

  6.         private MyOpenHelper oh;
  7.         private SQLiteDatabase db;
  8.         
  9.         @Override
  10.         protected void setUp() throws Exception {
  11.                 super.setUp();
  12.                 oh =  new MyOpenHelper(getContext());
  13.                 db = oh.getWritableDatabase();
  14.         }
  15.         
  16.         public void insertApi(){

  17.                 for(int i = 0; i < 50; i++){
  18.                         ContentValues values = new ContentValues();
  19.                         values.put("name","张" + i);
  20.                         values.put("phone","138" + i + i);
  21.                         values.put("salary","200" + i);
  22.                         db.insert("person", null, values);
  23.                 }
  24.         }
  25.         
  26.         @Override
  27.         protected void tearDown() throws Exception {
  28.                 super.tearDown();
  29.                 db.close();
  30.         }
  31. }
复制代码

    src/cn.itcast.showdata.domain/Person.java
  1. package cn.itcast.showdata.domain;

  2. public class Person {

  3.         private int _id;
  4.         private String name;
  5.         private String phone;
  6.         private int salary;
  7.         
  8.         public Person(int _id, String name, String phone, int salary) {
  9.                 super();
  10.                 this._id = _id;
  11.                 this.name = name;
  12.                 this.phone = phone;
  13.                 this.salary = salary;
  14.         }
  15.         
  16.         public int get_id() {
  17.                 return _id;
  18.         }
  19.         public void set_id(int _id) {
  20.                 this._id = _id;
  21.         }
  22.         public String getName() {
  23.                 return name;
  24.         }
  25.         public void setName(String name) {
  26.                 this.name = name;
  27.         }
  28.         public String getPhone() {
  29.                 return phone;
  30.         }
  31.         public void setPhone(String phone) {
  32.                 this.phone = phone;
  33.         }
  34.         public int getSalary() {
  35.                 return salary;
  36.         }
  37.         public void setSalary(int salary) {
  38.                 this.salary = salary;
  39.         }

  40.         @Override
  41.         public String toString() {
  42.                 return "name=" + name + ", phone=" + phone
  43.                                 + ", salary=" + salary;
  44.         }
  45. }
复制代码

    res\layout\activity_main.xml
  1. <ScrollView
  2.     android:layout_width="match_parent"
  3.         android:layout_height="match_parent"
  4.     xmlns:android="http://schemas.android.com/apk/res/android"
  5.         xmlns:tools="http://schemas.android.com/tools"
  6.     >
  7.         <LinearLayout
  8.             android:id="@+id/ll"
  9.             android:layout_width="match_parent"
  10.             android:layout_height="match_parent"
  11.             tools:context=".MainActivity"
  12.             android:orientation="vertical">
  13.         
  14.         </LinearLayout>
  15. </ScrollView>
复制代码

    src/cn.itcast.showdata/MainActivity.java
  1. package cn.itcast.showdata;

  2. import java.util.ArrayList;
  3. import java.util.List;

  4. import android.app.Activity;
  5. import android.database.Cursor;
  6. import android.database.sqlite.SQLiteDatabase;
  7. import android.os.Bundle;
  8. import android.widget.LinearLayout;
  9. import android.widget.TextView;
  10. import cn.itcast.sqlite.domain.Person;

  11. public class MainActivity extends Activity {

  12.         List<Person> personList;
  13.         
  14.         @Override
  15.         protected void onCreate(Bundle savedInstanceState) {
  16.                 super.onCreate(savedInstanceState);
  17.                 setContentView(R.layout.activity_main);
  18.                
  19.                 personList = new ArrayList<Person>();
  20.                
  21.                 //读取数据库
  22.                 MyOpenHelper oh = new MyOpenHelper(this);
  23.                 SQLiteDatabase db = oh.getWritableDatabase();
  24.                
  25.                 Cursor cursor = db.query("person", null, null, null, null, null, null, null);
  26.                
  27.                 while(cursor.moveToNext()){
  28.                         int _id = cursor.getInt(0);
  29.                         String name = cursor.getString(1);
  30.                         String phone = cursor.getString(2);
  31.                         int salary = cursor.getInt(3);
  32.                         
  33.                         Person p = new Person(_id, name, phone, salary);
  34.                         personList.add(p);
  35.                 }
  36.                
  37.                 //获取线性布局
  38.                 LinearLayout ll = (LinearLayout) findViewById(R.id.ll);
  39.                
  40.                 for(Person p : personList){
  41.                         TextView tv = new TextView(this);
  42.                         tv.setText(p.toString());
  43.                         tv.setTextSize(16);
  44.                         
  45.                         //把tv设置为线性布局的子节点
  46.                         ll.addView(tv);
  47.                 }
  48.         }
  49. }
复制代码
    运行结果:

    首先,在模拟器上运行应用程序,在data/data目录下创建应用程序文件目录。运行Test类中的insertApi方法,导出people.db文件,拖入SQLite Expert,可以看到插入数据成功。





    然后,再次在模拟器上运行应用程序,将数据库中的数据通过TextView的形式展示在屏幕上。



    P.S.
    使用ScrollView包裹LinearLayout,ScrollView表示可以上下滑动的View。如果线性布局过大,超出屏幕显示范围,那么就可以上下滑动了。

    使用ListView显示数据

    开发中不会按照如上方法显示数据到屏幕上的。因为,如果待显示数据太多,程序可能会崩溃。原因在于循环提取数据,如果有10000条数据,就需要创建10000个JavaBean对象和10000个TextView对象到内存中,太耗内存。解决方案之一是采用分页查询,只查询一部分数据,通过SQL语句的limit控制读取的条数。另一个Android方式的解决方案是动态创建TextView,也就是说屏幕只能显示10条数据,那么就创建10个JavaBean对象和10个TextView对象。如果用户下滑屏幕显示数据,一方面缓存(内存不足的时候会被摧毁,内存充足的时候缓存,避免下次再显示的时候重新创建,提升性能)屏幕上方已经消失的TextView,一方面创建屏幕下方要显示的TextView。这样,内容中只有10个JavaBean对象及10个TextView,避免内存溢出。Android中用ListView实现此功能。

    ListView专门用于显示列表,每一行称为一个条目(Item)。

    MVC:
    M:模型层 Javabean personList
    V:视图层 jsp            ListView
    C:控制层 servlet      Adapter(Adapter是适配器,用适配器控制要显示哪些内容

    ListAdapter是一个接口,需要实现的方法太多。因此,一般通过继承BaseAdapter(抽象类)的方式创建ListAdapter对象。


    所有在布局文件中定义的组件(包括LinearLayout),都可以在ListView中显示。



    示例:

    修改上个示例中的代码如下:

    res\layout\activity_main.xml
  1. <LinearLayout
  2.     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.     tools:context=".MainActivity"
  7.     android:orientation="vertical">

  8.     <ListView
  9.         android:id="@+id/lv"
  10.         android:layout_width="match_parent"
  11.             android:layout_height="match_parent">
  12.         
  13.     </ListView>
  14.    
  15. </LinearLayout>
复制代码

    src/cn.itcast.listView/MainActivity.java
  1. package cn.itcast.listView;

  2. import java.util.ArrayList;
  3. import java.util.List;

  4. import android.app.Activity;
  5. import android.database.Cursor;
  6. import android.database.sqlite.SQLiteDatabase;
  7. import android.os.Bundle;
  8. import android.view.View;
  9. import android.view.ViewGroup;
  10. import android.widget.BaseAdapter;
  11. import android.widget.ListView;
  12. import android.widget.TextView;
  13. import cn.itcast.listView.domain.Person;

  14. public class MainActivity extends Activity {

  15.         List<Person> personList;
  16.         
  17.         @Override
  18.         protected void onCreate(Bundle savedInstanceState) {
  19.                 super.onCreate(savedInstanceState);
  20.                 setContentView(R.layout.activity_main);
  21.                
  22.                 personList = new ArrayList<Person>();
  23.                
  24.                 //读取数据库
  25.                 MyOpenHelper oh = new MyOpenHelper(this);
  26.                 SQLiteDatabase db = oh.getWritableDatabase();
  27.                
  28.                 Cursor cursor = db.query("person", null, null, null, null, null, null, null);
  29.                
  30.                 while(cursor.moveToNext()){
  31.                         int _id = cursor.getInt(0);
  32.                         String name = cursor.getString(1);
  33.                         String phone = cursor.getString(2);
  34.                         int salary = cursor.getInt(3);
  35.                         
  36.                         Person p = new Person(_id, name, phone, salary);
  37.                         personList.add(p);
  38.                 }
  39.                
  40.                 ListView lv = (ListView)findViewById(R.id.lv);
  41.                 lv.setAdapter(new MyAdapter());
  42.         }
  43.         
  44.         class MyAdapter extends BaseAdapter{
  45.         
  46.                 //获取集合的元素数量
  47.                 @Override
  48.                 public int getCount() {
  49.                         return personList.size();
  50.                 }

  51.                 //系统调用此方法,获取一个View对象,该View对象会作为一个条目显示至ListView中
  52.                 //position:getView返回的View对象会作为ListView的第几个条目显示,那么position的值就是多少
  53.                 @Override
  54.                 public View getView(int position, View convertView, ViewGroup parent) {
  55.                         System.out.println("getView调用" + position);
  56.                         Person p = personList.get(position);
  57.                         TextView tv = new TextView(MainActivity.this);
  58.                         tv.setText(p.toString());
  59.                         tv.setTextSize(16);
  60.                         return tv;
  61.                 }
  62.                
  63.                 @Override
  64.                 public Object getItem(int position) {
  65.                         return null;
  66.                 }

  67.                 @Override
  68.                 public long getItemId(int position) {
  69.                         return 0;
  70.                 }
  71.         }
  72. }
复制代码
   运行结果:





    如果将屏幕向下滑动,结果如下:



    如果将屏幕向上滑动,结果如下:



    把布局文件填充成View对象

    如果想要修改ListView的展示样式,那么就需要将指定的布局文件填充为View。

    示例:

    修改上个示例中的代码,如下:

    res\layout\item_listview.xml
  1. <RelativeLayout
  2.     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="wrap_content">

  6.    
  7.     <TextView
  8.         android:id="@+id/tv_name"
  9.         android:layout_width="wrap_content"
  10.             android:layout_height="wrap_content"
  11.             android:text="name"
  12.             android:textSize="22sp"/>
  13.         
  14.         <LinearLayout
  15.         android:layout_width="wrap_content"
  16.             android:layout_height="wrap_content"
  17.             android:orientation="vertical"
  18.             android:layout_alignParentRight="true"
  19.             android:layout_centerVertical="true"
  20.             >
  21.             <TextView
  22.                 android:id="@+id/tv_phone"
  23.                 android:layout_width="wrap_content"
  24.                     android:layout_height="wrap_content"
  25.                     android:text="phone"               
  26.                 />
  27.             <TextView
  28.                 android:id="@+id/tv_salary"
  29.                 android:layout_width="wrap_content"
  30.                     android:layout_height="wrap_content"
  31.                     android:text="salary"               
  32.                 />
  33.         </LinearLayout>
  34.    
  35. </RelativeLayout>
复制代码

    src/cn.itcast.listView/MainActivity.java
  1. package cn.itcast.listView;

  2. import java.util.ArrayList;
  3. import java.util.List;

  4. import android.app.Activity;
  5. import android.database.Cursor;
  6. import android.database.sqlite.SQLiteDatabase;
  7. import android.os.Bundle;
  8. import android.view.LayoutInflater;
  9. import android.view.View;
  10. import android.view.ViewGroup;
  11. import android.widget.BaseAdapter;
  12. import android.widget.ListView;
  13. import android.widget.TextView;
  14. import cn.itcast.listView.domain.Person;

  15. public class MainActivity extends Activity {

  16.         List<Person> personList;
  17.         
  18.         @Override
  19.         protected void onCreate(Bundle savedInstanceState) {
  20.                 super.onCreate(savedInstanceState);
  21.                 setContentView(R.layout.activity_main);
  22.                
  23.                 personList = new ArrayList<Person>();
  24.                
  25.                 MyOpenHelper oh = new MyOpenHelper(this);
  26.                 SQLiteDatabase db = oh.getWritableDatabase();
  27.                
  28.                 Cursor cursor = db.query("person", null, null, null, null, null, null, null);
  29.                
  30.                 while(cursor.moveToNext()){
  31.                         int _id = cursor.getInt(0);
  32.                         String name = cursor.getString(1);
  33.                         String phone = cursor.getString(2);
  34.                         int salary = cursor.getInt(3);
  35.                         
  36.                         Person p = new Person(_id, name, phone, salary);
  37.                         personList.add(p);
  38.                 }
  39.                
  40.                 ListView lv = (ListView)findViewById(R.id.lv);
  41.                 lv.setAdapter(new MyAdapter());
  42.         }
  43.         
  44.         class MyAdapter extends BaseAdapter{
  45.         
  46.                 @Override
  47.                 public int getCount() {
  48.                         return personList.size();
  49.                 }

  50.                 @Override
  51.                 public View getView(int position, View convertView, ViewGroup parent) {
  52.                         System.out.println("getView调用" + position);
  53.                         Person p = personList.get(position);
  54.                         
  55.                         //把指定布局文件填充成View对象
  56.                         //第二个参数指定把哪个布局文件转换成View对象,变成ListView条目显示在屏幕上
  57.                         //第三个参数给布局文件指定父节点,不需要,设置null
  58.                         View v = View.inflate(MainActivity.this, R.layout.item_listview, null);
  59.                         
  60.                         //第二种方式,不常用
  61.                         //LayoutInflater inflater = LayoutInflater.from(MainActivity.this);
  62.                         //View v = inflater.inflate(R.layout.item_listview, null);
  63.                         
  64.                         //第三种方式,不常用
  65.                         //LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
  66.                         //View v = inflater.inflate(R.layout.item_listview, null);
  67.                         
  68.                         //修改View对象中各个组件的内容
  69.                         //findViewById(R.id.tv_name);通过id寻找tv_name默认是在activity_mian.xml布局文件中查找(由于本类中onCreate方法有一条语句setContentView(R.layout.activity_main);)。
  70.                         //v.findViewById(R.id.tv_name);就会在被填充的item_listview布局文件中查找tv_name。
  71.                         TextView tv_name = (TextView)v.findViewById(R.id.tv_name);
  72.                         tv_name.setText(p.getName());
  73.                         
  74.                         TextView tv_phone = (TextView)v.findViewById(R.id.tv_phone);
  75.                         tv_phone.setText(p.getPhone());
  76.                         
  77.                         TextView tv_salary = (TextView)v.findViewById(R.id.tv_salary);
  78.                         //参数一定要为字符串,如果是整数,那么就会把它作为一个id,去寻找相应的资源
  79.                         tv_salary.setText(p.getSalary() + "");
  80.                         
  81.                         return v;
  82.                 }
  83.                
  84.                 //下面两个方法,系统不会调用,程序员可以调用
  85.                 //返回条目,一般返回某个元素,例如:personList.get(position);
  86.                 @Override
  87.                 public Object getItem(int position) {
  88.                         return null;
  89.                 }

  90.                 //返回条目的id,一般返回元素的主键
  91.                 @Override
  92.                 public long getItemId(int position) {
  93.                         return 0;
  94.                 }
  95.         }
  96. }
复制代码
    运行结果:



    ListView的优化

    上面的代码,只要用户一直上下滑屏,就会不断填充新的View对象(View v = View.inflate(MainActivity.this, R.layout.item_listview, null);),一方面耗费内存(内存可能会溢出)、CPU,另一方面导致加载时间变长





    可以使用listView的缓存机制解决这个问题。任何一个条目如果被滑出屏幕,那么就缓存起来,下次再显示,不用重新创建,直接从缓存中提取就好。

    ListView对条目的缓存。在显示新的条目时,只要内存中有缓存,就会拿来用,不管是哪个条目的缓存。

    示例:

    修改上面的示例代码,如下:

    src/cn.itcast.listView/MainActivity.java
  1. package cn.itcast.listView;

  2. import java.util.ArrayList;
  3. import java.util.List;

  4. import android.app.Activity;
  5. import android.database.Cursor;
  6. import android.database.sqlite.SQLiteDatabase;
  7. import android.os.Bundle;
  8. import android.view.View;
  9. import android.view.ViewGroup;
  10. import android.widget.BaseAdapter;
  11. import android.widget.ListView;
  12. import android.widget.TextView;
  13. import cn.itcast.listView.domain.Person;

  14. public class MainActivity extends Activity {

  15.         List<Person> personList;
  16.         
  17.         @Override
  18.         protected void onCreate(Bundle savedInstanceState) {
  19.                 super.onCreate(savedInstanceState);
  20.                 setContentView(R.layout.activity_main);
  21.                
  22.                 personList = new ArrayList<Person>();
  23.                
  24.                 MyOpenHelper oh = new MyOpenHelper(this);
  25.                 SQLiteDatabase db = oh.getWritableDatabase();
  26.                
  27.                 Cursor cursor = db.query("person", null, null, null, null, null, null, null);
  28.                
  29.                 while(cursor.moveToNext()){
  30.                         int _id = cursor.getInt(0);
  31.                         String name = cursor.getString(1);
  32.                         String phone = cursor.getString(2);
  33.                         int salary = cursor.getInt(3);
  34.                         
  35.                         Person p = new Person(_id, name, phone, salary);
  36.                         personList.add(p);
  37.                 }
  38.                
  39.                 ListView lv = (ListView)findViewById(R.id.lv);
  40.                 lv.setAdapter(new MyAdapter());
  41.         }
  42.         
  43.         class MyAdapter extends BaseAdapter{
  44.         
  45.                 @Override
  46.                 public int getCount() {
  47.                         return personList.size();
  48.                 }

  49.                 //convertView就是被缓存起来的View对象,系统每次调用getView方法,都会把convertView传递进来
  50.                 @Override
  51.                 public View getView(int position, View convertView, ViewGroup parent) {
  52.                         System.out.println("getView调用" + position);
  53.                         Person p = personList.get(position);
  54.                         
  55.                         View v = null;
  56.                         
  57.                             System.out.println(convertView);
  58.                         
  59.                         if(convertView == null){
  60.                                 //如果没有缓存,填充新的View对象
  61.                                 v = View.inflate(MainActivity.this, R.layout.item_listview, null);
  62.                         }else{
  63.                                 //如果有缓存,复用缓存
  64.                                 v = convertView;
  65.                         }
  66.                         
  67.                         //缓存并不是指给每个单独的条目缓存,系统是只要系统中有对象被缓存就会拿来使用。
  68.                         //所以缓存的是View对象,并不是内容。也就是说系统中缓存的对象个数等于同屏能够显示的条目+1个。
  69.                         TextView tv_name = (TextView)v.findViewById(R.id.tv_name);
  70.                         tv_name.setText(p.getName());
  71.                         
  72.                         TextView tv_phone = (TextView)v.findViewById(R.id.tv_phone);
  73.                         tv_phone.setText(p.getPhone());
  74.                         
  75.                         TextView tv_salary = (TextView)v.findViewById(R.id.tv_salary);
  76.                         tv_salary.setText(p.getSalary() + "");
  77.                         
  78.                         return v;
  79.                 }
  80.                
  81.                 @Override
  82.                 public Object getItem(int position) {
  83.                         return null;
  84.                 }

  85.                 @Override
  86.                 public long getItemId(int position) {
  87.                         return 0;
  88.                 }
  89.         }
  90. }
复制代码
   运行结果:





    可以看到,缓存了11个View对象之后,后来不会再创建新的的View对象了,而都是通过缓存获取的。

    ArrayAdapter和SimpleAdapter

    ListAdapter,我们用的最多的是BaseAdapter,因为它的四个方法是我们自己实现的,自由度比较大,做复杂列表的时候比较容易。但列表不是那么复杂的时候,ListAdapter有一些封装度更高的Adapter提供给我们使用,用起来会更方便,其中的getCount、getView都不需要我们自己写代码。

    示例1:

    res\layout\activity_main.xml
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     android:layout_width="match_parent"
  4.     android:layout_height="wrap_content"
  5.     android:orientation="horizontal" >
  6.    
  7.     <ImageView
  8.         android:id="@+id/iv"
  9.         android:layout_width="40dp"
  10.         android:layout_height="40dp"
  11.         android:src="@drawable/ic_launcher"
  12.         />
  13.    
  14.     <TextView
  15.         android:id="@+id/tv"
  16.         android:layout_width="wrap_content"
  17.         android:layout_height="wrap_content"
  18.         android:text="name"
  19.         android:textSize="25sp"
  20.         android:layout_gravity="center_vertical"
  21.         />

  22. </LinearLayout>
复制代码

    src/cn.itcast.simplearray/MainActivity.java
  1. package cn.itcast.simplearray;

  2. import java.util.ArrayList;
  3. import java.util.HashMap;
  4. import java.util.List;
  5. import java.util.Map;

  6. import android.app.Activity;
  7. import android.os.Bundle;
  8. import android.widget.ArrayAdapter;
  9. import android.widget.ListView;
  10. import android.widget.SimpleAdapter;

  11. public class MainActivity extends Activity {

  12.         @Override
  13.         protected void onCreate(Bundle savedInstanceState) {
  14.                 super.onCreate(savedInstanceState);
  15.                 setContentView(R.layout.activity_main);
  16.                
  17.                 String[] objects = new String[]{"白吃","沙比","亚聪"};
  18.                
  19.                 ListView lv = (ListView)findViewById(R.id.lv);
  20.                 //使用ArrayAdapter只能处理文本数据,图片数据无法个性化单独设置,所以如果只是简单的文本显示,就是用ArrayAdapter。
  21.                 //第二个参数为资源文件,填充ListView条目的布局文件
  22.                 //第三个参数指定文本显示至哪一个textView中
  23.                 lv.setAdapter(new ArrayAdapter<String>(this, R.layout.item_listview, R.id.tv, objects));
  24.         }
  25. }
复制代码
   运行结果:



    示例2:

    src/cn.itcast.simplearray/MainActivity.java
  1. package cn.itcast.simplearray;

  2. import java.util.ArrayList;
  3. import java.util.HashMap;
  4. import java.util.List;
  5. import java.util.Map;

  6. import android.app.Activity;
  7. import android.os.Bundle;
  8. import android.widget.ArrayAdapter;
  9. import android.widget.ListView;
  10. import android.widget.SimpleAdapter;

  11. public class MainActivity extends Activity {

  12.         @Override
  13.         protected void onCreate(Bundle savedInstanceState) {
  14.                 super.onCreate(savedInstanceState);
  15.                 setContentView(R.layout.activity_main);
  16.                
  17.                 ListView lv = (ListView)findViewById(R.id.lv);
  18.                
  19.                 //集合中的每一个元素都是一个条目要显示的数据,因为有多种数据类型,所以List不能使用单一泛型,先把所有类型的数据都封装至map,然后把map存入List。
  20.                 List<Map<String,Object>> data = new ArrayList<Map<String,Object>>();
  21.                
  22.                 Map<String,Object> map1= new HashMap<String,Object>();
  23.                 map1.put("image", R.drawable.ic_launcher);
  24.                 map1.put("name", "白吃");
  25.                 data.add(map1);
  26.                
  27.                 Map<String,Object> map2= new HashMap<String,Object>();
  28.                 map2.put("image", R.drawable.photo1);
  29.                 map2.put("name", "沙比");
  30.                 data.add(map2);
  31.                
  32.                 Map<String,Object> map3= new HashMap<String,Object>();
  33.                 map3.put("image", R.drawable.photo2);
  34.                 map3.put("name", "亚聪");
  35.                 data.add(map3);
  36.                
  37.                 lv.setAdapter(new SimpleAdapter(this, data, R.layout.item_listview        , new String[]{"image","name"}, new int[]{R.id.iv,R.id.tv}));
  38.         }
  39. }
复制代码
   运行结果:



~END~



~爱上海,爱黑马~



9 个回复

倒序浏览
学习了。。。。。
回复 使用道具 举报
看不懂。。。。。。。。。。
回复 使用道具 举报
很赞的说!
回复 使用道具 举报
学习了......
回复 使用道具 举报
这么好的帖子,点个赞!不知道,有没有web的总结!
回复 使用道具 举报
这么多代码,我什么时候才能这么大神呀
回复 使用道具 举报
先顶后看~
回复 使用道具 举报
ajiao 中级黑马 2015-7-19 13:11:13
9#
继续收藏,赞一个!
回复 使用道具 举报
学习一下
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马