recyclerview实现加载更多

这里并没有重写recyclerview,只是对adapter进行了封装。
封装的adapter

/**
 *
 * @fuction recycleview 加载更多用的adpter
 * @date 2018/9/15
 * @author zhou
 */
abstract class RVLoadMoreAdapter<T>(
    protected var mContext: Context,
    private val recyclerView: RecyclerView,
    private val res_item_id: Int,
    var dataSet: MutableList<T>
) : RecyclerView.Adapter<RViewHolder>() {

    val TAG = RVLoadMoreAdapter::class.java.simpleName
    var isLoading = false
    private var canLoadMore = false
    private var loadMoreComplete = true
    private var loadingMore: OnLoadingMore? = null

    protected var mOnItemClickListener: OnItemClickListener? = null
    private var lastPositions: IntArray? = null
    private var footViewholder: RViewHolder? = null
    private var headerView: View? = null

    fun findMax(lastPositions: IntArray): Int {
        var max = lastPositions[0]
        for (value in lastPositions) {
            if (value > max) {
                max = value
            }
        }
        return max
    }

    fun loadMore() {
        loadingMore?.also {
            loadMoreComplete = true
            Loading(true)
            it.onLoadMore()
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RViewHolder {
        val holder: RViewHolder
        if (viewType == TYPE_HEAD) {
            holder = RViewHolder.createViewHolder(mContext, headerView!!)
        } else if (viewType == TYPE_LOAD_MORE) {
            if (footViewholder == null) {
                footViewholder = RViewHolder.createViewHolder(mContext, parent, R.layout.loadmore_default_footer)
            }
            holder = footViewholder!!
            showNormal()
        } else {
            holder = RViewHolder.createViewHolder(mContext, parent, res_item_id)
        }
        onViewHolderCreated(holder, holder.convertView, viewType)
        setListener(parent, holder, viewType)
        return holder
    }

    open fun onViewHolderCreated(
        holder: RViewHolder,
        itemView: View,
        viewType: Int
    ) {
    }

    override fun onBindViewHolder(holder: RViewHolder, position: Int) {
        if (getItemViewType(position) == TYPE_LOAD_MORE) {
            return
        }
        if (getItemViewType(position) == TYPE_HEAD) {
            return
        }
        val p = if (headerView != null) position - 1 else position
        val t = dataSet[p]
        convert(holder, t, p)
    }

    protected abstract fun convert(holder: RViewHolder, t: T, position: Int)
    override fun getItemCount(): Int {
        var size = dataSet.size
        if (headerView != null) {
            size++
        }
        if (canLoadMore) {
            size++
        }
        return size
    }

    override fun getItemViewType(position: Int): Int {
        if (position == 0) {
            if (headerView != null) {
                return TYPE_HEAD
            }
        }
        if (canLoadMore) {
            if (position == itemCount - 1) {
                return TYPE_LOAD_MORE
            }
        }
        return TYPE_NORMAL
    }

    fun setLoadingMore(loadingMore: OnLoadingMore?) {
        this.loadingMore = loadingMore
    }

    fun Loading(loading: Boolean) {
        isLoading = loading
        showNormal()
    }

    fun setLoadMoreComplete(complete: Boolean) {
        canLoadMore = loadingMore != null
        loadMoreComplete = complete
    }

    private var custom_layout_empty: LinearLayout? = null
    fun showNormal() {
        canLoadMore = loadingMore != null
        if (!canLoadMore) {
            return
        }
        if (footViewholder == null) {
            return
        }
        if (loadMoreComplete) {
            footViewholder!!.setVisible(R.id.layout_empty_default, true)
            val loadmore_default_footer_tv = footViewholder!!.getView<TextView>(R.id.loadmore_default_footer_tv)
            if (isLoading) {
                loadmore_default_footer_tv.text = "加载中"
                loadmore_default_footer_tv.setOnClickListener(null)
                footViewholder!!.setVisible(R.id.loadmore_default_footer_progressbar, true)
            } else {
                loadmore_default_footer_tv.text = "点击加载更多"
                loadmore_default_footer_tv.setOnClickListener { loadMore() }
                footViewholder!!.setVisible(R.id.loadmore_default_footer_progressbar, false)
            }
            custom_layout_empty?.visibility = View.GONE
        } else {
            if (dataSet.size > 0) {
                footViewholder!!.setVisible(R.id.layout_empty_default, true)
                footViewholder!!.setText(R.id.loadmore_default_footer_tv, "无更多数据")
                footViewholder!!.setVisible(R.id.loadmore_default_footer_progressbar, false)
                custom_layout_empty?.visibility = View.GONE
            } else {
                footViewholder!!.setVisible(R.id.layout_empty_default, false)
                if (custom_layout_empty == null) {
                    var stub_import = footViewholder!!.itemView.findViewById<ViewStub>(R.id.stub_import)
                    if (stub_import != null) {
                        stub_import.inflate()
                        stub_import = null
                    }
                    custom_layout_empty = footViewholder!!.getView(R.id.custom_layout_empty)
                    if (!TextUtils.isEmpty(emptyText)) {
                        val tv_empty = custom_layout_empty!!.findViewById<TextView>(R.id.tv_empty)
                        tv_empty.text = emptyText
                    }
                    val iv_empty = custom_layout_empty!!.findViewById<ImageView>(R.id.iv_empty)
                    iv_empty.setImageResource(emptyRes)
                }
                custom_layout_empty!!.visibility = View.VISIBLE
            }
        }
    }

    fun addData(t: T) {
        dataSet!!.add(t)
        notifyDataSetChanged()
    }

    interface OnLoadingMore {
        fun onLoadMore()
    }

    protected fun setListener(
        parent: ViewGroup?,
        viewHolder: RViewHolder,
        viewType: Int
    ) {
        viewHolder.convertView.setOnClickListener(View.OnClickListener { v ->
            mOnItemClickListener?.also {
                val position = viewHolder.adapterPosition
                if (TYPE_HEAD == getItemViewType(position)) {
                    return@OnClickListener
                }
                if (TYPE_LOAD_MORE == getItemViewType(position)) {
                    return@OnClickListener
                }
                val p = if (headerView != null) position - 1 else position
                it.onItemClick(v, viewHolder, p)
            }
        })
        viewHolder.convertView.setOnLongClickListener(OnLongClickListener { v ->
            mOnItemClickListener?.also {
                val position = viewHolder.adapterPosition
                if (TYPE_HEAD == getItemViewType(position)) {
                    return@OnLongClickListener false
                }
                if (TYPE_LOAD_MORE == getItemViewType(position)) {
                    return@OnLongClickListener false
                }
                val p = if (headerView != null) position - 1 else position
                return@OnLongClickListener it.onItemLongClick(v, viewHolder, p)
            }
            false
        })
    }

    interface OnItemClickListener {
        fun onItemClick(
            view: View,
            holder: ViewHolder,
            position: Int
        )

        fun onItemLongClick(
            view: View,
            holder: ViewHolder,
            position: Int
        ): Boolean
    }

    fun setOnItemClickListener(onItemClickListener: OnItemClickListener?) {
        mOnItemClickListener = onItemClickListener
    }

    fun addHeaderView(view: View?) {
        headerView = view
    }

    fun setCanLoadMore(canLoadMore: Boolean) {
        this.canLoadMore = canLoadMore
    }

    private var emptyText: String? = null
    private var emptyRes = R.drawable.icon_empty_default
    fun setEmptyContent(txt: String?, res: Int) {
        emptyText = txt
        emptyRes = res
    }

    fun setEmptyRes(emptyRes: Int) {
        this.emptyRes = emptyRes
    }

    fun setEmptyText(emptyText: String?) {
        this.emptyText = emptyText
    }

    companion object {
        const val TYPE_NORMAL = 100
        const val TYPE_HEAD = 101
        const val TYPE_LOAD_MORE = 102
    }

    init {
        //监听recylerview的滑动
        recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                super.onScrolled(recyclerView, dx, dy)
                if (dy <= 0) {
                    return
                }
                if (loadMoreComplete && canLoadMore && !isLoading) {
                    var lastVisibleItem = 0
                    val layoutManager = recyclerView.layoutManager
                    if (layoutManager is LinearLayoutManager) {
                        lastVisibleItem = layoutManager.findLastVisibleItemPosition()
                    } else if (layoutManager is GridLayoutManager) {
                        lastVisibleItem = layoutManager.findLastVisibleItemPosition()
                    } else if (layoutManager is StaggeredGridLayoutManager) {
                        if (lastPositions == null) {
                            lastPositions = IntArray(layoutManager.spanCount)
                        }
                        layoutManager.findLastVisibleItemPositions(lastPositions)
                        lastVisibleItem = findMax(lastPositions!!)
                    } else {
                        throw RuntimeException(
                            "Unsupported LayoutManager used. Valid ones are LinearLayoutManager, GridLayoutManager and StaggeredGridLayoutManager"
                        )
                    }
                    if (lastVisibleItem + 1 == itemCount) {
                        loadMore()
                    }
                }
            }
        })
    }
}

