Android inflate方法總結(jié)

前言

inflater.inflate(R.layout.layout_inflate_test,null);
inflater.inflate(R.layout.layout_inflate_test, root,false);
inflater.inflate(R.layout.layout_inflate_test, root,true);

看到上面這幾個方法是不是非常眼熟,基本上做過Android開發(fā)的人都會調(diào)用過inflate方法硼讽,可是你真的了解inflate方法嗎?各個參數(shù)都是什么含義?傳遞不同參數(shù)會產(chǎn)生什么效果折欠?以前的觀點是鑰匙就是用來開鎖的,椅子就是用來坐的吼过,能用不就行了锐秦,管它原理是什么。這種觀點對于一個新手還好說盗忱,刨根問底確實有點難度酱床,但是隨著時間的推移,你總會不斷遇到一些相同的問題趟佃。如果你不早點把原理搞清楚扇谣,那么你就像路過沒有燈光的胡同,會在相同的地方跌倒一次又一次闲昭。扯遠了哈罐寨,其實網(wǎng)上對inflate方法太多的總結(jié)和分析,我在這里主要是自己記錄總結(jié)序矩,當然能幫到有需要的人更好鸯绿。

我先提供三個鏈接:分析都挺好的
1,郭神分析:http://blog.csdn.net/guolin_blog/article/details/12921889
2, http://blog.csdn.net/u012702547/article/details/52628453
3, http://blog.csdn.net/l540675759/article/details/78080656

其實博主我,之前沒寫這篇博客的時候楞慈,只會一直用幔烛,然后都不知道LayoutInflater的加載原理,每次直接
LayoutInflater.from(context).inflate(R.layout.activity_test, root, false);
//不行就這樣囊蓝,反正有一種能實現(xiàn)我要的效果
LayoutInflater.from(context).inflate(R.layout.activity_test, null);
反正總有一種方式適合我饿悬。

上面摘錄自第三篇博客,我深有共鳴聚霜。我以前也是這樣狡恬,雖然閉著眼睛,憑著經(jīng)驗也可以邁過一些坑蝎宇。但是如果你是一個有追求的想讓自己的title加上高級兩個字的工程師弟劲,你就要去看源碼,去了解有疑問的地方的原理姥芥,不然你去大廠面試的時候深深體會到書到用時方恨少兔乞,胸中無墨,啞口無言的真正含義凉唐。

分析

首先

放源碼之前先要知道inflate方法是干嘛的庸追,看返回是一個View,就知道這個方法是要根據(jù)布局id把這個布局加載成一個View并返回的台囱。

