你知道AttributeSet與XmlPullParser的關(guān)系嗎悼枢?

前言

AttributeSet與XmlPullParser這2個接口在解析xml文件時經(jīng)常配合使用提揍,二者可進(jìn)行相互轉(zhuǎn)換,理清二者的關(guān)系對于深入理解LayoutIflater.inflate()源碼時俩由,有著重要作用。
故本文的目的在于理清二者之間的關(guān)系癌蚁,簡述XmlPullParser的基本用法幻梯,為后續(xù)理解LayoutIflater.inflate方法源碼打下基礎(chǔ)。

類圖結(jié)構(gòu)

AttributeSet與XmlPullParser的類圖關(guān)系如下圖所示:


類圖結(jié)構(gòu)

AttributeSet接口抽象了訪問xml節(jié)點屬性的方法努释,XmlPullPaser接口抽象了解析xml文件的方法碘梢,這個2個接口具有部分相同的方法聲明,如下圖所示洽洁。這些方法是XmlPull解析常用來訪問xml節(jié)點屬性的方法痘系。

    int getAttributeCount();
    String getAttributeName(int index);
    String getAttributeValue(int index);
    String getAttributeValue(String namespace, String name);
    String getPositionDescription();

AttributeSet與XmlPullParser的關(guān)系

在Android中AttributeSet接口的實現(xiàn)類有XmlPullAttribute和Parser(XmlResourceParser接口的實現(xiàn)類,該接口繼承了XmlPullParser和AttributeSet接口)饿自。
我們先來看看XmlPullAttribute的實現(xiàn)汰翠,部分代碼如下:

class XmlPullAttributes implements AttributeSet {
    public XmlPullAttributes(XmlPullParser parser) {
        mParser = parser;
    }

    public int getAttributeCount() {
        return mParser.getAttributeCount();
    }

    public String getAttributeName(int index) {
        return mParser.getAttributeName(index);
    }

    public String getAttributeValue(int index) {
        return mParser.getAttributeValue(index);
    }

    public String getAttributeValue(String namespace, String name) {
        return mParser.getAttributeValue(namespace, name);
    }

    public String getPositionDescription() {
        return mParser.getPositionDescription();
    }

    public int getAttributeNameResource(int index) {
        return 0;
    }

    public int getAttributeListValue(String namespace, String attribute,
            String[] options, int defaultValue) {
        return XmlUtils.convertValueToList(
            getAttributeValue(namespace, attribute), options, defaultValue);
    }
     ............
    //AttributeSet接口的剩余方法實現(xiàn)省略,其實現(xiàn)與getAttributeListValue()方法
    //相似昭雌,都依賴XmlUtils與getAttributeValue()复唤。
}

可見該類關(guān)聯(lián)了一個XmlPullParser類型的成員變量(實際上是KXmlParser),AttributeSet接口與XmlPullParser接口相同聲明函數(shù)的實現(xiàn)都是調(diào)用的mParser的同名函數(shù)烛卧;而AttributeSet接口的其他方法皆依賴于getAttributeValue方法來實現(xiàn)佛纫,即也依賴于mParser。
從代碼實現(xiàn)來看总放,很自然的會聯(lián)想到裝飾者設(shè)計模式呈宇,雖然從類圖結(jié)構(gòu)上來看,并非屬于嚴(yán)格意義上的裝飾者模式局雄,但我想可以將AttributeSet理解為XmlPullParser的裝飾者甥啄,只不過這個裝飾者沒有全部裝飾而已,只是裝飾了XmlParser用于訪問xml節(jié)點屬性的那一部分炬搭。
自創(chuàng)部分裝飾設(shè)計蜈漓,強行解說2333....
綜上所述:AttributeSet是對XmlPullParser的部分裝飾穆桂,裝飾了用于訪問xml節(jié)點屬性的部分∪谒洌或者理解為AttributeSet是對XmlPullParser中用于訪問xml節(jié)點屬性方法的封裝享完。