该adapter分别可以适配线性列表,grid列表,瀑布流列表三种布局的加载更多。
使用方法:线性列表

 val layoutManager = LinearLayoutManager(this); //线性布局
        recyclerview.layoutManager = layoutManager
        homeAdapter = object: RVLoadMoreAdapter<String>(this@AdapterMoreLoad1Activity,recyclerview,R.layout.item_rv_txt, mDatas){
            override fun convert(holder: RViewHolder, t: String, position: Int) {
                holder.setText(R.id.txt,mDatas[position])
            }

        }

        recyclerview.adapter = homeAdapter

        homeAdapter!!.setOnItemClickListener(object: RVLoadMoreAdapter.OnItemClickListener{
            override fun onItemClick(view: View, holder: RecyclerView.ViewHolder, position: Int) {
                
            }

            override fun onItemLongClick(
                view: View,
                holder: RecyclerView.ViewHolder,
                position: Int
            ): Boolean {
                return false
            }

        })
 homeAdapter!!.setLoadingMore(object: RVLoadMoreAdapter.OnLoadingMore{
            override fun onLoadMore() {
                downJson(mCurrentPage+1)
            }

        })

在downjson是可以是接口获取数据,获取完数据需要做一些操作,如下

 private fun downJson(page: Int) {

        Handler().postDelayed(Runnable {
            swipe_layout.isRefreshing = false
            if(page == 1){
                mDatas.clear()
                homeAdapter!!.setLoadMoreComplete(true)
            }
            mCurrentPage = page
            val datalist = ArrayList<String>()

            if(page == 3){ //模拟滑动到最底部
                for (i in 1..7){
                    datalist.add("RecyclerView使用$i")
                }
            }else{
                for (i in 1..20){
                    datalist.add("RecyclerView使用$i")
                }
            }
            mDatas.addAll(datalist)
            if (datalist.size < 20) {
                homeAdapter!!.setLoadMoreComplete(false)
            }

            homeAdapter!!.notifyDataSetChanged()
            homeAdapter!!.Loading(false)
        },1000)

    }

