RecyclerView 万能适配器

RecyclerVeiw 与ListView区别:


recyclerView 缓存的Holder而不是View, RecyclerView 不管布局、不管动画、不管分隔、 只管view 的复用,并支持多种刷新模式:notifyDataSetChanged(), notifyItemInserted(position), notifyItemRemoved(position)等多种刷新模式,很大程度提高效率。

LayoutManager布局管理器:


LinearLaoutManager:线形
GridLayoutManager:网格
StaggeredManager:错乱样式(瀑布流)

简单使用:


在xmlk 中的布局

<android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

RecyclerView Adapter



/**
 * 说明:基本使用
 * 波粒:1050189980 2018/6/20
 */
public class SimpleAdapter extends RecyclerView.Adapter<SimpleAdapter.MyHolder> {
    protected List<String> mData;
    private Context mContext;
    private LayoutInflater mLayoutInflater;
    OnItemClick mOnItemClick;

    public SimpleAdapter(Context contex, List<String> data) {
        mContext = contex;
        mData = data;
        mLayoutInflater = LayoutInflater.from(mContext);
    }

    /**
     * 添加数据
     */
    public void add(int position) {
        mData.add(position, "新增");
        notifyItemInserted(position);
    }

    /**
     * 删除数据
     */
    public void delete(int position) {
        mData.remove(position);
        notifyItemRemoved(position);
    }

    /**
     * 点击事件
     */
    public interface OnItemClick {
        void click(View view, int position);

        void longClick(View view, int position);
    }

    /**
     * 设置事件
     */
    public void setOnItmeClick(OnItemClick onItmeClick) {
        mOnItemClick = onItmeClick;
    }

    /**
     * 创建Holder 对象
     */
    @Override
    public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = mLayoutInflater.inflate(R.layout.itme_simple, parent, false);
        return new MyHolder(view);
    }

    /**
     * 绑定Holder 设置数据与事件
     */
    @Override
    public void onBindViewHolder(final MyHolder holder, final int position) {
        holder.textView.setText(mData.get(position));
        if (mOnItemClick != null) {
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mOnItemClick.click(holder.itemView, holder.getLayoutPosition());
                }
            });
            holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    mOnItemClick.longClick(holder.itemView, holder.getLayoutPosition());
                    return false;
                }
            });
        }
    }

    /**
     * item大小
     */
    @Override
    public int getItemCount() {
        return mData.size();
    }

    public class MyHolder extends RecyclerView.ViewHolder {
        TextView textView;

        public MyHolder(View itemView) {
            super(itemView);
            textView = itemView.findViewById(R.id.textView);
        }
    }
}

在Activity 中使用


/**
 * RecyclerView  的简单使用
 */
public class SimpleActivity extends AppCompatActivity {
    RecyclerView mRecyclerView;
    private List<String> mData;
    SimpleAdapter simpleAdapter;
    SimpleStaggeredAdapter simpleStaggeredAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_simple);
        mRecyclerView = findViewById(R.id.recyclerView);
        mData = new ArrayList<>();
        //添加数据源
        for (int i = 'A'; i <= 'z'; i++) {
            mData.add("" + (char) i);
        }

        simpleStaggeredAdapter = new SimpleStaggeredAdapter(this, mData);
        simpleAdapter = new SimpleAdapter(this, mData);
        //设置adapter
        mRecyclerView.setAdapter(simpleAdapter);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
        //设置管理器
        mRecyclerView.setLayoutManager(linearLayoutManager);
        //设置动画
        mRecyclerView.setItemAnimator(new DefaultItemAnimator());
        //设置分隔线
        DividerItemDecoration decoration1 = new DividerItemDecoration(this, DividerItemDecoration.VERTICAL);
        mRecyclerView.addItemDecoration(decoration1);
        //设置事件
        simpleAdapter.setOnItmeClick(new SimpleAdapter.OnItemClick() {
            @Override
            public void click(View view, int position) {
                Toast.makeText(SimpleActivity.this, "click" + position, Toast.LENGTH_SHORT).show();
            }

            @Override
            public void longClick(View view, int position) {
                simpleAdapter.delete(position);
                Toast.makeText(SimpleActivity.this, "longClick" + position, Toast.LENGTH_SHORT).show();
            }
        });
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        //导入菜单布局
        getMenuInflater().inflate(R.menu.menu_simple, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        //线型
        if (item.getItemId() == R.id.listView) {
            mRecyclerView.setAdapter(simpleAdapter);
            mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
            //网格
        } else if (item.getItemId() == R.id.gridView) {
            mRecyclerView.setAdapter(simpleAdapter);
            mRecyclerView.setLayoutManager(new GridLayoutManager(this, 4));
            //瀑布流
        } else if (item.getItemId() == R.id.horizontal) {
            mRecyclerView.setAdapter(simpleAdapter);
            mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(5, StaggeredGridLayoutManager.HORIZONTAL));
            //横向滑动
        } else if (item.getItemId() == R.id.staggeredView) {
            mRecyclerView.setAdapter(simpleStaggeredAdapter);
            mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(5, StaggeredGridLayoutManager.VERTICAL));
            //添加数据
        } else if (item.getItemId() == R.id.add) {
            simpleAdapter.add(1);
            //减少数据
        } else if (item.getItemId() == R.id.delete) {
            simpleAdapter.delete(1);
        }
        return super.onOptionsItemSelected(item);
    }
}

