RecyclerView 的使用

一筷狼、前言:

1. RecyclerView是什么

從Android 5.0開始棍潘,谷歌公司推出了一個用于大量數(shù)據(jù)展示的新控件RecylerView恃鞋,可以用來代替?zhèn)鹘y(tǒng)的ListView,更加強大和靈活亦歉。

RecyclerView是support-v7包中的新組件恤浪,是一個強大的滑動組件,與經(jīng)典的ListView相比肴楷,同樣擁有item回收復(fù)用的功能水由,這一點從它的名字Recyclerview即回收view也可以看出。

2. RecyclerView的優(yōu)點

RecyclerView并不會完全替代ListView(這點從ListView沒有被標(biāo)記為@Deprecated可以看出)赛蔫,兩者的使用場景不一樣砂客。但是RecyclerView的出現(xiàn)會讓很多開源項目被廢棄,例如橫向滾動的ListView, 橫向滾動的GridView, 瀑布流控件呵恢,因為RecyclerView能夠?qū)崿F(xiàn)所有這些功能鞠值。

比如:有一個需求是屏幕豎著的時候的顯示形式是ListView,屏幕橫著的時候的顯示形式是2列的GridView渗钉,此時如果用RecyclerView彤恶,則通過設(shè)置LayoutManager一行代碼實現(xiàn)替換。

RecylerView相對于ListView的優(yōu)點羅列如下:

  • RecyclerView封裝了viewholder的回收復(fù)用,也就是說RecyclerView標(biāo)準(zhǔn)化了ViewHolder声离,編寫Adapter面向的是ViewHolder而不再是View了歇竟,復(fù)用的邏輯被封裝了,寫起來更加簡單抵恋。
    直接省去了listview中convertView.setTag(holder)和convertView.getTag()這些繁瑣的步驟焕议。

  • 提供了一種插拔式的體驗,高度的解耦弧关,異常的靈活盅安,針對一個Item的顯示RecyclerView專門抽取出了相應(yīng)的類,來控制Item的顯示世囊,使其的擴展性非常強别瞭。

  • 設(shè)置布局管理器以控制Item的布局方式,橫向株憾、豎向以及瀑布流方式

    例如:你想控制橫向或者縱向滑動列表效果可以通過LinearLayoutManager這個類來進行控制
    (與GridView效果對應(yīng)的是GridLayoutManager,
    與瀑布流對應(yīng)的還StaggeredGridLayoutManager等)蝙寨。
    也就是說RecyclerView不再拘泥于ListView的線性展示方式,它也可以實現(xiàn)GridView的效果等多種效果嗤瞎。

  • 可設(shè)置Item的間隔樣式(可繪制)
    通過繼承RecyclerView的ItemDecoration這個類墙歪,然后針對自己的業(yè)務(wù)需求去書寫代碼。

  • 可以控制Item增刪的動畫贝奇,可以通過ItemAnimator這個類進行控制虹菲,當(dāng)然針對增刪的動畫,RecyclerView有其自己默認(rèn)的實現(xiàn)掉瞳。

但是關(guān)于Item的點擊和長按事件毕源,需要用戶自己去實現(xiàn)。

二陕习、 基本使用

1. 依賴:

 //recyclerview依賴
implementation 'com.android.support:recyclerview-v7:27.1.0'
//開源動畫
implementation 'jp.wasabeef:recyclerview-animators:2.2.4'

2. 使用范例:

recyclerView = (RecyclerView) findViewById(R.id.recyclerView);  
LinearLayoutManager layoutManager = new LinearLayoutManager(this );  
//設(shè)置布局管理器  
recyclerView.setLayoutManager(layoutManager);  
//設(shè)置為垂直布局霎褐,這也是默認(rèn)的  
layoutManager.setOrientation(OrientationHelper. VERTICAL);  
//設(shè)置Adapter  
recyclerView.setAdapter(recycleAdapter);  
 //設(shè)置分隔線  
recyclerView.addItemDecoration( new DividerGridItemDecoration(this ));  
//設(shè)置增加或刪除條目的動畫  
recyclerView.setItemAnimator( new DefaultItemAnimator());  

在使用RecyclerView時候,必須指定一個適配器Adapter和一個布局管理器LayoutManager该镣。適配器繼承RecyclerView.Adapter類冻璃,具體實現(xiàn)類似ListView的適配器,取決于數(shù)據(jù)信息以及展示的UI拌牲。布局管理器用于確定RecyclerView中Item的展示方式以及決定何時復(fù)用已經(jīng)不可見的Item俱饿,避免重復(fù)創(chuàng)建以及執(zhí)行高成本的findViewById()方法歌粥。

