ListView常用優(yōu)化技巧(Android群英傳)

內(nèi)容是博主照著書敲出來(lái)的掀泳,博主碼字挺辛苦的况既,轉(zhuǎn)載請(qǐng)注明出處,后序內(nèi)容陸續(xù)會(huì)碼出属瓣。

前言:ListView——列表载迄,它作為一個(gè)非常重要的顯示方式,不管是在Web中還是移動(dòng)平臺(tái)中抡蛙,都是一個(gè)非常好的护昧、不開或缺的展示信息的工具。在Android中粗截,ListView控件接管了這一重?fù)?dān)惋耙,在大量的場(chǎng)合下,我們都需要使用這個(gè)控件。雖然在Android 5.X時(shí)代绽榛,RecyclerView在很多地方都在逐漸取代ListView遥金,但ListView的使用范圍依然非常的廣泛,它這萬(wàn)年老大哥的地位也不是輕易就能撼動(dòng)的蒜田。下面就介紹一下ListView常用優(yōu)化技巧稿械。

使用ViewHolder模式提高效率

ViewHolder模式是提高ListView效率的一個(gè)很重要的方法。ViewHolder模式充分利用了ListView的視圖緩存機(jī)制冲粤,避免了每次在調(diào)用getView()的時(shí)候都去通過(guò)findViewById()實(shí)例化控件美莫。據(jù)測(cè)試,使用ViewHolder將提高50%以上的效率梯捕。使用ViewHolder模式來(lái)優(yōu)化ListView非常簡(jiǎn)單厢呵,只需要在自定義Adapter中定義一個(gè)內(nèi)部類ViewHolder,并將布局中的控件作為成員變量傀顾,代碼如下所示襟铭。

public final class ViewHolder {
    public ImageView img;
    public TextView title;
}

接下來(lái),只要在getView()方法中通過(guò)視圖緩存機(jī)制來(lái)重用以緩存即可短曾,完整的使用ViewHolder創(chuàng)建ListView Adapter的實(shí)例代碼如下所示寒砖。

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
 
import java.util.List;
 
/*********************************************
* author: Blankj on 2016/7/23 15:39
 * blog:   http://blankj.com
* e-mail: blankj@qq.com
*********************************************/
public class ViewHolderAdapter extends BaseAdapter {
 
    private List<String> mData;
    private LayoutInflater mInflater;
 
    public ViewHolderAdapter(Context context, List<String> data) {
        this.mData = data;
        mInflater = LayoutInflater.from(context);
    }
 
    @Override
    public int getCount() {
        return mData.size();
    }
 
    @Override
    public Object getItem(int position) {
        return mData.get(position);
    }
 
    @Override
    public long getItemId(int position) {
        return position;
    }
 
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder = null;
        // 判斷是否緩存
        if (convertView == null) {
            viewHolder = new ViewHolder();
            // 通過(guò)LayoutInflater實(shí)例化布局
            convertView = mInflater.inflate(R.layout.viewholder_item, null);
            viewHolder.img = (ImageView) convertView.findViewById(R.id.imageView);
            viewHolder.title = (TextView) convertView.findViewById(R.id.textView);
            convertView.setTag(viewHolder);
        }else {
            // 通過(guò)tag找到緩存的布局
            viewHolder = (ViewHolder) convertView.getTag();
        }
        // 設(shè)置布局中控件要顯示的視圖
        viewHolder.img.setBackgroundResource(R.mipmap.ic_launcher);
        viewHolder.title.setText(mData.get(position));
        return convertView;
    }
 
    public final class ViewHolder {
        public ImageView img;
        public TextView title;
    }
}

效果很簡(jiǎn)單,這就是一個(gè)簡(jiǎn)單的ListView嫉拐,如下圖所示哩都。

使用ViewHolder的ListView

設(shè)置項(xiàng)目間分隔線

ListView的各個(gè)項(xiàng)目之間,可以通過(guò)設(shè)置分隔線來(lái)進(jìn)行區(qū)分婉徘,系統(tǒng)提供了divider和dividerHeight這樣兩個(gè)屬性來(lái)幫助我們實(shí)現(xiàn)這一功能漠嵌。通過(guò)這兩個(gè)屬性,也可以控制ListView之間的分隔線和它的高度盖呼。當(dāng)然儒鹿,分隔線不僅僅可以設(shè)置為一個(gè)顏色,同樣也可以設(shè)置為一個(gè)圖片資源几晤,分隔線的使用代碼如下所示约炎。