源碼分析

   /**
     * ...
     */
    public View inflate(@LayoutRes int resource, @Nullable ViewGroup root) {
        return inflate(resource, root, root != null);
    }

    /**
     * ...
     */
    public View inflate(XmlPullParser parser, @Nullable ViewGroup root) {
        return inflate(parser, root, root != null);
    }

    /**
     * Inflate a new view hierarchy from the specified xml resource. Throws
     * {@link InflateException} if there is an error.
     *
     * @param resource ID for an XML layout resource to load (e.g.,
     *        <code>R.layout.main_page</code>)
     * @param root Optional view to be the parent of the generated hierarchy (if
     *        <em>attachToRoot</em> is true), or else simply an object that
     *        provides a set of LayoutParams values for root of the returned
     *        hierarchy (if <em>attachToRoot</em> is false.)
     * @param attachToRoot Whether the inflated hierarchy should be attached to
     *        the root parameter? If false, root is only used to create the
     *        correct subclass of LayoutParams for the root view in the XML.
     * @return The root View of the inflated hierarchy. If root was supplied and
     *         attachToRoot is true, this is root; otherwise it is the root of
     *         the inflated XML file.
     */
    public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot) {
        final Resources res = getContext().getResources();
        if (DEBUG) {
            Log.d(TAG, "INFLATING from resource: \"" + res.getResourceName(resource) + "\" ("
                    + Integer.toHexString(resource) + ")");
        }

        final XmlResourceParser parser = res.getLayout(resource);
        try {
            return inflate(parser, root, attachToRoot);
        } finally {
            parser.close();
        }
    }

    /**
     * Inflate a new view hierarchy from the specified XML node. Throws
     * {@link InflateException} if there is an error.
     * <p>
     * <em><strong>Important</strong></em>&nbsp;&nbsp;&nbsp;For performance
     * reasons, view inflation relies heavily on pre-processing of XML files
     * that is done at build time. Therefore, it is not currently possible to
     * use LayoutInflater with an XmlPullParser over a plain XML file at runtime.
     *
     * @param parser XML dom node containing the description of the view
     *        hierarchy.
     * @param root Optional view to be the parent of the generated hierarchy (if
     *        <em>attachToRoot</em> is true), or else simply an object that
     *        provides a set of LayoutParams values for root of the returned
     *        hierarchy (if <em>attachToRoot</em> is false.)
     * @param attachToRoot Whether the inflated hierarchy should be attached to
     *        the root parameter? If false, root is only used to create the
     *        correct subclass of LayoutParams for the root view in the XML.
     * @return The root View of the inflated hierarchy. If root was supplied and
     *         attachToRoot is true, this is root; otherwise it is the root of
     *         the inflated XML file.
     */
    public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
        synchronized (mConstructorArgs) {
            Trace.traceBegin(Trace.TRACE_TAG_VIEW, "inflate");

            final Context inflaterContext = mContext;
            final AttributeSet attrs = Xml.asAttributeSet(parser);
            Context lastContext = (Context) mConstructorArgs[0];
            mConstructorArgs[0] = inflaterContext;
            View result = root;

            try {
                // Look for the root node.
                int type;
                while ((type = parser.next()) != XmlPullParser.START_TAG &&
                        type != XmlPullParser.END_DOCUMENT) {
                    // Empty
                }

                if (type != XmlPullParser.START_TAG) {
                    throw new InflateException(parser.getPositionDescription()
                            + ": No start tag found!");
                }

                final String name = parser.getName();

                if (DEBUG) {
                    System.out.println("**************************");
                    System.out.println("Creating root view: "
                            + name);
                    System.out.println("**************************");
                }

                if (TAG_MERGE.equals(name)) {
                    if (root == null || !attachToRoot) {
                        throw new InflateException("<merge /> can be used only with a valid "
                                + "ViewGroup root and attachToRoot=true");
                    }

                    rInflate(parser, root, inflaterContext, attrs, false);
                } else {
                    // Temp is the root view that was found in the xml
                    final View temp = createViewFromTag(root, name, inflaterContext, attrs);

                    ViewGroup.LayoutParams params = null;

                    if (root != null) {
                        if (DEBUG) {
                            System.out.println("Creating params from root: " +
                                    root);
                        }
                        // Create layout params that match root, if supplied
                        params = root.generateLayoutParams(attrs);
                        if (!attachToRoot) {
                            // Set the layout params for temp if we are not
                            // attaching. (If we are, we use addView, below)
                            temp.setLayoutParams(params);
                        }
                    }

                    if (DEBUG) {
                        System.out.println("-----> start inflating children");
                    }

                    // Inflate all children under temp against its context.
                    rInflateChildren(parser, temp, attrs, true);

                    if (DEBUG) {
                        System.out.println("-----> done inflating children");
                    }

                    // We are supposed to attach all the views we found (int temp)
                    // to root. Do that now.
                    if (root != null && attachToRoot) {
                        root.addView(temp, params);
                    }

                    // Decide whether to return the root that was passed in or the
                    // top view found in xml.
                    if (root == null || !attachToRoot) {
                        result = temp;
                    }
                }

            } catch (XmlPullParserException e) {
                final InflateException ie = new InflateException(e.getMessage(), e);
                ie.setStackTrace(EMPTY_STACK_TRACE);
                throw ie;
            } catch (Exception e) {
                final InflateException ie = new InflateException(parser.getPositionDescription()
                        + ": " + e.getMessage(), e);
                ie.setStackTrace(EMPTY_STACK_TRACE);
                throw ie;
            } finally {
                // Don't retain static reference on context.
                mConstructorArgs[0] = lastContext;
                mConstructorArgs[1] = null;

                Trace.traceEnd(Trace.TRACE_TAG_VIEW);
            }

            return result;
        }
    }