可以看見RecyclerView相比ListView會多出許多操作塌忽,這也是RecyclerView靈活的地方,它將許多動能暴露出來失驶,用戶可以選擇性的自定義屬性以滿足需求土居。

3. 創(chuàng)建適配器

標(biāo)準(zhǔn)實現(xiàn)步驟如下:
創(chuàng)建Adapter:創(chuàng)建一個繼承RecyclerView.Adapter<VH>的Adapter類(VH是ViewHolder的類名)

創(chuàng)建ViewHolder:在Adapter中創(chuàng)建一個繼承RecyclerView.ViewHolder的靜態(tài)內(nèi)部類,記為VH。ViewHolder的實現(xiàn)和ListView的ViewHolder實現(xiàn)幾乎一樣擦耀。

在Adapter中實現(xiàn)3個方法:

  • onCreateViewHolder()
    這個方法主要生成為每個Item inflater出一個View棉圈,但是該方法返回的是一個ViewHolder。該方法把View直接封裝在ViewHolder中眷蜓,然后我們面向的是ViewHolder這個實例分瘾,當(dāng)然這個ViewHolder需要我們自己去編寫。

需要注意的是在onCreateViewHolder()中吁系,映射Layout必須為

View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_1, parent, false);

而不能是:

View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_1, null);
  • onBindViewHolder()
    這個方法主要用于適配渲染數(shù)據(jù)到View中德召。方法提供給你了一viewHolder而不是原來的convertView。

  • getItemCount()
    這個方法就類似于BaseAdapter的getCount方法了汽纤,即總共有多少個條目上岗。

可以看出,RecyclerView將ListView中g(shù)etView()的功能拆分成了onCreateViewHolder()和onBindViewHolder()蕴坪。

基本的Adapter實現(xiàn)如下:

// ① 創(chuàng)建Adapter
public class NormalAdapter extends RecyclerView.Adapter<NormalAdapter.VH>{
    //② 創(chuàng)建ViewHolder
    public static class VH extends RecyclerView.ViewHolder{
        public final TextView title;
        public VH(View v) {
            super(v);
            title = (TextView) v.findViewById(R.id.title);
        }
    }
    
    private List<String> mDatas;
    public NormalAdapter(List<String> data) {
        this.mDatas = data;
    }

    //③ 在Adapter中實現(xiàn)3個方法
    @Override
    public void onBindViewHolder(VH holder, int position) {
        holder.title.setText(mDatas.get(position));
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //item 點擊事件
            }
        });
    }

    @Override
    public int getItemCount() {
        return mDatas.size();
    }

    @Override
    public VH onCreateViewHolder(ViewGroup parent, int viewType) {
        //LayoutInflater.from指定寫法
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_1, parent, false);
        return new VH(v);
    }
}

4. 設(shè)置RecyclerView

創(chuàng)建完Adapter肴掷,接著對RecyclerView進行設(shè)置,一般來說背传,需要為RecyclerView進行四大設(shè)置呆瞻,也就是后文說的四大組成:

  • Layout Manager(必選)
  • Adapter(必選)
  • Item Decoration(可選,默認(rèn)為空)
  • Item Animator(可選径玖,默認(rèn)為DefaultItemAnimator)

如果要實現(xiàn)ListView的效果栋烤,只需要設(shè)置Adapter和Layout Manager,如下:

List<String> data = initData();
RecyclerView rv = (RecyclerView) findViewById(R.id.rv);
//Layout Manager必選
rv.setLayoutManager(new LinearLayoutManager(this));
//Adapter 必選
rv.setAdapter(new NormalAdapter(data));

5. 四大組成

RecyclerView的四大組成是:

  • Layout Manager:Item的布局挺狰。
  • Adapter:為Item提供數(shù)據(jù)明郭。
  • Item Decoration:Item之間的Divider。
  • Item Animator:添加丰泊、刪除Item動畫薯定。

三、Layout Manager布局管理器

1. 布局管理器

在最開始就提到瞳购,RecyclerView 能夠支持各種各樣的布局效果话侄,這是 ListView 所不具有的功能,那么這個功能如何實現(xiàn)的呢学赛?其核心關(guān)鍵在于 RecyclerView.LayoutManager類中年堆。從前面的基礎(chǔ)使用可以看到,RecyclerView 在使用過程中要比 ListView 多一個 setLayoutManager 步驟盏浇,這個 LayoutManager 就是用于控制我們 RecyclerView 最終的展示效果的变丧。

