You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何打乱Firebase获取的有序数据并实现随机展示?

Firebase视频数据随机展示实现问题

从Firebase中按顺序获取视频数据,希望随机展示这些数据,但打乱Firebase返回数据时遇到了问题。以下是相关代码:

现有代码

Main Activity

class MainActivity : AppCompatActivity() {

    lateinit var viewPager2:ViewPager2
    lateinit var adapter:VideoAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        /**set fullscreen*/
        window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN)

        /**set find id*/
        viewPager2 = findViewById(R.id.vpager)

        /**set database*/
        val mDataBase = Firebase.database.getReference("videos")

        val options = FirebaseRecyclerOptions.Builder<VideoModel>()
            .setQuery(mDataBase,VideoModel::class.java)
            .build()


        /**set adapter*/
        adapter = VideoAdapter(options)
        viewPager2.adapter = adapter

    }

    override fun onStart() {
        super.onStart()
        adapter.startListening()
    }

    override fun onStop() {
        super.onStop()
        adapter.stopListening()
    }
}

VideoAdapter

class VideoAdapter(options: FirebaseRecyclerOptions<VideoModel?>) :
    FirebaseRecyclerAdapter<VideoModel?, VideoAdapter.MyViewHolder?>(options) {

    override fun onBindViewHolder(holder: MyViewHolder, position: Int, model: VideoModel) {
        holder.setdata(model)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        val view: View = LayoutInflater.from(parent.context).inflate(R.layout.single_video_row, parent, false)
        return MyViewHolder(view)
    }

    inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        var videoView: VideoView
        var title: TextView
        var desc: TextView
        var pbar: ProgressBar
        var fav :ImageView
        var isFav = false

        fun setdata(obj: VideoModel) {
            videoView.setVideoPath(obj.url)
            title.setText(obj.title)
            desc.setText(obj.desc)

            videoView.setOnPreparedListener { mediaPlayer ->
                pbar.visibility = View.GONE
                mediaPlayer.start()
            }
            videoView.setOnCompletionListener { mediaPlayer -> mediaPlayer.start() }
            fav.setOnClickListener {
                if (!isFav){
                    fav.setImageResource(R.drawable.ic_fill_favorite)
                    isFav = true

                }
                else{
                    fav.setImageResource(R.drawable.ic_favorite)
                    isFav = false
                }

            }
        }

        init {
            videoView = itemView.findViewById<View>(R.id.videoView) as VideoView
            title = itemView.findViewById<View>(R.id.textVideoTitle) as TextView
            desc = itemView.findViewById<View>(R.id.textVideoDescription) as TextView
            pbar = itemView.findViewById<View>(R.id.videoProgressBar) as ProgressBar
            fav = itemView.findViewById(R.id.favorites) as ImageView
            count = itemView.findViewById(R.id.count) as TextView
        }

    }
}

VideoModel

data class VideoModel( 
    var title:String?=null,
    var desc:String?=null,
    var url:String?=null
)

Firebase中存储的视频数据包含title(标题)、desc(描述)、url(播放地址)三个字段。

解决方案

方法一:本地加载后打乱数据(适合小数据量场景)

FirebaseRecyclerAdapter直接绑定实时数据流,无法直接打乱顺序,可先将所有数据加载到本地列表,打乱后用普通RecyclerView Adapter展示:

  1. 修改MainActivity,监听数据变化并打乱列表
class MainActivity : AppCompatActivity() {

    lateinit var viewPager2: ViewPager2
    lateinit var adapter: VideoAdapter
    private val videoList = mutableListOf<VideoModel>()
    private val mDatabase = Firebase.database.getReference("videos")

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN)

        viewPager2 = findViewById(R.id.vpager)
        adapter = VideoAdapter(videoList)
        viewPager2.adapter = adapter

        // 监听Firebase数据变化
        mDatabase.addValueEventListener(object : ValueEventListener {
            override fun onDataChange(snapshot: DataSnapshot) {
                videoList.clear()
                snapshot.children.forEach { child ->
                    val video = child.getValue(VideoModel::class.java)
                    video?.let { videoList.add(it) }
                }
                // 打乱列表
                videoList.shuffle()
                adapter.notifyDataSetChanged()
            }

            override fun onCancelled(error: DatabaseError) {
                // 处理数据读取错误
            }
        })
    }
}
  1. 修改VideoAdapter为普通RecyclerView Adapter
class VideoAdapter(private val videoList: List<VideoModel>) :
    RecyclerView.Adapter<VideoAdapter.MyViewHolder>() {

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        holder.setdata(videoList[position])
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(R.layout.single_video_row, parent, false)
        return MyViewHolder(view)
    }

    override fun getItemCount() = videoList.size

    inner class MyViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        private val videoView: VideoView = itemView.findViewById(R.id.videoView)
        private val title: TextView = itemView.findViewById(R.id.textVideoTitle)
        private val desc: TextView = itemView.findViewById(R.id.textVideoDescription)
        private val pbar: ProgressBar = itemView.findViewById(R.id.videoProgressBar)
        private val fav: ImageView = itemView.findViewById(R.id.favorites)
        private var isFav = false

        fun setdata(obj: VideoModel) {
            videoView.setVideoPath(obj.url)
            title.text = obj.title
            desc.text = obj.desc

            videoView.setOnPreparedListener { mediaPlayer ->
                pbar.visibility = View.GONE
                mediaPlayer.start()
            }
            videoView.setOnCompletionListener { mediaPlayer -> mediaPlayer.start() }
            fav.setOnClickListener {
                isFav = !isFav
                fav.setImageResource(if (isFav) R.drawable.ic_fill_favorite else R.drawable.ic_favorite)
            }
        }
    }
}

方法二:Firebase端添加随机排序字段(适合大数据量场景)

给每条视频添加随机数值字段,通过Firebase查询时按该字段排序,实现随机返回:

  1. 更新VideoModel,添加random字段
data class VideoModel( 
    var title: String? = null,
    var desc: String? = null,
    var url: String? = null,
    var random: Double? = null
)
  1. 上传视频时,给每条视频设置random值(比如用Math.random()生成0-1之间的随机数)。

  2. 修改MainActivity中的查询逻辑

val options = FirebaseRecyclerOptions.Builder<VideoModel>()
    .setQuery(mDataBase.orderByChild("random"), VideoModel::class.java)
    .build()

方案对比

  • 方法一:实现简单,无需修改Firebase数据结构;但需加载全部数据到本地,数据量大时内存开销高,实时更新需重新打乱。
  • 方法二:无需本地加载全部数据,适合大数据量;但需维护额外字段,随机性依赖随机字段的分布均匀度。

内容的提问来源于stack exchange,提问作者Yugant Jha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 04:06:13