資料庫(66期第三天)

葬天VS曉偉發表於2016-03-29

Pull解析xml檔案(掌握)

  • 先自己寫一個xml檔案,存一些天氣資訊

拿到xml檔案

    InputStream is = getClassLoader().getResourceAsStream("weather.xml");

拿到pull解析器

    XmlPullParser xp = Xml.newPullParser();

開始解析

  • 拿到指標所在當前節點的事件型別

    int type = xp.getEventType();
    
  • 事件型別主要有五種

    • START_DOCUMENT:xml頭的事件型別
    • END_DOCUMENT:xml尾的事件型別
    • START_TAG:開始節點的事件型別
    • END_TAG:結束節點的事件型別
    • TEXT:文字節點的事件型別
  • 如果獲取到的事件型別不是END_DOCUMENT,就說明解析還沒有完成,如果是,解析完成,while迴圈結束

    while(type != XmlPullParser.END_DOCUMENT)
    
  • 當我們解析到不同節點時,需要進行不同的操作,所以判斷一下當前節點的name

    • 當解析到weather的開始節點時,new出list
    • 當解析到city的開始節點時,建立city物件,建立物件是為了更方便的儲存即將解析到的文字
    • 當解析到name開始節點時,獲取下一個節點的文字內容,temp、pm也是一樣

      case XmlPullParser.START_TAG:
      //獲取當前節點的名字
          if("weather".equals(xp.getName())){
              citys = new ArrayList<City>();
          }
          else if("city".equals(xp.getName())){
              city = new City();
          }
          else if("name".equals(xp.getName())){
              //獲取當前節點的下一個節點的文字
              String name = xp.nextText();
              city.setName(name);
          }
          else if("temp".equals(xp.getName())){
              String temp = xp.nextText();
              city.setTemp(temp);
          }
          else if("pm".equals(xp.getName())){
              String pm = xp.nextText();
              city.setPm(pm);
          }
          break;
      
  • 當解析到city的結束節點時,說明city的三個子節點已經全部解析完了,把city物件新增至list

    case XmlPullParser.END_TAG:
        if("city".equals(xp.getName())){
                citys.add(city);
        }
    

測試(瞭解)

  • 黑盒測試
    • 測試邏輯業務
  • 白盒測試

    • 測試邏輯方法
  • 根據測試粒度

    • 方法測試:function test
    • 單元測試:unit test
    • 整合測試:integration test
    • 系統測試:system test
  • 根據測試暴力程度

    • 冒煙測試:smoke test
    • 壓力測試:pressure test

單元測試junit(熟悉)

  • 定義一個類繼承AndroidTestCase,在類中定義方法,即可測試該方法

  • 在指定指令集時,targetPackage指定你要測試的應用的包名

    <instrumentation 
    android:name="android.test.InstrumentationTestRunner"
    android:targetPackage="com.itheima.junit"
    ></instrumentation>
    
  • 定義使用的類庫

    <uses-library android:name="android.test.runner"></uses-library>
    
  • 斷言的作用,檢測執行結果和預期是否一致

  • 如果應用出現異常,會拋給測試框架

SQLite資料庫(掌握)

  • 輕量級關係型資料庫
  • 建立資料庫需要使用的api:SQLiteOpenHelper

    • 必須定義一個構造方法:

      //arg1:資料庫檔案的名字
      //arg2:遊標工廠
      //arg3:資料庫版本
      public MyOpenHelper(Context context, String name, CursorFactory factory, int version){
      
      }
      
    • 資料庫被建立時會呼叫:onCreate方法
    • 資料庫升級時會呼叫:onUpgrade方法

建立資料庫

//建立OpenHelper物件
MyOpenHelper oh = new MyOpenHelper(getContext(), "person.db", null, 1);
//獲得資料庫物件,如果資料庫不存在,先建立資料庫,後獲得,如果存在,則直接獲得
SQLiteDatabase db = oh.getWritableDatabase();
  • getWritableDatabase():開啟可讀寫的資料庫
  • getReadableDatabase():在磁碟空間不足時開啟只讀資料庫,否則開啟可讀寫資料庫
  • 在建立資料庫時建立表

    public void onCreate(SQLiteDatabase db) {
        // TODO Auto-generated method stub
        db.execSQL("create table person (_id integer primary key autoincrement, name char(10), phone char(20), money integer(20))");
    }
    

資料庫的增刪改查(掌握)

SQL語句

  • insert into person (name, phone, money) values (‘張三’, ‘159874611’, 2000);
  • delete from person where name = ‘李四’ and _id = 4;
  • update person set money = 6000 where name = ‘李四’;
  • select name, phone from person where name = ‘張三’;

執行SQL語句實現增刪改查

    //插入
    db.execSQL("insert into person (name, phone, money) values (?, ?, ?);", new Object[]{"張三", 15987461, 75000});
    //查詢
    Cursor cs = db.rawQuery("select _id, name, money from person where name = ?;", new String[]{"張三"});

* 測試方法執行前會呼叫此方法

    protected void setUp() throws Exception {
        super.setUp();
        //                  獲取虛擬上下文物件
        oh = new MyOpenHelper(getContext(), "people.db", null, 1);
    }

