Pull解析xml文件(掌握)
- 先自己寫一個xml文件,存一些天氣信息
拿到xml文件
InputStream is = getClassLoader().getResourceAsStream("weather.xml");
拿到pull解析器
XmlPullParser xp = Xml.newPullParser();
開始解析
-
拿到指針所在當前節(jié)點的事件類型
int type = xp.getEventType(); -
事件類型主要有五種
- START_DOCUMENT:xml頭的事件類型
- END_DOCUMENT:xml尾的事件類型
- START_TAG:開始節(jié)點的事件類型
- END_TAG:結(jié)束節(jié)點的事件類型
- TEXT:文本節(jié)點的事件類型
-
如果獲取到的事件類型不是END_DOCUMENT,就說明解析還沒有完成,如果是,解析完成,while循環(huán)結(jié)束
while(type != XmlPullParser.END_DOCUMENT) -
當我們解析到不同節(jié)點時,需要進行不同的操作,所以判斷一下當前節(jié)點的name
當解析到weather的開始節(jié)點時,new出list
當解析到city的開始節(jié)點時,創(chuàng)建city對象,創(chuàng)建對象是為了更方便的保存即將解析到的文本
-
當解析到name開始節(jié)點時,獲取下一個節(jié)點的文本內(nèi)容,temp、pm也是一樣
case XmlPullParser.START_TAG: //獲取當前節(jié)點的名字 if("weather".equals(xp.getName())){ citys = new ArrayList<City>(); } else if("city".equals(xp.getName())){ city = new City(); } else if("name".equals(xp.getName())){ //獲取當前節(jié)點的下一個節(jié)點的文本 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的結(jié)束節(jié)點時,說明city的三個子節(jié)點已經(jīng)全部解析完了,把city對象添加至list
case XmlPullParser.END_TAG: if("city".equals(xp.getName())){ citys.add(city); }
測試(了解)
-
黑盒測試
- 測試邏輯業(yè)務(wù)
-
白盒測試
- 測試邏輯方法
-
根據(jù)測試粒度
- 方法測試:function test
- 單元測試:unit test
- 集成測試:integration test
- 系統(tǒng)測試:system test
-
根據(jù)測試暴力程度
- 冒煙測試:smoke test
- 壓力測試:pressure test
單元測試junit(熟悉)
定義一個類繼承AndroidTestCase,在類中定義方法,即可測試該方法
-
在指定指令集時,targetPackage指定你要測試的應(yīng)用的包名
<instrumentation android:name="android.test.InstrumentationTestRunner" android:targetPackage="com.itheima.junit" ></instrumentation> -
定義使用的類庫
<uses-library android:name="android.test.runner"></uses-library> 斷言的作用,檢測運行結(jié)果和預(yù)期是否一致
如果應(yīng)用出現(xiàn)異常,會拋給測試框架
SQLite數(shù)據(jù)庫(掌握)
- 輕量級關(guān)系型數(shù)據(jù)庫
- 創(chuàng)建數(shù)據(jù)庫需要使用的api:SQLiteOpenHelper
-
必須定義一個構(gòu)造方法:
//arg1:數(shù)據(jù)庫文件的名字 //arg2:游標工廠 //arg3:數(shù)據(jù)庫版本 public MyOpenHelper(Context context, String name, CursorFactory factory, int version){ } 數(shù)據(jù)庫被創(chuàng)建時會調(diào)用:onCreate方法
數(shù)據(jù)庫升級時會調(diào)用:onUpgrade方法
-
創(chuàng)建數(shù)據(jù)庫
//創(chuàng)建OpenHelper對象
MyOpenHelper oh = new MyOpenHelper(getContext(), "person.db", null, 1);
//獲得數(shù)據(jù)庫對象,如果數(shù)據(jù)庫不存在,先創(chuàng)建數(shù)據(jù)庫,后獲得,如果存在,則直接獲得
SQLiteDatabase db = oh.getWritableDatabase();
getWritableDatabase():打開可讀寫的數(shù)據(jù)庫
getReadableDatabase():在磁盤空間不足時打開只讀數(shù)據(jù)庫,否則打開可讀寫數(shù)據(jù)庫
-
在創(chuàng)建數(shù)據(jù)庫時創(chuàng)建表
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))"); }
數(shù)據(jù)庫的增刪改查(掌握)
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 = '張三';
執(zhí)行SQL語句實現(xiàn)增刪改查
//插入
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[]{"張三"});
-
測試方法執(zhí)行前會調(diào)用此方法
protected void setUp() throws Exception { super.setUp(); // 獲取虛擬上下文對象 oh = new MyOpenHelper(getContext(), "people.db", null, 1); }
使用api實現(xiàn)增刪改查
-
插入
//以鍵值對的形式保存要存入數(shù)據(jù)庫的數(shù)據(jù) ContentValues cv = new ContentValues(); cv.put("name", "劉能"); cv.put("phone", 1651646); cv.put("money", 3500); //返回值是改行的主鍵,如果出錯返回-1 long i = db.insert("person", null, cv); -
刪除
//返回值是刪除的行數(shù) 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); }
事務(wù)
保證多條SQL語句要么同時成功,要么同時失敗
最常見案例:銀行轉(zhuǎn)賬
-
事務(wù)api
try { //開啟事務(wù) db.beginTransaction(); ........... //設(shè)置事務(wù)執(zhí)行成功 db.setTransactionSuccessful(); } finally{ //關(guān)閉事務(wù) //如果此時已經(jīng)設(shè)置事務(wù)執(zhí)行成功,則sql語句生效,否則不生效 db.endTransaction(); }
把數(shù)據(jù)庫的數(shù)據(jù)顯示至屏幕(了解)
- 任意插入一些數(shù)據(jù)
定義業(yè)務(wù)bean:Person.java
-
讀取數(shù)據(jù)庫的所有數(shù)據(jù)
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")); //把讀到的數(shù)據(jù)封裝至Person對象 Person p = new Person(name, phone, money); //把person對象保存至集合中 people.add(p); } -
把集合中的數(shù)據(jù)顯示至屏幕
LinearLayout ll = (LinearLayout) findViewById(R.id.ll); for(Person p : people){ //創(chuàng)建TextView,每條數(shù)據(jù)用一個文本框顯示 TextView tv = new TextView(this); tv.setText(p.toString()); //把文本框設(shè)置為ll的子節(jié)點 ll.addView(tv); } -
分頁查詢
Cursor cs = db.query("person", null, null, null, null, null, null, "0, 10");
ListView(掌握)
- 用于顯示列表
- MVC結(jié)構(gòu)
- M:model模型層,要顯示的數(shù)據(jù) ————people集合
- V:view視圖層,用戶看到的界面 ————ListView
- c:control控制層,操作數(shù)據(jù)如何顯示 ————adapter對象
- 每一個條目都是一個View對象
BaseAdapter
-
必須實現(xiàn)的兩個方法
-
第一個
//系統(tǒng)調(diào)用此方法,用來獲知模型層有多少條數(shù)據(jù) @Override public int getCount() { return people.size(); } -
第二個
//系統(tǒng)調(diào)用此方法,獲取要顯示至ListView的View對象 //position:是return的View對象所對應(yīng)的數(shù)據(jù)在集合中的位置 @Override public View getView(int position, View convertView, ViewGroup parent) { System.out.println("getView方法調(diào)用" + position); TextView tv = new TextView(MainActivity.this); //拿到集合中的元素 Person p = people.get(position); tv.setText(p.toString()); //把TextView的對象返回出去,它會變成ListView的條目 return tv; }
-
屏幕上能顯示多少個條目,getView方法就會被調(diào)用多少次,屏幕向下滑動時,getView會繼續(xù)被調(diào)用,創(chuàng)建更多的View對象顯示至屏幕
條目的緩存
- 當條目劃出屏幕時,系統(tǒng)會把該條目緩存至內(nèi)存,當該條目再次進入屏幕,系統(tǒng)在重新調(diào)用getView時會把緩存的條目作為convertView參數(shù)傳入,但是傳入的條目不一定是之前被緩存的該條目,即系統(tǒng)有可能在調(diào)用getView方法獲取第一個條目時,傳入任意一個條目的緩存
ArrayAdapter(熟悉)
-
在條目中顯示一個字符串
String[] objects = new String[]{ "張三", "李四", "王五" }; ListView lv = (ListView) findViewById(R.id.lv); //arg1:指定要填充的布局文件 //arg2:指定文本顯示至哪一個文本框內(nèi) lv.setAdapter(new ArrayAdapter<String>(this, R.layout.item_array, R.id.tv_name, objects));
SimpleAdapter(熟悉)
可在條目中顯示多種數(shù)據(jù)
-
要顯示的數(shù)據(jù)封裝在List中,集合的每一個元素存放的是一個條目會顯示的數(shù)據(jù),因為可能會有多種數(shù)據(jù),而集合的泛型只能指定一種數(shù)據(jù),所以把數(shù)據(jù)先存放在Map中,在把Map放入List中
List<Map<String, Object>> data = new ArrayList<Map<String,Object>>(); //張三的頭像和名字是兩種類型的數(shù)據(jù),先封裝至Map Map<String, Object> map1 = new HashMap<String, Object>(); map1.put("name", "張三"); map1.put("image", R.drawable.photo1); //把Map封裝至List data.add(map1); ... 通過兩個數(shù)組的下標對應(yīng)指定數(shù)據(jù)存放入對應(yīng)的控件中
lv.setAdapter(new SimpleAdapter(this, data, R.layout.item_array,
new String[]{"name", "image"}, new int[]{R.id.tv_name, R.id.iv_photo}));