android:divider="@color/colorAccent"
android:dividerHeight="10dp"

以上代碼所實(shí)行的效果如下圖所示。

ListView分隔線

特殊情況下锌仅,當(dāng)設(shè)置分隔線為如下代碼時(shí)章钾,就可以把分隔線設(shè)置為透明了。

android:divider="@null"

隱藏ListView的滾動(dòng)條

默認(rèn)的ListView在滾動(dòng)時(shí)热芹,在右邊會(huì)顯示滾動(dòng)條,指示當(dāng)前滑動(dòng)的位置惨撇,我們可以設(shè)置scrollbars屬性伊脓,控制ListView的滾動(dòng)條狀態(tài)。特別地,當(dāng)設(shè)置scrollbars屬性為none的時(shí)候报腔,ListView滾動(dòng)或者不滾動(dòng)株搔,就都不會(huì)出現(xiàn)滾動(dòng)條了,代碼如下所示纯蛾。

android:scrollbars="none"

取消ListView的Item點(diǎn)擊效果

當(dāng)點(diǎn)擊ListView中的一項(xiàng)時(shí)纤房,系統(tǒng)默認(rèn)會(huì)出現(xiàn)一個(gè)點(diǎn)擊效果,在Android5.X上是一個(gè)波紋效果翻诉,而在Android5.X之下的版本則是一個(gè)改變背景顏色的效果炮姨,但可以通過(guò)修改listSelector屬性來(lái)取消掉點(diǎn)擊后的回饋效果,代碼如下所示碰煌。

android:listSelector="#00000000"

當(dāng)然舒岸,也可以直接使用Android自帶的透明色來(lái)實(shí)現(xiàn)這個(gè)效果,代碼如下所示芦圾。

android:listSelector="@android:color/transparent"

設(shè)置ListView需要顯示在第幾項(xiàng)

ListView以Item為單位進(jìn)行顯示蛾派,默認(rèn)顯示在第一個(gè)Item,當(dāng)需要指定具體顯示的Item時(shí)个少,可以通過(guò)如下代碼來(lái)實(shí)現(xiàn)洪乍。

mListView.setSelection(N);

其中N就是需要顯示的第N個(gè)Item。
  當(dāng)然夜焦,這個(gè)方法類似scrollTo典尾,是瞬間完成的移動(dòng)。除此以外糊探,還可以使用如下代碼來(lái)實(shí)現(xiàn)平滑移動(dòng)钾埂。

mListView.smoothScrollBy(distance,duration);
mListView.smoothScrollByOffset(offset);
mListView.smoothScrollToPosition(index);

動(dòng)態(tài)修改ListView

ListView中的數(shù)據(jù)在某些情況下是需要變化的,當(dāng)然可以通過(guò)重新設(shè)置ListView的Adapter來(lái)更新ListView的顯示科平,但這也就需要重新獲取一下數(shù)據(jù)褥紫,相當(dāng)于重新刷新創(chuàng)建的ListView,這樣顯然不是非常友好瞪慧,而且效率也不會(huì)太高髓考。因此,可以使用一個(gè)更簡(jiǎn)單的方法來(lái)實(shí)現(xiàn)ListView的動(dòng)態(tài)修改弃酌,代碼如下所示氨菇。

mData.add("new");
mAdapter.notifyDataSetChanged();

當(dāng)修改了傳遞給Adapter的映射List之后,只需要通過(guò)調(diào)用Adapter的notifyDataSetChanged()方法妓湘,通知ListView更改數(shù)據(jù)源即可完成對(duì)ListView的動(dòng)態(tài)修改查蓉。不過(guò),使用這個(gè)方法有一點(diǎn)需要注意的是榜贴,在使用mAdapter.notifyDataSetChanged()方法時(shí)豌研,必須保證傳進(jìn)Adapter的數(shù)據(jù)List是同一個(gè)List而不能是其他對(duì)象,否則將無(wú)法實(shí)現(xiàn)該效果。下面這個(gè)實(shí)例就演示了如何動(dòng)態(tài)地修改ListView鹃共。通過(guò)點(diǎn)擊按鈕鬼佣,不斷地給原有的List增加一個(gè)新的Item,并調(diào)用notifyDataSetChanged()方法來(lái)實(shí)現(xiàn)ListView的動(dòng)態(tài)更新霜浴,完整代碼如下所示晶衷。

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.ListView;
 