LayoutManager負(fù)責(zé)RecyclerView的布局,其中包含了Item View的獲取與回收绢掰。

RecyclerView提供了三種布局管理器

  • LinerLayoutManager垂直或者水平列表方式展示Item
  • GridLayoutManager網(wǎng)格方式展示Item
  • StaggeredGridLayoutManager瀑布流方式展示Item

如果你想用 RecyclerView 來實現(xiàn)自己自定義效果痒蓬,則應(yīng)該去繼承實現(xiàn)自己的 LayoutManager童擎,并重寫相應(yīng)的方法,而不應(yīng)該想著去改寫 RecyclerView攻晒。

2. LayoutManager 常見 API

關(guān)于 LayoutManager 的使用有下面一些常見的 API(有些在 LayoutManager 實現(xiàn)的子類中)

canScrollHorizontally();//能否橫向滾動
canScrollVertically();//能否縱向滾動
scrollToPosition(int position);//滾動到指定位置

setOrientation(int orientation);//設(shè)置滾動的方向
getOrientation();//獲取滾動方向

findViewByPosition(int position);//獲取指定位置的Item View
findFirstCompletelyVisibleItemPosition();//獲取第一個完全可見的Item位置
findFirstVisibleItemPosition();//獲取第一個可見Item的位置
findLastCompletelyVisibleItemPosition();//獲取最后一個完全可見的Item位置
findLastVisibleItemPosition();//獲取最后一個可見Item的位置

3. 局部刷新閃屏問題解決

對于RecyclerView的Item Animator顾复,有一個常見的坑就是“閃屏問題”。
這個問題的描述是:當(dāng)Item視圖中有圖片和文字鲁捏,當(dāng)更新文字并調(diào)用notifyItemChanged()時芯砸,文字改變的同時圖片會閃一下。這個問題的原因是當(dāng)調(diào)用notifyItemChanged()時给梅,會調(diào)用DefaultItemAnimator的animateChangeImpl()執(zhí)行change動畫乙嘀,該動畫會使得Item的透明度從0變?yōu)?,從而造成閃屏破喻。

解決辦法很簡單:
在rv.setAdapter()之前調(diào)用((SimpleItemAnimator)rv.getItemAnimator()).setSupportsChangeAnimations(false)禁用change動畫虎谢。

4.點擊事件

RecyclerView并沒有像ListView一樣暴露出Item點擊事件或者長按事件處理的api,也就是說使用RecyclerView時候曹质,需要我們自己來實現(xiàn)Item的點擊和長按等事件的處理婴噩。
實現(xiàn)方法有很多:

  • 可以監(jiān)聽RecyclerView的Touch事件然后判斷手勢做相應(yīng)的處理,
  • 也可以通過在綁定ViewHolder的時候設(shè)置監(jiān)聽羽德,然后通過Apater回調(diào)出去

我們選擇第二種方法几莽,更加直觀和簡單。
看一下Adapter的完整代碼宅静。

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder>{
    // 展示數(shù)據(jù)
    private ArrayList<String> mData;
    // 事件回調(diào)監(jiān)聽
    private MyAdapter.OnItemClickListener onItemClickListener;
    public MyAdapter(ArrayList<String> data) {
        this.mData = data;
    }
    public void updateData(ArrayList<String> data) {
        this.mData = data;
        notifyDataSetChanged();
    }
    // 添加新的Item
    public void addNewItem() {
        if(mData == null) {
            mData = new ArrayList<>();
        }
        mData.add(0, "new Item");
        notifyItemInserted(0);
    }
    // 刪除Item
    public void deleteItem() {
        if(mData == null || mData.isEmpty()) {
            return;
        }
        mData.remove(0);
        notifyItemRemoved(0);
    }

    // ① 定義點擊回調(diào)接口
    public interface OnItemClickListener {
        void onItemClick(View view, int position);
        void onItemLongClick(View view, int position);
    }
    
    // ② 定義一個設(shè)置點擊監(jiān)聽器的方法
    public void setOnItemClickListener(MyAdapter.OnItemClickListener listener) {
        this.onItemClickListener = listener;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        // 實例化展示的view
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_rv_item, parent, false);
        // 實例化viewholder
        ViewHolder viewHolder = new ViewHolder(v);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(final ViewHolder holder, int position) {
        // 綁定數(shù)據(jù)
        holder.mTv.setText(mData.get(position));
        //③ 對RecyclerView的每一個itemView設(shè)置點擊事件
        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(final View v) {
                if(onItemClickListener != null) {
                    int pos = holder.getLayoutPosition();
                    onItemClickListener.onItemClick(holder.itemView, pos);
                }
            }
        });

        holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                if(onItemClickListener != null) {
                    int pos = holder.getLayoutPosition();
                    onItemClickListener.onItemLongClick(holder.itemView, pos);
                }
                //表示此事件已經(jīng)消費章蚣,不會觸發(fā)單擊事件
                return true;
            }
        });
    }

    @Override
    public int getItemCount() {
        return mData == null ? 0 : mData.size();
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {
        TextView mTv;
        public ViewHolder(View itemView) {
            super(itemView);
            mTv = (TextView) itemView.findViewById(R.id.item_tv);
        }
    }
}