至于為什么要這么做呢?拙見如下:

  1. AttributeSet這個接口更適合Android的設(shè)計有额,其語意性更強般又;如果將View的構(gòu)造函數(shù)中的AttributeSet換為XmlPullParser,看起來是不是有一種別扭的感覺的谆吴,而AttributeSet(屬性集合)這個命名更易讓人理解接受倒源,裝飾的作用之一就是可以“改頭換面”嘛苛预。
  2. 單一職責(zé)原則句狼,XmlPullParser接口的職責(zé)不單單是用于訪問xml節(jié)點的屬性,從中分離出一個用于訪問節(jié)點屬性的接口豈不美哉热某?
  3. 對XmlPullParser中的Xml節(jié)點屬性訪問方法進(jìn)行擴展腻菇,方便使用,如getAttributeIntValue方法可直接獲取int類型的屬性值昔馋,若使用XmlPullParser則只能獲取String類型的數(shù)據(jù)筹吐,還需要我們自己轉(zhuǎn)換一次。

下面來看看XmlResourceParser接口秘遏。
該接口同時繼承了XmlPullParser接口以及AttributeSet接口丘薛,作用有二。

  1. 對XmlPullParser起到部分裝飾的作用邦危,實現(xiàn)XmlResourceParser接口洋侨,即可達(dá)到目的。
  2. 繼承XmlPullParser接口倦蚪,實現(xiàn)一個專用于Android Xml資源文件的解析器希坚,如解析layout、drawable等目錄下的xml文件陵且。
    Android中的常見打開方式如下:
        Resources resources = getResources();
        XmlResourceParser  parser0 = resources.getXml(R.xml.test);
        XmlResourceParser  parser1 = resources.getLayout(R.layout.activity_main);
        XmlResourceParser  parser2 = resources.getAnimation(R.anim.test);

Drawable目錄下的xml解析并未提供我們可直接獲取XmlResourceParser的API裁僧,其解析封裝在ResourseImpl類(@hide)的方法中。

    /**
        * Loads a drawable from XML or resources stream.
        */
    private Drawable loadDrawableForCookie(Resources wrapper, TypedValue value, int id,Resources.Theme theme) {
        ............
        if (file.endsWith(".xml")) {
                final XmlResourceParser rp = loadXmlResourceParser(
                        file, id, value.assetCookie, "drawable");
                dr = Drawable.createFromXml(wrapper, rp, theme);
                rp.close();
            } else {
                final InputStream is = mAssets.openNonAsset(
                        value.assetCookie, file, AssetManager.ACCESS_STREAMING);
                dr = Drawable.createFromResourceStream(wrapper, value, is, file, null);
                is.close();
            }
       ............
}

XmlResourceParser的實現(xiàn)類為Parser類慕购,該類屬于BlockXml類的一個內(nèi)部類聊疲,用于解析Android中的layout布局文件。
這里說一個小技巧沪悲,方便想要自行查看源碼的朋友:
在Android Studio中可通過雙擊Shift鍵來快速查找類文件获洲,可以查到一些隱藏類文件的源碼。
總結(jié)
1可训、AttributeSet接口是對XmlPullParser接口的部分裝飾昌妹,裝飾了XmlPullParser中xml節(jié)點屬性的訪問方法捶枢。AttributeSet接口語意性更強,更適合Android架構(gòu)的整體設(shè)計飞崖。
2烂叔、其實現(xiàn)類無論是Parser還是XmlPullAttribute,它只是起到一個裝飾作用固歪,最終對xml節(jié)點屬性的訪問都是通過里面的XmlPullParser的節(jié)點屬性訪問方法來完成的蒜鸡。

至此,AttributeSet與XmlPullParser的關(guān)系已經(jīng)分析清楚牢裳,后文只是方便自己后續(xù)查看逢防,主要記錄XmlPullParser的基本使用。

轉(zhuǎn)換分析

XmlPullParser轉(zhuǎn)換為AttributeSet的方法為:

  Xml.asAttributeSet(parser0);

進(jìn)去看看源碼:

//如果傳入的XmlPullParser類型為XmlResourceParser(Parser)蒲讯,返回的就是XmlResourceParser(Parser)
//反之則new 一個XmlPullAttributeSet
 public static AttributeSet asAttributeSet(XmlPullParser parser) {
        return (parser instanceof AttributeSet)
                ? (AttributeSet) parser
                : new XmlPullAttributes(parser);
    }

XmlPullParser的基本使用