效果如下:

QQ图片20180621000226.png
QQ图片20180621000233.png

组合使用:

(支持下拉刷新与自动加载,支持多布局与多数据源)

通过一个adaper 进行实现,使用者只需传入布局id与数据源即可,使用简单方便,不用重复写adapter.

在xml 在使用

 <cashierdesk.xkeshi.com.simple.x_view.recyclerview.XRecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

自定义 Adapter


/**
 * 说明:RecyclerView 包裹Adapter
 * 杨阳:360621904 2018/5/30
 */
@SuppressWarnings({"unchecked", "unused"})
public abstract class WrapperAdapter extends RecyclerView.Adapter<WrapperViewHolder> {
    private IWrapperAdapterListener.OnItemClick mOnItemClick;
    private IWrapperAdapterListener.OnItemLongClick mOnItemLongClick;
    private Map<ItemType, List> mTypeList;
    private LayoutInflater inflater;
    private MyListenerImp myListenerImp;
    private RecyclerView.ViewHolder holder;
    private RecyclerView mRecyclerView;
    /**
     * item 的UI 存储需要跨列的类型(目前是加载类型)
     */
    private List<Integer> mItemTypeData;

    @SuppressWarnings("WeakerAccess")
    public WrapperAdapter(@NonNull Context context) {
        mTypeList = new LinkedHashMap<>();
        this.inflater = LayoutInflater.from(context);
        myListenerImp = new MyListenerImp();
        mItemTypeData = new ArrayList<>();
    }

    /**
     * 添加单布局holder
     *
     * @param LayoutId 布局Id
     * @param data     数据源
     */
    public void addHolder(int LayoutId, @NonNull List data) {
        mTypeList.put(new ItemType(LayoutId), data);
    }

    /**
     * 添加多布局holder,实体对象必须实现 {@link IWrapperAdapterMoreType}这个接口
     *
     * @param data 数据源
     */
    public void addMoreHolder(@NonNull List<IWrapperAdapterMoreType> data) {
        mTypeList.put(new ItemType(IWrapperAdapterMoreType.class.hashCode()), data);
    }

    public void addFloorLoadingHolder(int layoutId, @NonNull List<IWrapperAdapterFloorType> data,
                                      IWrapperAdapterListener.OnLoadingFloorItemShowCallback onLoadingFloorItemShowCallback) {
        mTypeList.put(new ItemTypeTwo(layoutId, onLoadingFloorItemShowCallback), data);
        mItemTypeData.add(layoutId);
    }


    /**
     * 设置item 的数据
     *
     * @param holder item 对应的Holder
     * @param object item 对应的数据对象
     */
    public abstract void setItemData(WrapperViewHolder holder, Object object);

    public void setOnItemClick(IWrapperAdapterListener.OnItemClick onItemLick) {
        mOnItemClick = onItemLick;
    }

    public void setOnItemLongClick(IWrapperAdapterListener.OnItemLongClick onItemLongClick) {
        mOnItemLongClick = onItemLongClick;
    }