設(shè)置Adapter的事件監(jiān)聽。

mAdapter.setOnItemClickListener(new MyAdapter.OnItemClickListener() {
    @Override
    public void onItemClick(View view, int position) {
        Toast.makeText(MDRvActivity.this,"click " + position + " item", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onItemLongClick(View view, int position) {
        Toast.makeText(MDRvActivity.this,"long click " + position + " item", Toast.LENGTH_SHORT).show();
    }
});

5.網(wǎng)格樣式

RecyclerView展示的樣式由布局管理器LayoutManager來控制姨夹。
網(wǎng)格樣式的管理器是GridLayoutManager纤垂,看一下它最常用的兩個構(gòu)造函數(shù)以及參數(shù)含義。

  • GridLayoutManager(Context context, int spanCount)

    • spanCount磷账,每列或者每行的item個數(shù)峭沦,設(shè)置為1,就是列表樣式
    • 該構(gòu)造函數(shù)默認(rèn)是豎直方向的網(wǎng)格樣式
  • GridLayoutManager(Context context, int spanCount, int orientation,boolean reverseLayout)

    • spanCount逃糟,每列或者每行的item個數(shù)吼鱼,設(shè)置為1,就是列表樣式
    • 網(wǎng)格樣式的方向绰咽,水平(OrientationHelper.HORIZONTAL)或者豎直(OrientationHelper.VERTICAL)
    • reverseLayout菇肃,是否逆向,true:布局逆向展示取募,false:布局正向顯示
// 豎直方向的網(wǎng)格樣式琐谤,每行四個Item
mLayoutManager = new GridLayoutManager(this, 4, OrientationHelper.VERTICAL, false);
mRecyclerView.setLayoutManager(mLayoutManager);

運行效果:

image.png

6.瀑布流樣式

RecyclerView的瀑布流布局管理器是StaggeredGridLayoutManager,它最常用的構(gòu)造函數(shù)就一個矛辕,StaggeredGridLayoutManager(int spanCount, int orientation)笑跛,spanCount代表每行或每列的Item個數(shù)付魔,orientation代表列表的方向聊品,豎直或者水平飞蹂。

看在代碼中的使用。

// 初始化布局管理器
mLayoutManager = new StaggeredGridLayoutManager(2, OrientationHelper.VERTICAL);
// 設(shè)置布局管理器
mRecyclerView.setLayoutManager(mLayoutManager);
// 設(shè)置adapter
mRecyclerView.setAdapter(mAdapter);
// 設(shè)置間隔樣式
mRecyclerView.addItemDecoration(new MDStaggeredRvDividerDecotation(this));

要實現(xiàn)瀑布流效果(僅討論豎直方向的瀑布流樣式)翻屈,每一個Item的高度要有所差別陈哑,如果所有的item的高度相同,就和網(wǎng)格樣式是一樣的展示效果伸眶。示例中就實現(xiàn)兩中不同高度的Item惊窖,一個高度為80dp,一個高度為100dp。

view_rv_staggered_item.xml布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="80dp">
    <TextView
        android:id="@+id/item_tv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        tools:text="item"/>
</LinearLayout>

view_rv_staggered_item_two.xml布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="100dp">
    <TextView
        android:id="@+id/item_tv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        tools:text="item"/>
</LinearLayout>

Item不同的布局是在Adapter里面綁定的厘贼,看一下Adapter的實現(xiàn)界酒。

public class MDStaggeredRvAdapter extends RecyclerView.Adapter<MDStaggeredRvAdapter.ViewHolder> {
    // 展示數(shù)據(jù)
    private ArrayList<String> mData;
    public MDStaggeredRvAdapter(ArrayList<String> data) {
        this.mData = data;
    }
    public void updateData(ArrayList<String> data) {
        this.mData = data;
        notifyDataSetChanged();
    }

    @Override
    public int getItemViewType(int position) {
        // 瀑布流樣式外部設(shè)置spanCount為2,在這列設(shè)置兩個不同的item type嘴秸,以區(qū)分不同的布局
        return position % 2;
    }

    @Override
    public MDStaggeredRvAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        // 實例化展示的view
        View v;
        if(viewType == 1) {
            v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_rv_staggered_item, parent, false);
        } else {
            v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_rv_staggered_item_two, parent, false);
        }
        // 實例化viewholder
        ViewHolder viewHolder = new ViewHolder(v);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(MDStaggeredRvAdapter.ViewHolder holder, int position) {
        // 綁定數(shù)據(jù)
        holder.mTv.setText(mData.get(position));
    }

    @Override
    public int getItemCount() {
        return mData == null ? 0 : mData.size();
    }

    public static class ViewHolder extends RecyclerView.ViewHolder {

        TextView mTv;

        public ViewHolder(View itemView) {
            super(itemView);
            mTv = (TextView) itemView.findViewById(R.id.item_tv);
        }
    }
}