源碼有點長淡溯,不要被嚇到,下面一一拆解
看源碼一共有四個inflate方法簿训,這四個又分為兩類:

首參數(shù)為布局id咱娶,@LayoutRes int resource ,也是我們經(jīng)常用的强品;
public View inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot)

首參數(shù)為Parser膘侮,XmlPullParser parse ,我開發(fā)中好像沒有用到過的榛。
public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot)

源碼中inflate(R.layout.layout_inflate_test,null)其實調(diào)用的是inflate(@LayoutRes int resource, @Nullable ViewGroup root, boolean attachToRoot)琼了,inflate(XmlPullParser parser, @Nullable ViewGroup root)調(diào)用的是inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot)。

final XmlResourceParser parser = res.getLayout(resource);
        try {
            return inflate(parser, root, attachToRoot);
        } finally {
            parser.close();
        }

第一類其實調(diào)用的也是第四個方法困曙。那就著重看一下第四個方法inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot)表伦。
開始分析:

final Context inflaterContext = mContext;
final AttributeSet attrs = Xml.asAttributeSet(parser);
Context lastContext = (Context) mConstructorArgs[0];
mConstructorArgs[0] = inflaterContext;
View result = root;

看開始的幾句代碼谦去,先不管前面的那幾句定義慷丽,最后一句話View result = root;那么這個result基本就是作為返回值了,看這個方法最后return result;好吧果然是的鳄哭。result = root要糊,也就是將第二個參數(shù)ViewGroup root返回了,但是使用的inflate方法的時候我們有可能傳遞的是null也有可能不是null妆丘,繼續(xù)往下看

// Look for the root node.
int type;
while ((type = parser.next()) != XmlPullParser.START_TAG &&
        type != XmlPullParser.END_DOCUMENT) {
    // Empty
}

if (type != XmlPullParser.START_TAG) {
    throw new InflateException(parser.getPositionDescription()
            + ": No start tag found!");
}

final String name = parser.getName();

這幾句的意思是獲取到根節(jié)點的標簽名稱

if (TAG_MERGE.equals(name)) {
    if (root == null || !attachToRoot) {
        throw new InflateException("<merge /> can be used only with a valid "
                + "ViewGroup root and attachToRoot=true");
    }

    rInflate(parser, root, inflaterContext, attrs, false);
}

如果根節(jié)點的標簽是merge锄俄,如果root為null或者attachToRoot為false會直接拋異常局劲,也就是當根標簽為merge的時候必須使用inflater.inflate(R.layout.layout_inflate_test, root,true);這種形式,不然會報錯奶赠,你可以自己試驗一下鱼填。實驗結(jié)果:


329DC4C2-A7AF-4B70-807C.png

繼續(xù)往下看:rInflate(parser, root, inflaterContext, attrs, false);