具体操作大家可以自己分析,还是很容易理解。

这里特别注意:用grid列表的时候需要加入

layoutManager.spanSizeLookup = object: GridLayoutManager.SpanSizeLookup() {
            override fun getSpanSize(position: Int): Int {
                return if (homeAdapter!!.getItemViewType(position) == RVLoadMoreAdapter.TYPE_LOAD_MORE) {
                    2
                } else {
                    1
                }
            }

        }

这样加载更多的底部布局才能跨列显示。上面的2是因为我用的是2列的grid,如果是3列就是3,以此类推。

瀑布流的时候,需要重写onViewHolderCreated的方法,解决加载更多的跨列问题,如下

homeAdapter = object: RVLoadMoreAdapter<String>(this@AdapterMoreLoad3Activity,recyclerview,R.layout.item_rv_txt, mDatas){

            override fun onViewHolderCreated(holder: RViewHolder, itemView: View, viewType: Int) {
                super.onViewHolderCreated(holder, itemView, viewType)
                if (viewType === TYPE_LOAD_MORE) {
                    val lp = holder.itemView.layoutParams
                    if (lp != null && lp is StaggeredGridLayoutManager.LayoutParams) {
                        lp.isFullSpan = true
                    }
                }
            }

            override fun convert(holder: RViewHolder, t: String, position: Int) {
                holder.setText(R.id.txt,mDatas[position])
            }

        }