使用api實現增刪改查

  • 插入

    //以鍵值對的形式儲存要存入資料庫的資料
    ContentValues cv = new ContentValues();
    cv.put("name", "劉能");
    cv.put("phone", 1651646);
    cv.put("money", 3500);
    //返回值是改行的主鍵,如果出錯返回-1
    long i = db.insert("person", null, cv);
    
  • 刪除

    //返回值是刪除的行數
    int i = db.delete("person", "_id = ? and name = ?", new String[]{"1", "張三"});
    
  • 修改

    ContentValues cv = new ContentValues();
    cv.put("money", 25000);
    int i = db.update("person", cv, "name = ?", new String[]{"趙四"});
    
  • 查詢

    //arg1:要查詢的欄位
    //arg2:查詢條件
    //arg3:填充查詢條件的佔位符
    Cursor cs = db.query("person", new String[]{"name", "money"}, "name = ?", new String[]{"張三"}, null, null, null);
    while(cs.moveToNext()){
        //                          獲取指定列的索引值
        String name = cs.getString(cs.getColumnIndex("name"));
        String money = cs.getString(cs.getColumnIndex("money"));
        System.out.println(name + ";" + money);
    }
    

事務

  • 保證多條SQL語句要麼同時成功,要麼同時失敗
  • 最常見案例:銀行轉賬
  • 事務api

    try {
        //開啟事務
        db.beginTransaction();
        ...........
        //設定事務執行成功
        db.setTransactionSuccessful();
    } finally{
        //關閉事務
        //如果此時已經設定事務執行成功,則sql語句生效,否則不生效
        db.endTransaction();
    }
    

把資料庫的資料顯示至螢幕(瞭解)

  1. 任意插入一些資料

    • 定義業務bean:Person.java
    • 讀取資料庫的所有資料

      Cursor cs = db.query(“person”, null, null, null, null, null, null);
      while(cs.moveToNext()){
      String name = cs.getString(cs.getColumnIndex(“name”));
      String phone = cs.getString(cs.getColumnIndex(“phone”));
      String money = cs.getString(cs.getColumnIndex(“money”));
      //把讀到的資料封裝至Person物件
      Person p = new Person(name, phone, money);
      //把person物件儲存至集合中
      people.add(p);
      }

    • 把集合中的資料顯示至螢幕

      LinearLayout ll = (LinearLayout) findViewById(R.id.ll);
      for(Person p : people){
      //建立TextView,每條資料用一個文字框顯示
      TextView tv = new TextView(this);
      tv.setText(p.toString());
      //把文字框設定為ll的子節點
      ll.addView(tv);
      }

    • 分頁查詢

      Cursor cs = db.query(“person”, null, null, null, null, null, null, “0, 10”);


ListView(掌握)

  • 用於顯示列表
  • MVC結構
    • M:model模型層,要顯示的資料 ————people集合
    • V:view檢視層,使用者看到的介面 ————ListView
    • c:control控制層,運算元據如何顯示 ————adapter物件
  • 每一個條目都是一個View物件

BaseAdapter

  • 必須實現的兩個方法

    • 第一個

      //系統呼叫此方法,用來獲知模型層有多少條資料
      @Override
      public int getCount() {
          return people.size();
      }
      
    • 第二個

      //系統呼叫此方法,獲取要顯示至ListView的View物件
      //position:是return的View物件所對應的資料在集合中的位置
      @Override
      public View getView(int position, View convertView, ViewGroup parent) {
          System.out.println("getView方法呼叫" + position);
          TextView tv = new TextView(MainActivity.this);
          //拿到集合中的元素
          Person p = people.get(position);
          tv.setText(p.toString());
      
          //把TextView的物件返回出去,它會變成ListView的條目
          return tv;
      }
      
  • 螢幕上能顯示多少個條目,getView方法就會被呼叫多少次,螢幕向下滑動時,getView會繼續被呼叫,建立更多的View物件顯示至螢幕

條目的快取

  • 當條目劃出螢幕時,系統會把該條目快取至記憶體,當該條目再次進入螢幕,系統在重新呼叫getView時會把快取的條目作為convertView引數傳入,但是傳入的條目不一定是之前被快取的該條目,即系統有可能在呼叫getView方法獲取第一個條目時,傳入任意一個條目的快取

ArrayAdapter(熟悉)

  • 在條目中顯示一個字串

    String[] objects = new String[]{
            "張三",
            "李四",
            "王五"
    };
    
    ListView lv = (ListView) findViewById(R.id.lv);
    //arg1:指定要填充的佈局檔案
    //arg2:指定文字顯示至哪一個文字框內
    lv.setAdapter(new ArrayAdapter<String>(this, R.layout.item_array, R.id.tv_name, objects));
    

SimpleAdapter(熟悉)

  • 可在條目中顯示多種資料
  • 要顯示的資料封裝在List中,集合的每一個元素存放的是一個條目會顯示的資料,因為可能會有多種資料,而集合的泛型只能指定一種資料,所以把資料先存放在Map中,在把Map放入List中

     List<Map<String, Object>> data = new ArrayList<Map<String,Object>>();
    
     //張三的頭像和名字是兩種型別的資料,先封裝至Map
     Map<String, Object> map1 = new HashMap<String, Object>();
     map1.put("name", "張三");
     map1.put("image", R.drawable.photo1);
     //把Map封裝至List
     data.add(map1);
     ...
    
  • 通過兩個陣列的下標對應指定資料存放入對應的控制元件中
    lv.setAdapter(new SimpleAdapter(this, data, R.layout.item_array,
    new String[]{“name”, “image”}, new int[]{R.id.tv_name, R.id.iv_photo}));

相關文章