import java.util.ArrayList;
 
public class MainActivity extends AppCompatActivity {
 
    ListView mListView;
    ViewHolderAdapter mAdapter;
    ArrayList<String> mData;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mListView = (ListView) findViewById(R.id.listView);
        mData = new ArrayList<>();
        for (int i = 0; i < 20; ++i) {
            mData.add(i + "");
        }
        mAdapter = new ViewHolderAdapter(this, mData);
        mListView.setAdapter(mAdapter);
        mAdapter.notifyDataSetChanged();
        for (int i = 0, len = mListView.getCheckedItemCount(); i < len; i++) {
            View view = mListView.getChildAt(i);
        }
    }
 
    public void btnAdd(View view) {
        mData.add("new");
        mAdapter.notifyDataSetChanged();
        mListView.setSelection(mData.size() - 1);
    }
}

實(shí)現(xiàn)的效果如下圖所示。

動(dòng)態(tài)更新ListView

遍歷ListView中的所有Item

ListView作為一個(gè)ViewGroup阴孟,為我們提供了操縱子View的各種方法晌纫,最常用的就是通過(guò)getChildAt()來(lái)獲取第i個(gè)子View,代碼如下所示温眉。

for (int i = 0, len = mListView.getCheckedItemCount(); i < len; i++) {
    View view = mListView.getChildAt(i);
}

處理空ListView

ListView用于展示列表數(shù)據(jù)缸匪,但當(dāng)列表中無(wú)數(shù)據(jù)時(shí),ListView不會(huì)顯示任何數(shù)據(jù)或提示类溢,按照完善用戶體驗(yàn)的需求凌蔬,這里應(yīng)該給以無(wú)數(shù)據(jù)的提示。幸好闯冷,ListView提供了一個(gè)方法——setEmptyView()砂心,通過(guò)這個(gè)方法,我們可以給ListView設(shè)置一個(gè)在空數(shù)據(jù)下顯示的默認(rèn)提示蛇耀。包含ListView的布局設(shè)置如下辩诞。

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.blankj.listviewskill.MainActivity">
 
    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:divider="@null"
        android:listSelector="@android:color/transparent"
        android:paddingBottom="40dp"/>
 
    <ImageView
        android:id="@+id/empty_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="@mipmap/ic_launcher"/>
</FrameLayout>

在代碼中,我們通過(guò)以下方式給ListView設(shè)置空數(shù)據(jù)時(shí)要顯示的布局纺涤,代碼如下所示译暂。

mListView.setEmptyView(findViewById(R.id.empty_view));

通過(guò)以上代碼,就給ListView在空數(shù)據(jù)時(shí)顯示了一張默認(rèn)的圖片撩炊,用來(lái)提示用戶外永;而在有數(shù)據(jù)時(shí),則不會(huì)顯示拧咳。

ListView的滑動(dòng)監(jiān)聽

ListView的滑動(dòng)監(jiān)聽伯顶,是ListView中最重要的技巧,很多重寫的ListView基本上都是在滑動(dòng)事件的處理上下功夫骆膝,通過(guò)判斷滑動(dòng)事件進(jìn)行不同的邏輯處理祭衩。而為了更佳精確地監(jiān)聽滑動(dòng)事件,開發(fā)者通常還需要使用GestureDetector手勢(shì)識(shí)別阅签、VelocityTracker滑動(dòng)速度檢測(cè)等輔助類來(lái)完成更好的監(jiān)聽掐暮。這里介紹兩種監(jiān)聽ListView滑動(dòng)事件的方法,一個(gè)是通過(guò)OnTouchListener來(lái)實(shí)現(xiàn)監(jiān)聽愉择,另一個(gè)是使用OnScrollListener來(lái)實(shí)現(xiàn)監(jiān)聽劫乱。