/**
     * Recursive method used to descend down the xml hierarchy and instantiate
     * views, instantiate their children, and then call onFinishInflate().
     * <p>
     * <strong>Note:</strong> Default visibility so the BridgeInflater can
     * override it.
     */
    void rInflate(XmlPullParser parser, View parent, Context context,
            AttributeSet attrs, boolean finishInflate) throws XmlPullParserException, IOException {

        final int depth = parser.getDepth();
        int type;
        boolean pendingRequestFocus = false;

        while (((type = parser.next()) != XmlPullParser.END_TAG ||
                parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {

            if (type != XmlPullParser.START_TAG) {
                continue;
            }

            final String name = parser.getName();

            if (TAG_REQUEST_FOCUS.equals(name)) {
                pendingRequestFocus = true;
                consumeChildElements(parser);
            } else if (TAG_TAG.equals(name)) {
                parseViewTag(parser, parent, attrs);
            } else if (TAG_INCLUDE.equals(name)) {
                if (parser.getDepth() == 0) {
                    throw new InflateException("<include /> cannot be the root element");
                }
                parseInclude(parser, context, parent, attrs);
            } else if (TAG_MERGE.equals(name)) {
                throw new InflateException("<merge /> must be the root element");
            } else {
                final View view = createViewFromTag(parent, name, context, attrs);
                final ViewGroup viewGroup = (ViewGroup) parent;
                final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);
                rInflateChildren(parser, view, attrs, true);
                viewGroup.addView(view, params);
            }
        }

        if (pendingRequestFocus) {
            parent.restoreDefaultFocus();
        }

        if (finishInflate) {
            parent.onFinishInflate();
        }
    }

這個方法的意思是:遞歸方法進入xml層次結(jié)構(gòu)并實例化視圖,實例化它們的子項毅戈,然后調(diào)用onFinishInflate()苹丸。這個方法的內(nèi)容可以先不看,知道它的作用就行了苇经,就是把這個布局里面的各個子項實例化赘理。舉個例子一個完整的快遞肯定是大盒子包小盒子再包,有的包了好幾層最后才是你的商品扇单。你想要的肯定不是最外層的那個空盒子商模,你需要的是一個完整的快遞。這個方法就是用來把一個或者好幾個商品用紙盒子一層層包起來組成一個可以運輸?shù)目爝f的蜘澜,上面的root就是最外面的那個盒子施流。

else {
    // Temp is the root view that was found in the xml
    final View temp = createViewFromTag(root, name, inflaterContext, attrs);

    ViewGroup.LayoutParams params = null;

    if (root != null) {
        if (DEBUG) {
            System.out.println("Creating params from root: " +
                    root);
        }
        // Create layout params that match root, if supplied
        params = root.generateLayoutParams(attrs);
        if (!attachToRoot) {
            // Set the layout params for temp if we are not
            // attaching. (If we are, we use addView, below)
            temp.setLayoutParams(params);
        }
    }

    if (DEBUG) {
        System.out.println("-----> start inflating children");
    }

    // Inflate all children under temp against its context.
    rInflateChildren(parser, temp, attrs, true);

    if (DEBUG) {
        System.out.println("-----> done inflating children");
    }

    // We are supposed to attach all the views we found (int temp)
    // to root. Do that now.
    if (root != null && attachToRoot) {
        root.addView(temp, params);
    }

    // Decide whether to return the root that was passed in or the
    // top view found in xml.
    if (root == null || !attachToRoot) {
        result = temp;
    }
}

剛才哪個merge是特殊情況,一般常見的是else里面的情況

// Temp is the root view that was found in the xml
final View temp = createViewFromTag(root, name, inflaterContext, attrs);

生成一個root view兼都,也就是根據(jù)根目錄的標簽生成的view嫂沉。這里有個需要注意的地方,最后一個參數(shù)attrs扮碧,也就是說這個根視圖view的一些屬性還是會被添加上去例如背景顏色等屬性

ViewGroup.LayoutParams params = null;

 if (root != null) {
        if (DEBUG) {
            System.out.println("Creating params from root: " +
                    root);
        }
        // Create layout params that match root, if supplied
        params = root.generateLayoutParams(attrs);
        if (!attachToRoot) {
            // Set the layout params for temp if we are not
            // attaching. (If we are, we use addView, below)
            temp.setLayoutParams(params);
        }
    }

考點來了趟章,如果root != null,創(chuàng)建LayoutParams慎王,params = root.generateLayoutParams(attrs);這個參數(shù)attrs來自上面的final AttributeSet attrs = Xml.asAttributeSet(parser);Xml.asAttributeSet(parser)這句代碼我也不是很懂蚓土,但是有時候可以通過具體現(xiàn)象或返回值推算某一句代碼的作用。它返回一個AttributeSet赖淤,AttributeSet是view的布局屬性集合蜀漆,所以這里的作用就是把我們傳入的布局的屬性拿到。然后后面根據(jù)這些屬性創(chuàng)建LayoutParams咱旱∪范看下面