这里并没有重写recyclerview,只是对adapter进行了封装。
封装的adapter

/**
 *
 * @fuction recycleview 加载更多用的adpter
 * @date 2018/9/15
 * @author zhou
 */
abstract class RVLoadMoreAdapter<T>(
    protected var mContext: Context,
    private val recyclerView: RecyclerView,
    private val res_item_id: Int,
    var dataSet: MutableList<T>
) : RecyclerView.Adapter<RViewHolder>() {

    val TAG = RVLoadMoreAdapter::class.java.simpleName
    var isLoading = false
    private var canLoadMore = false
    private var loadMoreComplete = true
    private var loadingMore: OnLoadingMore? = null

    protected var mOnItemClickListener: OnItemClickListener? = null
    private var lastPositions: IntArray? = null
    private var footViewholder: RViewHolder? = null
    private var headerView: View? = null

    fun findMax(lastPositions: IntArray): Int {
        var max = lastPositions[0]
        for (value in lastPositions) {
            if (value > max) {
                max = value
            }
        }
        return max
    }

    fun loadMore() {
        loadingMore?.also {
            loadMoreComplete = true
            Loading(true)
            it.onLoadMore()
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RViewHolder {
        val holder: RViewHolder
        if (viewType == TYPE_HEAD) {
            holder = RViewHolder.createViewHolder(mContext, headerView!!)
        } else if (viewType == TYPE_LOAD_MORE) {
            if (footViewholder == null) {
                footViewholder = RViewHolder.createViewHolder(mContext, parent, R.layout.loadmore_default_footer)
            }
            holder = footViewholder!!
            showNormal()
        } else {
            holder = RViewHolder.createViewHolder(mContext, parent, res_item_id)
        }
        onViewHolderCreated(holder, holder.convertView, viewType)
        setListener(parent, holder, viewType)
        return holder
    }

    open fun onViewHolderCreated(
        holder: RViewHolder,
        itemView: View,
        viewType: Int
    ) {
    }

    override fun onBindViewHolder(holder: RViewHolder, position: Int) {
        if (getItemViewType(position) == TYPE_LOAD_MORE) {
            return
        }
        if (getItemViewType(position) == TYPE_HEAD) {
            return
        }
        val p = if (headerView != null) position - 1 else position
        val t = dataSet[p]
        convert(holder, t, p)
    }

    protected abstract fun convert(holder: RViewHolder, t: T, position: Int)
    override fun getItemCount(): Int {
        var size = dataSet.size
        if (headerView != null) {
            size++
        }
        if (canLoadMore) {
            size++
        }
        return size
    }

    override fun getItemViewType(position: Int): Int {
        if (position == 0) {
            if (headerView != null) {
                return TYPE_HEAD
            }
        }
        if (canLoadMore) {
            if (position == itemCount - 1) {
                return TYPE_LOAD_MORE
            }
        }
        return TYPE_NORMAL
    }

    fun setLoadingMore(loadingMore: OnLoadingMore?) {
        this.loadingMore = loadingMore
    }

    fun Loading(loading: Boolean) {
        isLoading = loading
        showNormal()
    }

    fun setLoadMoreComplete(complete: Boolean) {
        canLoadMore = loadingMore != null
        loadMoreComplete = complete
    }

    private var custom_layout_empty: LinearLayout? = null
    fun showNormal() {
        canLoadMore = loadingMore != null
        if (!canLoadMore) {
            return
        }
        if (footViewholder == null) {
            return
        }
        if (loadMoreComplete) {
            footViewholder!!.setVisible(R.id.layout_empty_default, true)
            val loadmore_default_footer_tv = footViewholder!!.getView<TextView>(R.id.loadmore_default_footer_tv)
            if (isLoading) {
                loadmore_default_footer_tv.text = "加载中"
                loadmore_default_footer_tv.setOnClickListener(null)
                footViewholder!!.setVisible(R.id.loadmore_default_footer_progressbar, true)
            } else {
                loadmore_default_footer_tv.text = "点击加载更多"
                loadmore_default_footer_tv.setOnClickListener { loadMore() }
                footViewholder!!.setVisible(R.id.loadmore_default_footer_progressbar, false)
            }
            custom_layout_empty?.visibility = View.GONE
        } else {
            if (dataSet.size > 0) {
                footViewholder!!.setVisible(R.id.layout_empty_default, true)
                footViewholder!!.setText(R.id.loadmore_default_footer_tv, "无更多数据")
                footViewholder!!.setVisible(R.id.loadmore_default_footer_progressbar, false)
                custom_layout_empty?.visibility = View.GONE
            } else {
                footViewholder!!.setVisible(R.id.layout_empty_default, false)
                if (custom_layout_empty == null) {
                    var stub_import = footViewholder!!.itemView.findViewById<ViewStub>(R.id.stub_import)
                    if (stub_import != null) {
                        stub_import.inflate()
                        stub_import = null
                    }
                    custom_layout_empty = footViewholder!!.getView(R.id.custom_layout_empty)
                    if (!TextUtils.isEmpty(emptyText)) {
                        val tv_empty = custom_layout_empty!!.findViewById<TextView>(R.id.tv_empty)
                        tv_empty.text = emptyText
                    }
                    val iv_empty = custom_layout_empty!!.findViewById<ImageView>(R.id.iv_empty)
                    iv_empty.setImageResource(emptyRes)
                }
                custom_layout_empty!!.visibility = View.VISIBLE
            }
        }
    }

    fun addData(t: T) {
        dataSet!!.add(t)
        notifyDataSetChanged()
    }

    interface OnLoadingMore {
        fun onLoadMore()
    }

    protected fun setListener(
        parent: ViewGroup?,
        viewHolder: RViewHolder,
        viewType: Int
    ) {
        viewHolder.convertView.setOnClickListener(View.OnClickListener { v ->
            mOnItemClickListener?.also {
                val position = viewHolder.adapterPosition
                if (TYPE_HEAD == getItemViewType(position)) {
                    return@OnClickListener
                }
                if (TYPE_LOAD_MORE == getItemViewType(position)) {
                    return@OnClickListener
                }
                val p = if (headerView != null) position - 1 else position
                it.onItemClick(v, viewHolder, p)
            }
        })
        viewHolder.convertView.setOnLongClickListener(OnLongClickListener { v ->
            mOnItemClickListener?.also {
                val position = viewHolder.adapterPosition
                if (TYPE_HEAD == getItemViewType(position)) {
                    return@OnLongClickListener false
                }
                if (TYPE_LOAD_MORE == getItemViewType(position)) {
                    return@OnLongClickListener false
                }
                val p = if (headerView != null) position - 1 else position
                return@OnLongClickListener it.onItemLongClick(v, viewHolder, p)
            }
            false
        })
    }

    interface OnItemClickListener {
        fun onItemClick(
            view: View,
            holder: ViewHolder,
            position: Int
        )

        fun onItemLongClick(
            view: View,
            holder: ViewHolder,
            position: Int
        ): Boolean
    }

    fun setOnItemClickListener(onItemClickListener: OnItemClickListener?) {
        mOnItemClickListener = onItemClickListener
    }

    fun addHeaderView(view: View?) {
        headerView = view
    }

    fun setCanLoadMore(canLoadMore: Boolean) {
        this.canLoadMore = canLoadMore
    }

    private var emptyText: String? = null
    private var emptyRes = R.drawable.icon_empty_default
    fun setEmptyContent(txt: String?, res: Int) {
        emptyText = txt
        emptyRes = res
    }

    fun setEmptyRes(emptyRes: Int) {
        this.emptyRes = emptyRes
    }

    fun setEmptyText(emptyText: String?) {
        this.emptyText = emptyText
    }

    companion object {
        const val TYPE_NORMAL = 100
        const val TYPE_HEAD = 101
        const val TYPE_LOAD_MORE = 102
    }

    init {
        //监听recylerview的滑动
        recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
                super.onScrolled(recyclerView, dx, dy)
                if (dy <= 0) {
                    return
                }
                if (loadMoreComplete && canLoadMore && !isLoading) {
                    var lastVisibleItem = 0
                    val layoutManager = recyclerView.layoutManager
                    if (layoutManager is LinearLayoutManager) {
                        lastVisibleItem = layoutManager.findLastVisibleItemPosition()
                    } else if (layoutManager is GridLayoutManager) {
                        lastVisibleItem = layoutManager.findLastVisibleItemPosition()
                    } else if (layoutManager is StaggeredGridLayoutManager) {
                        if (lastPositions == null) {
                            lastPositions = IntArray(layoutManager.spanCount)
                        }
                        layoutManager.findLastVisibleItemPositions(lastPositions)
                        lastVisibleItem = findMax(lastPositions!!)
                    } else {
                        throw RuntimeException(
                            "Unsupported LayoutManager used. Valid ones are LinearLayoutManager, GridLayoutManager and StaggeredGridLayoutManager"
                        )
                    }
                    if (lastVisibleItem + 1 == itemCount) {
                        loadMore()
                    }
                }
            }
        })
    }
}