OnTouchListener

OnTouchListener是View中的監(jiān)聽事件织中,通過(guò)監(jiān)聽ACTION_DOWN锥涕、ACTION_MOVE衷戈、ACTION_UP這三個(gè)事件發(fā)生時(shí)的坐標(biāo),就可以根據(jù)坐標(biāo)判斷用戶滑動(dòng)的方向层坠,并在不同的事件中進(jìn)行相應(yīng)的邏輯處理殖妇,這種方式的使用代碼如下所示。

mListView.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                // 觸摸時(shí)操作
                break;
            case MotionEvent.ACTION_MOVE:
                // 移動(dòng)時(shí)操作
                break;
            case MotionEvent.ACTION_UP:
                // 離開時(shí)操作
                break;
        }
        return false;
    }
});

OnScrollListener

OnScrollListener是AbsListView中的監(jiān)聽事件破花,它封裝了很多ListView相關(guān)的信息谦趣,使用起來(lái)也更加靈活。首先來(lái)看一下OnScrollListener的一般使用方法座每,代碼如下所示前鹅。

mListView.setOnScrollListener(new AbsListView.OnScrollListener() {
    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        switch (scrollState) {
            case SCROLL_STATE_IDLE:
                // 滑動(dòng)停止時(shí)
                Log.d("Test", "SCROLL_STATE_IDLE");
                break;
            case SCROLL_STATE_TOUCH_SCROLL:
                // 正在滾動(dòng)
                Log.d("Test", "SCROLL_STATE_TOUCH_SCROLL");
                break;
            case SCROLL_STATE_FLING:
                // 手指拋動(dòng)時(shí),即手指用力滑動(dòng)
                // 在離開后ListView由于慣性繼續(xù)滑動(dòng)
                Log.d("Test", "SCROLL_STATE_FLING");
                break;
        }
    }
    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        // 滾動(dòng)時(shí)一直調(diào)用
        Log.d("Test", "onScroll");
    }

OnScrollListener中有兩個(gè)回調(diào)方法——onScrollStateChanged()和onScroll()峭梳。
  先來(lái)看第一個(gè)方法onScrollStateChanged()舰绘,這個(gè)方法根據(jù)它的參數(shù)scrollState來(lái)決定其回調(diào)的次數(shù),scrollState有以下三種模式:
  ·SCROLL_STATE_IDLE:滾動(dòng)停止時(shí)葱椭。
  ·SCROLL_STATE_TOUCH_SCROLL:正在滾動(dòng)時(shí)捂寿。
  ·SCROLL_STATE_FLING:手指拋動(dòng)時(shí),即手指用力滑動(dòng)孵运,在離開后ListView由于慣性繼續(xù)滑動(dòng)
  當(dāng)用戶沒(méi)有做手指拋動(dòng)的狀態(tài)時(shí)秦陋,這個(gè)方法只會(huì)回調(diào)2次,否則會(huì)回調(diào)三次治笨,差別就是手指拋動(dòng)的這個(gè)狀態(tài)驳概。通常情況下,我們會(huì)在這個(gè)方法中通過(guò)不同的狀態(tài)來(lái)設(shè)置一些標(biāo)志Flag旷赖,來(lái)區(qū)分不同的滑動(dòng)狀態(tài)顺又,供其他方法處理。
  下面再來(lái)看看onScroll()這個(gè)回調(diào)方法杠愧,它在ListView滾動(dòng)時(shí)會(huì)一直回調(diào)待榔,而方法中的后三個(gè)int類型的參數(shù),則非常精確地顯示了當(dāng)前ListView滾動(dòng)的狀態(tài)流济,這三個(gè)參數(shù)如下所示锐锣。
  ·firstVisibleItem:當(dāng)前能看見的第一個(gè)Item的ID(從0開始)
  ·visibleItemCount:當(dāng)前能看見的Item的總數(shù)。
  ·totalItemCount:整個(gè)ListView的Item總數(shù)绳瘟。
  這里需要注意的是雕憔,當(dāng)前能看見的Item數(shù),包括沒(méi)有顯示完整的Item糖声,即顯示一小半的Item也包括在內(nèi)了斤彼。通過(guò)這幾個(gè)參數(shù)分瘦,可以很方便地進(jìn)行一些判斷,比如判斷是否滾動(dòng)到最后一行琉苇,就可以使用如下代碼進(jìn)行判斷嘲玫,當(dāng)前可視的另一個(gè)Item的ID加上當(dāng)前可視Item的和等于Item總數(shù)的時(shí)候,即滾動(dòng)到了最后一行并扇。