/**
     * Returns a new set of layout parameters based on the supplied attributes set.
     * 根據(jù)提供的屬性集返回一個新的LayoutParams
     * @param attrs the attributes to build the layout parameters from
     *
     * @return an instance of {@link android.view.ViewGroup.LayoutParams} or one
     *         of its descendants
     */
    public LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new LayoutParams(getContext(), attrs);
    }

...

/**
     * Creates a new set of layout parameters. The values are extracted from
     * the supplied attributes set and context. The XML attributes mapped
     * to this set of layout parameters are:
     *
     * <ul>
     *   <li><code>layout_width</code>: the width, either an exact value,
     *   {@link #WRAP_CONTENT}, or {@link #FILL_PARENT} (replaced by
     *   {@link #MATCH_PARENT} in API Level 8)</li>
     *   <li><code>layout_height</code>: the height, either an exact value,
     *   {@link #WRAP_CONTENT}, or {@link #FILL_PARENT} (replaced by
     *   {@link #MATCH_PARENT} in API Level 8)</li>
     * </ul>
     *
     * @param c the application environment
     * @param attrs the set of attributes from which to extract the layout
     *              parameters' values
     */
    public LayoutParams(Context c, AttributeSet attrs) {
        TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.ViewGroup_Layout);
        setBaseAttributes(a,
                R.styleable.ViewGroup_Layout_layout_width,
                R.styleable.ViewGroup_Layout_layout_height);
        a.recycle();
    }

現(xiàn)在有了LayoutParams,如果attachToRoot為false時執(zhí)行temp.setLayoutParams(params);將上面得到的LayoutParams給temp--也就是我們上面根據(jù)布局根目錄標簽創(chuàng)建的的那個View設置上吐限。布局根目錄一般都是LinearLayout鲜侥,RelativeLayout等這些ViewGroup,當然也可以是view
再往下看

if (DEBUG) {
    System.out.println("-----> start inflating children");
}

// Inflate all children under temp against its context.
rInflateChildren(parser, temp, attrs, true);

if (DEBUG) {
    System.out.println("-----> done inflating children");
}
/**
     * Recursive method used to inflate internal (non-root) children. This
     * method calls through to {@link #rInflate} using the parent context as
     * the inflation context.
     * <strong>Note:</strong> Default visibility so the BridgeInflater can
     * call it.
     */
    final void rInflateChildren(XmlPullParser parser, View parent, AttributeSet attrs,
            boolean finishInflate) throws XmlPullParserException, IOException {
        rInflate(parser, parent, parent.getContext(), attrs, finishInflate);
    }

跟剛才哪個merge標簽的情況一樣打包快遞诸典,把子布局子view都一層層組裝起來描函,裝到temp里。繼續(xù)

// We are supposed to attach all the views we found (int temp)
// to root. Do that now.
if (root != null && attachToRoot) {
    root.addView(temp, params);
}

又到考點了,假如root不為空舀寓,并且attachToRoot為true胆数,那么root就把生成的temp裝到自己里面addView,后面還有參數(shù)params互墓。temp會被添加到root的最后必尼,并且params設置給temp。

// Decide whether to return the root that was passed in or the
// top view found in xml.
if (root == null || !attachToRoot) {
    result = temp;
}

最后一個考點篡撵,如果root為空胰伍,那么attachToRoot就不用看了,attachToRoot為true或者false都沒有意義酸休, 直接result = temp骂租。注意這里temp是沒有被設置剛才的LayoutParams的,而LayoutParams是用來設置位置斑司、高渗饮、寬等信息,也就意味著temp的這些屬性是全新的宿刮。

結(jié)論