该adapter分别可以适配线性列表,grid列表,瀑布流列表三种布局的加载更多。
使用方法:线性列表

 val layoutManager = LinearLayoutManager(this); //线性布局
        recyclerview.layoutManager = layoutManager
        homeAdapter = object: RVLoadMoreAdapter<String>(this@AdapterMoreLoad1Activity,recyclerview,R.layout.item_rv_txt, mDatas){
            override fun convert(holder: RViewHolder, t: String, position: Int) {
                holder.setText(R.id.txt,mDatas[position])
            }

        }

        recyclerview.adapter = homeAdapter

        homeAdapter!!.setOnItemClickListener(object: RVLoadMoreAdapter.OnItemClickListener{
            override fun onItemClick(view: View, holder: RecyclerView.ViewHolder, position: Int) {
                
            }

            override fun onItemLongClick(
                view: View,
                holder: RecyclerView.ViewHolder,
                position: Int
            ): Boolean {
                return false
            }

        })
 homeAdapter!!.setLoadingMore(object: RVLoadMoreAdapter.OnLoadingMore{
            override fun onLoadMore() {
                downJson(mCurrentPage+1)
            }

        })

在downjson是可以是接口获取数据,获取完数据需要做一些操作,如下

 private fun downJson(page: Int) {

        Handler().postDelayed(Runnable {
            swipe_layout.isRefreshing = false
            if(page == 1){
                mDatas.clear()
                homeAdapter!!.setLoadMoreComplete(true)
            }
            mCurrentPage = page
            val datalist = ArrayList<String>()

            if(page == 3){ //模拟滑动到最底部
                for (i in 1..7){
                    datalist.add("RecyclerView使用$i")
                }
            }else{
                for (i in 1..20){
                    datalist.add("RecyclerView使用$i")
                }
            }
            mDatas.addAll(datalist)
            if (datalist.size < 20) {
                homeAdapter!!.setLoadMoreComplete(false)
            }

            homeAdapter!!.notifyDataSetChanged()
            homeAdapter!!.Loading(false)
        },1000)

    }