if (firstVisibleItem + visibleItemCount == totalItemCount && totalItemCount > 0) {
    Log.d("Test", "滾動(dòng)到最后一行");
}

再比如去团,可以通過(guò)如下代碼來(lái)判斷滾動(dòng)的方向,代碼如下所示穷蛹。

if(firstVisibleItem > lastVisibleItem){
    // 上滑
}else if(firstVisibleItem < lastVisibleItem){
    // 下滑
}
lastVisibleItem = firstVisibleItem;

通過(guò)一個(gè)成員變量lastVisibleItem來(lái)記錄上次第一個(gè)可視的Item的ID并于當(dāng)前的可視Item的ID進(jìn)行比較土陪,即可知道當(dāng)前滾動(dòng)的方向。
  要理解整個(gè)OnScrollListener肴熏,最好的方法還是在代碼中添加Log鬼雀,并打印出狀態(tài)信息來(lái)進(jìn)行分析學(xué)習(xí)。在以上代碼中蛙吏,已經(jīng)添加了相應(yīng)的Log源哩,對(duì)照Log進(jìn)行分析,會(huì)很快掌握OnScrollListener的用法出刷。
  當(dāng)然璧疗,ListView也給我們提供了一些封裝的方法來(lái)獲得當(dāng)前可視的Item的位置等信息。

// 獲取可視區(qū)域內(nèi)最后一個(gè)Item的id
mListView.getLastVisiblePosition();
// 獲取可視區(qū)域內(nèi)第一個(gè)Item的id
mListView.getFirstVisiblePosition();

項(xiàng)目地址→ListViewSkill


原文地址ListView常用優(yōu)化技巧(Android群英傳)
我的自媒體博客blankj小站(OJ馁龟、LeetCode崩侠、Android開發(fā)),歡迎來(lái)逛逛坷檩。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末却音,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子矢炼,更是在濱河造成了極大的恐慌系瓢,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件句灌,死亡現(xiàn)場(chǎng)離奇詭異夷陋,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)香椎,“玉大人种柑,你說(shuō)我怎么就攤上這事核芽。” “怎么了?”我有些...
    開封第一講書人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)撤缴。 經(jīng)常有香客問(wèn)我刹枉,道長(zhǎng),這世上最難降的妖魔是什么屈呕? 我笑而不...
    開封第一講書人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任微宝,我火速辦了婚禮,結(jié)果婚禮上凉袱,老公的妹妹穿的比我還像新娘芥吟。我一直安慰自己侦铜,他們只是感情好专甩,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著钉稍,像睡著了一般涤躲。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上贡未,一...
    開封第一講書人閱讀 49,764評(píng)論 1 290
  • 那天种樱,我揣著相機(jī)與錄音,去河邊找鬼俊卤。 笑死嫩挤,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的消恍。 我是一名探鬼主播岂昭,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼狠怨!你這毒婦竟也來(lái)了约啊?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤佣赖,失蹤者是張志新(化名)和其女友劉穎恰矩,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體憎蛤,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡外傅,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了俩檬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片萎胰。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖豆胸,靈堂內(nèi)的尸體忽然破棺而出奥洼,到底是詐尸還是另有隱情,我是刑警寧澤晚胡,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布灵奖,位于F島的核電站嚼沿,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏瓷患。R本人自食惡果不足惜骡尽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望擅编。 院中可真熱鬧攀细,春花似錦、人聲如沸爱态。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)锦担。三九已至俭识,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間洞渔,已是汗流浹背套媚。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留磁椒,地道東北人堤瘤。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像浆熔,于是被迫代替她去往敵國(guó)和親本辐。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

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