但是使用的時候我們更關(guān)心的是各個參數(shù)傳遞給我們帶來的影響和效果互站。那么通過看源碼我們得到什么樣的結(jié)論呢?
先把郭神的結(jié)論貼出來:

  1. 如果root為null僵缺,attachToRoot將失去作用胡桃,設置任何值都沒有意義。
  2. 如果root不為null磕潮,attachToRoot設為true翠胰,則會給加載的布局文件的指定一個父布局,即root自脯。
  3. 如果root不為null之景,attachToRoot設為false,則會將布局文件最外層的所有l(wèi)ayout屬性進行設置膏潮,當該view被添加到父view當中時锻狗,這些layout屬性會自動生效。
  4. 在不設置attachToRoot參數(shù)的情況下焕参,如果root不為null轻纪,attachToRoot參數(shù)默認為true。

關(guān)于上面還有一些補充說明叠纷,如果root不為null刻帚,布局文件最外層的layout關(guān)于LayoutParams設置的屬性和其他屬性都會被保留下來,attachToRoot設為true讲岁,則會給加載的布局文件的指定一個父布局我擂,我們不需要自己在addView,否則會報錯缓艳;attachToRoot設為false校摩,需要我們自己addView,root為null時阶淘,被加載的布局LayoutParams的屬性會被改變衙吩,但是其它屬性例如背景顏色什么的會被保留。

參考鏈接

http://blog.csdn.net/guolin_blog/article/details/12921889 http://blog.csdn.net/u012702547/article/details/52628453 http://blog.csdn.net/l540675759/article/details/78080656
https://www.cnblogs.com/coding-way/p/5257579.html
http://blog.csdn.net/jaysong2012/article/details/41117339
http://www.cnblogs.com/xiaoweiz/p/3788332.html
http://www.reibang.com/p/07fcd2517dbc

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末溪窒,一起剝皮案震驚了整個濱河市坤塞,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌澈蚌,老刑警劉巖摹芙,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異宛瞄,居然都是意外死亡浮禾,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門份汗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來盈电,“玉大人,你說我怎么就攤上這事杯活〈抑悖” “怎么了?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵旁钧,是天一觀的道長吸重。 經(jīng)常有香客問我,道長歪今,這世上最難降的妖魔是什么晤锹? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮彤委,結(jié)果婚禮上鞭铆,老公的妹妹穿的比我還像新娘。我一直安慰自己焦影,他們只是感情好车遂,可當我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著斯辰,像睡著了一般舶担。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上彬呻,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天衣陶,我揣著相機與錄音柄瑰,去河邊找鬼。 笑死剪况,一個胖子當著我的面吹牛教沾,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播译断,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼授翻,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了孙咪?” 一聲冷哼從身側(cè)響起堪唐,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎翎蹈,沒想到半個月后淮菠,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡荤堪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年兜材,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片逞力。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡曙寡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出寇荧,到底是詐尸還是另有隱情举庶,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布揩抡,位于F島的核電站户侥,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏峦嗤。R本人自食惡果不足惜蕊唐,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望烁设。 院中可真熱鬧替梨,春花似錦、人聲如沸装黑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽恋谭。三九已至糠睡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間疚颊,已是汗流浹背狈孔。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工信认, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人均抽。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓嫁赏,卻偏偏與公主長得像,于是被迫代替她去往敵國和親到忽。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,486評論 2 348

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

  • 一清寇、適用場景 ListViewListview是一個很重要的組件喘漏,它以列表的形式根據(jù)數(shù)據(jù)的長自適應展示具體內(nèi)容,用...
    Geeks_Liu閱讀 10,654評論 1 28
  • RecyclerView Item 布局寬高無效問題探究 前言 這個問題很早之前就碰到過,后來通過google找到...
    TinyMen閱讀 423評論 0 0
  • 原文地址:http://www.reibang.com/p/de7f651170be 一华烟、簡述 LayoutInf...
    AFinalStone閱讀 4,047評論 1 7
  • 有段時間沒寫博客了翩迈,感覺都有些生疏了呢。最近繁忙的工作終于告一段落盔夜,又有時間寫文章了负饲,接下來還會繼續(xù)堅持每一周篇的...
    justin_pan閱讀 550評論 0 2
  • 不止一次,我掙扎在自己的世界里 不止一次喂链,我認為這世上的一切都是虛假 或許我正活在自己的夢里 在幼年時的某次熟睡 ...
    梅千延閱讀 202評論 0 0