四毁欣、總結(jié):

  • 水平列表展示,設(shè)置LayoutManager的方向性
  • 豎直列表展示岳掐,設(shè)置LayoutManager的方向性
  • 自定義間隔凭疮,RecyclerView.addItemDecoration()
  • Item添加和刪除動畫,RecyclerView.setItemAnimator()
  • 網(wǎng)格樣式的布局管理器GridLayoutManager的spanCount設(shè)置為1,就是列表樣式
  • 瀑布流樣式如果Item的布局文件是等高串述,豎直方向执解,就是豎直方向的網(wǎng)格樣式;如果Item是等寬纲酗,水平方向衰腌,那就是水平方向的網(wǎng)絡(luò)樣式
  • 如果瀑布流樣式的布局管理器StaggeredGridLayoutManager的spanCount設(shè)置為1,豎直方向觅赊,是豎直方向的列表桶唐;水平方向,就是水平方向的列表

RecyclerView實現(xiàn)局部刷新

RecyclerView提供了notifyItemInserted(),notifyItemRemoved(),notifyItemChanged()等API更新單個或某個范圍的Item視圖茉兰。

gitHub 地址:https://github.com/lyyRunning/RecyclerViewDemo

作者:Rtia
鏈接:http://www.reibang.com/p/4f9591291365

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末尤泽,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子规脸,更是在濱河造成了極大的恐慌坯约,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件莫鸭,死亡現(xiàn)場離奇詭異闹丐,居然都是意外死亡,警方通過查閱死者的電腦和手機被因,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進店門卿拴,熙熙樓的掌柜王于貴愁眉苦臉地迎上來衫仑,“玉大人,你說我怎么就攤上這事堕花∥挠” “怎么了?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵缘挽,是天一觀的道長瞄崇。 經(jīng)常有香客問我,道長壕曼,這世上最難降的妖魔是什么苏研? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮腮郊,結(jié)果婚禮上摹蘑,老公的妹妹穿的比我還像新娘。我一直安慰自己轧飞,他們只是感情好衅鹿,可當(dāng)我...
    茶點故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著踪少,像睡著了一般塘安。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上援奢,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天兼犯,我揣著相機與錄音,去河邊找鬼集漾。 笑死切黔,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的具篇。 我是一名探鬼主播纬霞,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼驱显!你這毒婦竟也來了诗芜?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤埃疫,失蹤者是張志新(化名)和其女友劉穎伏恐,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體栓霜,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡翠桦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了胳蛮。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片销凑。...
    茶點故事閱讀 38,643評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡丛晌,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出斗幼,到底是詐尸還是另有隱情澎蛛,我是刑警寧澤,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布孟岛,位于F島的核電站瓶竭,受9級特大地震影響督勺,放射性物質(zhì)發(fā)生泄漏渠羞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一智哀、第九天 我趴在偏房一處隱蔽的房頂上張望次询。 院中可真熱鬧,春花似錦瓷叫、人聲如沸屯吊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽盒卸。三九已至,卻和暖如春次氨,著一層夾襖步出監(jiān)牢的瞬間蔽介,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工煮寡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留虹蓄,地道東北人。 一個月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓幸撕,卻偏偏與公主長得像薇组,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子坐儿,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,509評論 2 348

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