由上文可知忘朝,Android中XmlPull解析器有2種類型,一種是專用于Android xml資源文件的解析器判帮,一種是org.xmlpull.v1自帶的xml解析器局嘁,無論是那種類型,對外而言晦墙,其用法都一樣悦昵,這就是面向接口編程的一個好處。
實際應(yīng)用當(dāng)中晌畅,使用較多的應(yīng)該是org.xmlpull.v1自帶的xml解析器但指,畢竟Android的專用資源解析器,它已經(jīng)封裝好自動解析了抗楔。

         public static void main (String args[])
                throws XmlPullParserException, IOException
        {
            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
            //區(qū)分namespace
            factory.setNamespaceAware(true);
            XmlPullParser xpp = factory.newPullParser();
   
           /**
             * 解析最開始并非位于START_DOCUMENT,多次調(diào)用next棋凳,會依次位于
             * START_DOCUMENT
             * START_TAG(XML節(jié)點屬性解析只能在該事件類型中進(jìn)行解析)
             * TEXT(無Text部分“Hello World”則跳過該事件類型)
             * END_TAG
             * End document
             */
            xpp.setInput( new StringReader ( "<foo>Hello World!</foo>" ) );
            int eventType = xpp.getEventType();
            while (eventType != XmlPullParser.END_DOCUMENT) {
                if(eventType == XmlPullParser.START_DOCUMENT) {
                    System.out.println("Start document");
                } else if(eventType == XmlPullParser.START_TAG) {
                    System.out.println("Start tag "+xpp.getName());
                } else if(eventType == XmlPullParser.END_TAG) {
                    System.out.println("End tag "+xpp.getName());
                } else if(eventType == XmlPullParser.TEXT) {
                    System.out.println("Text "+xpp.getText());
                }
                eventType = xpp.next();
            }
            System.out.println("End document");
        }

結(jié)果:

 Start document
 Start tag foo
 Text Hello World!
 End tag foo
 End document
 
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市谓谦,隨后出現(xiàn)的幾起案子贫橙,更是在濱河造成了極大的恐慌,老刑警劉巖反粥,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件卢肃,死亡現(xiàn)場離奇詭異,居然都是意外死亡才顿,警方通過查閱死者的電腦和手機莫湘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來郑气,“玉大人幅垮,你說我怎么就攤上這事∥沧椋” “怎么了忙芒?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵示弓,是天一觀的道長。 經(jīng)常有香客問我呵萨,道長奏属,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任潮峦,我火速辦了婚禮囱皿,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘忱嘹。我一直安慰自己嘱腥,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布拘悦。 她就那樣靜靜地躺著齿兔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪窄做。 梳的紋絲不亂的頭發(fā)上愧驱,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天慰技,我揣著相機與錄音椭盏,去河邊找鬼。 笑死吻商,一個胖子當(dāng)著我的面吹牛掏颊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播艾帐,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼乌叶,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了柒爸?” 一聲冷哼從身側(cè)響起准浴,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎捎稚,沒想到半個月后乐横,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡今野,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年葡公,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片条霜。...
    茶點故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡催什,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出宰睡,到底是詐尸還是另有隱情蒲凶,我是刑警寧澤气筋,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站旋圆,受9級特大地震影響裆悄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一螃诅、第九天 我趴在偏房一處隱蔽的房頂上張望步鉴。 院中可真熱鬧,春花似錦艾君、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至权她,卻和暖如春虹茶,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背隅要。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工蝴罪, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人步清。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓要门,卻偏偏與公主長得像,于是被迫代替她去往敵國和親廓啊。 傳聞我的和親對象是個殘疾皇子欢搜,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,914評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,133評論 25 707
  • 綜述 在aapt編譯apk的過程中,aapt中的XMLNode類會將資源生成一個ResXMLTree對象谴轮,并將其序...
    Jtag特工閱讀 2,135評論 1 3
  • 第一次知道“坦白書”一詞好像是朋友Z的介紹炒瘟,剛開始以為馬良這個寫作者是一畫畫的,百度了一下第步,果然是個畫畫的疮装。 最近...
    扯來扯去扯不出蛋閱讀 468評論 0 1
  • 早晨,依然在兒子的讀書聲中醒來雌续,依然感覺到九月早晨的清涼斩个。沐浴晨風(fēng),我在陽臺洗衣驯杜。感賞由兒子的晨讀開啟的每一天受啥。 ...
    葦絮輕揚閱讀 226評論 13 6
  • 我覺得共情的能力高的人,辨識度和識人的品質(zhì)很高,使用客體的能力自然也就高滚局,談判的空間和策略也就更足 我覺得換位思考...
    956d9ce73cd5閱讀 250評論 0 0