    @Override
    public WrapperViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new WrapperViewHolder(inflater.inflate(viewType, parent, false), viewType);
    }

    @Override
    public void onBindViewHolder(final WrapperViewHolder holder, final int position) {
        setItemData(holder, getValue(position));
        Object object = getValue(position);
        //把holder,position,data 添加到view tag 中
        holder.itemView.setTag(R.id.tag_key_holder, holder);
        holder.itemView.setTag(R.id.tag_key_position, holder.getLayoutPosition());
        holder.itemView.setTag(R.id.tag_key_data, object);
        if (mOnItemClick != null && !(object instanceof IWrapperAdapterFloorType))
            holder.itemView.setOnClickListener(myListenerImp);
        if (mOnItemLongClick != null)
            holder.itemView.setOnLongClickListener(myListenerImp);
        if (mOnItemClick != null || mOnItemLongClick != null)
            holder.setItemBackground();
        //判断是否是加载的itemView
        if (object instanceof IWrapperAdapterFloorType) {
            ItemTypeTwo typeTwo = (ItemTypeTwo) getKey(position);
            assert typeTwo != null;
            if (typeTwo.mOnLoadingFloorItemShowCallback != null)
                typeTwo.mOnLoadingFloorItemShowCallback.floorItemShowCallback(holder.itemView, holder, holder.getLayoutPosition(), object);
        }
    }

    @Override
    public int getItemCount() {
        return getSumCount();
    }

    @Override
    public int getItemViewType(int position) {
        return getMyItemViewType(position);
    }

    @Override
    public void onViewAttachedToWindow(WrapperViewHolder holder) {
        super.onViewAttachedToWindow(holder);
        // 处理StaggeredGridLayoutManager,设置充满整行
        ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams();
        if (null != layoutParams && layoutParams instanceof StaggeredGridLayoutManager.LayoutParams) {
            if (mItemTypeData.contains(mRecyclerView.getAdapter().getItemViewType(holder.getLayoutPosition())))
                ((StaggeredGridLayoutManager.LayoutParams) layoutParams).setFullSpan(true);
        }
    }


    @Override
    public void onAttachedToRecyclerView(final RecyclerView recyclerView) {
        super.onAttachedToRecyclerView(recyclerView);
        mRecyclerView = recyclerView;
        // 处理GridLayoutManager,设置充满整行
        RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
        if (layoutManager instanceof GridLayoutManager) {
            final GridLayoutManager gridLayoutManager = (GridLayoutManager) layoutManager;
            gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
                @Override
                public int getSpanSize(int position) {
                    if (mItemTypeData.contains(mRecyclerView.getAdapter().getItemViewType(position))) {
                        return gridLayoutManager.getSpanCount();
                    }
                    return 1;
                }
            });
        }
    }

    /**
     * 事件回调的处理
     */
    class MyListenerImp implements View.OnClickListener, View.OnLongClickListener {
        @Override
        public void onClick(View view) {
            mOnItemClick.click(view, (WrapperViewHolder) view.getTag(R.id.tag_key_holder), (int) view.getTag(R.id.tag_key_position), view.getTag(R.id.tag_key_data));
        }

        @Override
        public boolean onLongClick(View view) {
            mOnItemLongClick.longClick(view, (WrapperViewHolder) view.getTag(R.id.tag_key_holder), (int) view.getTag(R.id.tag_key_position), view.getTag(R.id.tag_key_data));
            return false;
        }
    }

    /**
     * 总条目数
     */
    private int getSumCount() {
        int sumCount = 0;
        for (Map.Entry entry : mTypeList.entrySet()) {
            if (entry.getValue() != null)
                sumCount += ((List) entry.getValue()).size();
        }
        return sumCount;
    }

    /**
     * 条目UI 类型
     */
    private int getMyItemViewType(int position) {
        int count = 0;
        for (Map.Entry entry : mTypeList.entrySet()) {
            List list = (List) entry.getValue();
            //多布局
            if (list.get(0) instanceof IWrapperAdapterMoreType && ((count + list.size()) > position)) {
                int moreCount = count;
                for (int i = 0; i < list.size(); i++) {
                    if (moreCount == position) {
                        return ((IWrapperAdapterMoreType) list.get(i)).getItemViewId();
                    }
                    moreCount++;
                }
            }
            //统一布局
            count += ((List) entry.getValue()).size();
            if (count > position) {
                return ((ItemType) entry.getKey()).layoutId;
            }
        }
        return -1;
    }

    private ItemType getKey(int position) {
        int sumCount = 0;
        for (Map.Entry entry : mTypeList.entrySet()) {
            sumCount += ((List) entry.getValue()).size();
            if (sumCount > position) {
                return (ItemType) entry.getKey();
            }
        }
        return null;
    }

    /**
     * 获取数据对象
     */
    private Object getValue(int position) {
        int sumCount = 0;
        for (Map.Entry entry : mTypeList.entrySet()) {
            for (int i = 0; i < ((List) entry.getValue()).size(); i++) {
                if (sumCount == position) {
                    return ((List) entry.getValue()).get(i);
                }
                sumCount++;
            }
        }
        return null;
    }

    /**
     * 布局的类型
     */
    class ItemType {
        //布局的id
        int layoutId;

        ItemType(int layoutId) {
            this.layoutId = layoutId;
        }
    }

    class ItemTypeTwo extends ItemType {
        IWrapperAdapterListener.OnLoadingFloorItemShowCallback mOnLoadingFloorItemShowCallback;

        ItemTypeTwo(int layoutId, IWrapperAdapterListener.OnLoadingFloorItemShowCallback callback) {
            super(layoutId);
            this.mOnLoadingFloorItemShowCallback = callback;
        }
    }

}