具体操作大家可以自己分析,还是很容易理解。

这里特别注意:用grid列表的时候需要加入

layoutManager.spanSizeLookup = object: GridLayoutManager.SpanSizeLookup() {
            override fun getSpanSize(position: Int): Int {
                return if (homeAdapter!!.getItemViewType(position) == RVLoadMoreAdapter.TYPE_LOAD_MORE) {
                    2
                } else {
                    1
                }
            }

        }

这样加载更多的底部布局才能跨列显示。上面的2是因为我用的是2列的grid,如果是3列就是3,以此类推。

瀑布流的时候,需要重写onViewHolderCreated的方法,解决加载更多的跨列问题,如下

homeAdapter = object: RVLoadMoreAdapter<String>(this@AdapterMoreLoad3Activity,recyclerview,R.layout.item_rv_txt, mDatas){

            override fun onViewHolderCreated(holder: RViewHolder, itemView: View, viewType: Int) {
                super.onViewHolderCreated(holder, itemView, viewType)
                if (viewType === TYPE_LOAD_MORE) {
                    val lp = holder.itemView.layoutParams
                    if (lp != null && lp is StaggeredGridLayoutManager.LayoutParams) {
                        lp.isFullSpan = true
                    }
                }
            }

            override fun convert(holder: RViewHolder, t: String, position: Int) {
                holder.setText(R.id.txt,mDatas[position])
            }

        }

github地址:https://gitee.com/stonezry/AndroidDemo

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