Activity 中使用


/**
 * RecyclerView  组合的封闭使用
 */
public class TestXRecyclerViewActivity2 extends AppCompatActivity {
    XRecyclerView mRecyclerView;
    private List<String> mData;
    private List<String> mData1;
    private List<IWrapperAdapterMoreType> mData2;
    WrapperAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test_xrecyclerview);
        mRecyclerView = findViewById(R.id.recyclerView);
        mData = new ArrayList<>();
        mData1 = new ArrayList<>();
        mData2 = new ArrayList<>();

        addData();
        adapter = new WrapperAdapter(TestXRecyclerViewActivity2.this) {
            @Override
            public void setItemData(WrapperViewHolder holder, Object object) {
                setHolderData(holder, object);
            }
        };

        //设置数据,与布局id
        adapter.addHolder(R.layout.item_more_one, mData);
        adapter.addHolder(R.layout.item_more_two, mData);
        adapter.addHolder(R.layout.item_more_three, mData);
        adapter.addHolder(R.layout.item_more_one, mData1);
        adapter.addMoreHolder(mData2);

        //设置布局,动画、adapter
//        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
        GridLayoutManager linearLayoutManager = new GridLayoutManager(this, 2, StaggeredGridLayoutManager.VERTICAL, false);
//        StaggeredGridLayoutManager linearLayoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
        mRecyclerView.setLayoutManager(linearLayoutManager);
        mRecyclerView.setItemAnimator(new DefaultItemAnimator());
        mRecyclerView.setAdapter(adapter);

        //添加线
        VerticalDividerItemDecoration decoration = new VerticalDividerItemDecoration.Builder(this)
                .colorResId(R.color.colorGreen)
                .sizeResId(R.dimen.db_size)
                .build();
        mRecyclerView.addItemDecoration(decoration);
        //添加线
        HorizontalDividerItemDecoration decorationH = new HorizontalDividerItemDecoration.Builder(this)
                .colorResId(R.color.colorGreen)
                .sizeResId(R.dimen.db_size)
                .showLastDivider()
                .build();
        mRecyclerView.addItemDecoration(decorationH);
        //设置事件与回调
        setListener();

    }

    int count;

    /**
     * 设置事件与回调
     */
    private void setListener() {
        /**
         * 设置点击事件
         */
        adapter.setOnItemClick(new IWrapperAdapterListener.OnItemClick() {
            @Override
            public void click(View view, WrapperViewHolder holder, int position, Object data) {
                if (data instanceof String) {
                    String str = (String) data;
                    Toast.makeText(TestXRecyclerViewActivity2.this, "position:" + str + "--" + position, Toast.LENGTH_SHORT).show();
                }

                if (data instanceof MyWrapperAdapterMoreType) {
                    MyWrapperAdapterMoreType data1 = (MyWrapperAdapterMoreType) data;
                    Toast.makeText(TestXRecyclerViewActivity2.this, "position:" + data1.str + "--" + position, Toast.LENGTH_SHORT).show();
                }
            }
        });
        /**
         * 刷新的回调
         */
        mRecyclerView.setRefreshListener(new IXRecyclerViewBiz.RefreshListener() {
            @Override
            public void onRefreshListener() {
                mData.clear();
                mData.add("new");
                mData2.add(new MyWrapperAdapterMoreType(2, "新22"));
                adapter.notifyDataSetChanged();

                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        mRecyclerView.stopRefreshing();
                        count = 0;
//                        mRecyclerView.finishLoading();
                    }
                }, 1000);
            }
        });
        /**
         * 加载更多回调
         */
        mRecyclerView.setLoadingListener(new IXRecyclerViewBiz.LoadingListener() {
            @Override
            public void onLoadingListener() {
                Log.e("BBB", "加载的回调");
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        mData2.add(new MyWrapperAdapterMoreType(1, "加载新" + count));
                        mData2.add(new MyWrapperAdapterMoreType(1, "加载新" + count));
                        mData2.add(new MyWrapperAdapterMoreType(2, "加载新" + count));
                        mData2.add(new MyWrapperAdapterMoreType(1, "加载新" + count));
                        mData2.add(new MyWrapperAdapterMoreType(3, "加载新" + count));
                        mData2.add(new MyWrapperAdapterMoreType(1, "加载新" + count));
                        adapter.notifyDataSetChanged();
                        mRecyclerView.stopRefreshing();
                        count++;
                        if (count == 4) {
                            mRecyclerView.finishLoading();

                        }
                    }
                }, 1000);
            }
        });

    }

    /**
     * 设置UI 数据
     */
    private void setHolderData(WrapperViewHolder holder, Object object) {
        if (object instanceof String && R.layout.item_more_one == holder.getLayoutId()) {
            String str = (String) object;
            holder.setText(R.id.textView, str);

        } else if (object instanceof MyWrapperAdapterMoreType) {
            MyWrapperAdapterMoreType data = (MyWrapperAdapterMoreType) object;
            if (R.layout.item_more_one == holder.getLayoutId()) {
                holder.setText(R.id.textView, data.str + "");
            } else if (R.layout.item_more_two == holder.getLayoutId()) {
                holder.setText(R.id.textView1, data.str + "");
                holder.setText(R.id.textView2, data.str + "");
            } else if (R.layout.item_more_three == holder.getLayoutId()) {
                holder.setText(R.id.three_1, data.str + "");
                holder.setText(R.id.three_2, data.str + "");
                holder.setText(R.id.three_3, data.str + "");
            }
        } else if (object instanceof String && R.layout.item_more_two == holder.getLayoutId()) {
            String str = (String) object;
            holder.setText(R.id.textView1, str);
            holder.setText(R.id.textView2, str);

        } else if (object instanceof String && R.layout.item_more_three == holder.getLayoutId()) {
            String str = (String) object;
            holder.setText(R.id.three_1, str);
            holder.setText(R.id.three_2, str);
            holder.setText(R.id.three_3, str);
        }

    }

    /**
     * 添加数据
     */
    private void addData() {
        for (int i = 'A'; i <= 'C'; i++) {
            mData.add("" + (char) i);
        }
        mData1.add("1111111");
        mData1.add("1111111");
        mData1.add("1111111");
        mData1.add("1111111");
        mData1.add("1111111");

        mData2.add(new MyWrapperAdapterMoreType(3, "我是3"));
        mData2.add(new MyWrapperAdapterMoreType(2, "我是2"));
        mData2.add(new MyWrapperAdapterMoreType(2, "我是2"));
        mData2.add(new MyWrapperAdapterMoreType(2, "我是2"));
        mData2.add(new MyWrapperAdapterMoreType(2, "我是2"));
        mData2.add(new MyWrapperAdapterMoreType(2, "我是2"));
        mData2.add(new MyWrapperAdapterMoreType(1, "我是1"));
    }

    class MyWrapperAdapterMoreType implements IWrapperAdapterMoreType {
        int type;
        String str;

        MyWrapperAdapterMoreType(int type, String str) {
            this.type = type;
            this.str = str;
        }

        @Override
        public int getItemViewType() {
            return type;
        }

        @Override
        public int getItemViewId() {
            if (type == 1) {
                return R.layout.item_more_one;
            } else if (type == 2) {
                return R.layout.item_more_two;
            } else {
                return R.layout.item_more_three;
            }
        }
    }

}

效果展示

QQ图片20180621004110.png
QQ图片20180621004115.png

源码中有例子请运行查看:

  • 有带刷新与加载的自定义RecyclerView
  • 有支持DataBinding 适配器
  • 有分隔线
    源码地址下载

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,392评论 5 470
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,258评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,417评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,992评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,930评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,199评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,652评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,327评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,463评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,382评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,432评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,118评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,704评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,787评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,999评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,476评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,057评论 2 341

推荐阅读更多精彩内容