Android进阶之多级列表

news2024/11/23 19:47:20

遇到一个需求需要显示多级列表,因为界面是在平板上的,所以层级是从左向右往下排的,类似于
在这里插入图片描述
我当时的写法是在xml布局里一个个RecyclerView往下排的

在这里插入图片描述
当然前提是已经规定好最大的层级我才敢如此去写界面,如果已经明确规定只有两级或者三级,当然如果可以的话,不管多少级都这么写也是没毛病的

作为一名开发者,如果以后也用到类似的需求,并且级数不是固定的话,这么写肯定是有很多瑕疵的,所以想着怎么样去做一个轮子,以后遇到直接拿来用就行,不用每次都去搭界面,写逻辑,当然网络上也有类似的代码,但是感觉和自己的有多少出入,那不如自己来写一套吧

下面是效果图,界面有些丑,没有花时间去做一些美化,只是为了展示不同的效果,毕竟真正用起来界面样式还是多样化没法固定的

在这里插入图片描述
在这里插入图片描述
首先的问题是如何去分级,一开始想法是把所有数据放进入,自己去解析数据进行分级,但是又可能涉及到部分数据需要网络请求等复杂的环境

问题一: 如何解决一开始就分级还是点击之后逐级显示?

答: 自主触发,不自行解析添加,告诉我添加我再去添加

问题二: 不同条件下如何去分级?

答: 要定义一个自己的规则,可能不完善但是后面可以自己添加,否则出现要写死或者部分要网络请求的时候无法完整判断,而且不同的数据结构可能连参数名字都不一样,所以需要自主分类并且添加数据

思路:

1.一开始传入最大多少级,以及每一级的样式(比如宽度,背景),动态创建对应级数的列表并和适配器存储起来(别忘了关闭界面的时候或者不使用的时候去销毁),这样就不会存在每次点击都重新创建列表的情况,每次点击只是对应的显示隐藏和替换数据而已

2.我需要创建第一级的时候,我将第一级的数据筛选出来,将步骤1存储的第一级适配器拿出来塞数据

3.如果我一开始就要将第一级相关的全部显示出来我只要自己去根据数据筛选出对应的下一级,继续往里面塞

4.如果我要点击之后显示,那我也和第三步骤一样,点击之后我再去筛选,再去塞数据

5.我点之后要将所有下面的级数隐藏,在去显示对应的层级,否则就会出现我已经出现了三级,此时我点击其他的层级没有第三极,但是上次的第三极还在那显示

6.样式问题,不同的需求有不同的样式,这点无能为力,只能自己去修改样式,但是最基础的每一级的宽度,间距,背景,以及每一个条目的字体大小,高度是必须的,我可以统一规定起来

具体实现:

首先导入用到的三方依赖

 implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.4'

其中的适配器里的实体类要根据自己的情况去更改

1.创建多级列表:

xml布局里的主布局要用约束布局
将不同层级样式给Util去创建

        //这个集合存储的是每一层级的样式以及信息,会根据该集合的长度去创建最大多少级
        val mList: ArrayList<GetListUtils.GetListData> = arrayListOf()
        //第一级样式
        mList.add(GetListUtils.GetListData(width = 200,itemSize = 16f,itemHeight = 160, bGround = "#CC00FFFF"))
        //第二级样式
        mList.add(GetListUtils.GetListData(itemSize = 14f,itemHeight = 140,leftMargin = 60, bDrawable = getDrawable(R.mipmap.ic_launcher)))
        //第三极样式
        mList.add(GetListUtils.GetListData(width = 180,itemSize = 12f,itemHeight = 120,leftMargin = 80,bGround = "#CC33ff00"))
        //第四级样式
        mList.add(GetListUtils.GetListData(itemSize = 10f,itemHeight = 100,leftMargin = 30,bGround = "#CCFFFF33"))
        //第五级样式
        mList.add(GetListUtils.GetListData(itemSize = 8f,itemHeight = 80,leftMargin = 70))

        //这里是布局里的主布局,要用约束布局!!!
        val clAll = findViewById<ConstraintLayout>(R.id.cl_all)
        //层级列表和主布局传进去
        GetListUtils.find(clAll,context = this,mList)

2.自行分类,将数据塞给对应的层级,这里是筛选出第一级数据,并把数据给第一级

这里的模拟数据集合就需要替换成项目中真正的数据类了(TestData)

        //模拟数据 type当前类型 parentType 父级,默认parentType = 0 为一级
        val mListAll: ArrayList<GetListUtils.TestData> = arrayListOf()

        mListAll.add(GetListUtils.TestData(name = "美食",type = 1, parentType = 0))
        mListAll.add(GetListUtils.TestData("饮品",2,0))

        mListAll.add(GetListUtils.TestData("西瓜",3,1))
        mListAll.add(GetListUtils.TestData("火龙果",4,1))
        mListAll.add(GetListUtils.TestData("葡萄",5,1))
        mListAll.add(GetListUtils.TestData("橘子",6,1))
        mListAll.add(GetListUtils.TestData("可乐",7,2))
        mListAll.add(GetListUtils.TestData("雪碧",8,2))
        mListAll.add(GetListUtils.TestData("美年达",9,2))

        mListAll.add(GetListUtils.TestData("西瓜汁",10,3))
        mListAll.add(GetListUtils.TestData("冰镇西瓜",11,3))
        mListAll.add(GetListUtils.TestData("火龙果块",12,4))
        mListAll.add(GetListUtils.TestData("冰葡萄",13,5))
        mListAll.add(GetListUtils.TestData("橘子汁",14,6))
        mListAll.add(GetListUtils.TestData("无糖可乐",15,7))
        mListAll.add(GetListUtils.TestData("满糖可乐",16,7))

        mListAll.add(GetListUtils.TestData("西瓜皮",17,11))
        mListAll.add(GetListUtils.TestData("西瓜籽",18,11))
        mListAll.add(GetListUtils.TestData("西瓜瓤",19,11))
        mListAll.add(GetListUtils.TestData("火龙果籽",20,12))
        mListAll.add(GetListUtils.TestData("橘子皮",21,14))
        mListAll.add(GetListUtils.TestData("橘子核",22,14))

        mListAll.add(GetListUtils.TestData("西瓜子",23,18))


        //筛选一级目录
        val mList1: ArrayList<GetListUtils.TestData> = arrayListOf()
        mListAll.forEach {
            if (it.parentType == 0){
                mList1.add(it)
            }
        }
        //设置一级目录
        GetListUtils.setListData(1,mList1,object :GetListUtils.OnListener{
            override fun onClick(l: GetListUtils.TestData) {
                

            }
        })

默认显示对应的层级,只需要继续筛选,继续塞数据即可

        //筛选二级目录
        val mList2: ArrayList<GetListUtils.TestData> = arrayListOf()
        mListAll.forEach {
            if (it.parentType == 1){
                mList1.add(it)
            }
        }
        GetListUtils.setListData(2,mList2,object :GetListUtils.OnListener{
            override fun onClick(l: GetListUtils.TestData) {
            }

        })

以上就是使用方式, setListData(当前层级,层级数据,点击事件回调)

以下全部代码,供参考

GetListUtils
/**
 * 动态添加集合
 * */
object GetListUtils {

    private val mRVList: ArrayList<RecyclerView> = arrayListOf()
    private val mAdapterList: ArrayList<QnZtListAdapter> = arrayListOf()
    private var mParentView: ConstraintLayout? = null

    fun find(view: ConstraintLayout, //父控件
             context: Context, //上下文
             gradle: ArrayList<GetListData>, //几级
    ){
        clearList()
        mParentView = view
        for (i in 0 until gradle.size){
            val mGradle = gradle[i]
            val mRecyclerView = RecyclerView(context)
            mRecyclerView.id = View.generateViewId()
            mRVList.add(mRecyclerView)
            val layoutParams = ConstraintLayout.LayoutParams(
                mGradle.width,
                ViewGroup.LayoutParams.WRAP_CONTENT
            )
            if (i == 0){
                layoutParams.startToStart = view.id
                layoutParams.topToTop = view.id

                if (mGradle.leftMargin != 0){
                    layoutParams.leftMargin = mGradle.leftMargin
                }
            }else{
                layoutParams.startToEnd = mRVList[i-1].id
                layoutParams.topToTop = mRVList[i-1].id

                if (mGradle.leftMargin != 0){
                    layoutParams.leftMargin = mGradle.leftMargin
                }
            }
            //背景图优先级高
            if (mGradle.bDrawable != null){
                mRecyclerView.background = mGradle.bDrawable
            }else{
                if (mGradle.bGround.isNotEmpty()){
                    mRecyclerView.setBackgroundColor(Color.parseColor(mGradle.bGround))
                }
            }
            mRecyclerView.layoutParams = layoutParams
            mRecyclerView.layoutManager = LinearLayoutManager(context)
            mRecyclerView.itemAnimator = DefaultItemAnimator()

            val mAdapter = QnZtListAdapter(R.layout.item_get_list,mGradle)
            mRecyclerView.adapter = mAdapter
            mAdapterList.add(mAdapter)
            view.addView(mRecyclerView)
        }
    }

    //设置数据
    fun setListData(i: Int, l: ArrayList<TestData>,k: OnListener){
        val a = getAdapter(i)
        if (a != null){
            a.setList(l)
            a.setOnItemClickListener { adapter, view, position ->
                //点击当前层级,隐藏下一层级
                for (j in 0 until mRVList.size){
                    //这里减一是因为点击的时候是i点击的当前级数,要从下一级开始
                    if (j > i-1){
                        mRVList[j].visibility = View.GONE
                    }
                }
                //这里加一是因为i是当前级数,要从下一级开始
                //下标从零开始为什么还要加一呢?因为获取列表里面减一了
                if (getList(i+1) != null){
                    getList(i+1)!!.visibility = View.VISIBLE
                }
                val mData = adapter.data as ArrayList<TestData>
                //回调
                k.onClick(mData[position])
                //更新选中状态
                mData.forEach {
                    it.select = false
                }
                mData[position].select = true
                adapter.notifyDataSetChanged()
            }
        }
    }

    //获取对应层级的列表
    private fun getList(i: Int): RecyclerView?{
        var mL: RecyclerView? = null
        if (mRVList.isNotEmpty() && i-1 < mRVList.size){
            try {
                mL = mRVList[i - 1]
            }catch (e: java.lang.Exception){
                e.printStackTrace()
            }
        }
        return mL
    }

    //获取对应层级的适配器
    private fun getAdapter(i: Int): QnZtListAdapter?{
        var mAdapter: QnZtListAdapter? = null
        if (mAdapterList.isNotEmpty() && i-1 < mAdapterList.size){
            try {
                mAdapter = mAdapterList[i - 1]
            }catch (e: java.lang.Exception){
                e.printStackTrace()
            }
        }
        return mAdapter
    }

    //置空操作
    fun clearList(){
        mRVList.clear()
        mAdapterList.clear()
        if (mParentView != null){
            mParentView!!.removeAllViews()
        }
    }

    interface OnListener {
        fun onClick(l: TestData)
    }

    //需要的数据类
    data class GetListData(
        var width: Int = ViewGroup.LayoutParams.WRAP_CONTENT, //宽度
        var leftMargin: Int = 0, //左间距
        var bGround: String = "", //背景颜色
        var bDrawable: Drawable? = null, //背景图片
        var itemSize: Float = 0f, //条目字体大小
        var itemHeight: Int = ViewGroup.LayoutParams.WRAP_CONTENT, //条目字体高度
    ):java.io.Serializable

    //模拟数据
    data class TestData(
        var name: String? = "", //名称
        var type: Int? = 0, //分类
        var parentType: Int? = 0, //父类
        var select: Boolean = false //是否选中
    ):java.io.Serializable


    class QnZtListAdapter : BaseQuickAdapter<GetListUtils.TestData, BaseViewHolder> {

        constructor(layoutResId: Int) : super(layoutResId) {}

        private var gradle: GetListUtils.GetListData? = null

        constructor(layoutResId: Int, data: GetListUtils.GetListData) : super(layoutResId) {
            this.gradle = data
        }

        override fun convert(helper: BaseViewHolder, item: GetListUtils.TestData) {
            //总布局
            val clGetList = helper.getView<ConstraintLayout>(R.id.cl_get_list)
            //第一条不显示分割线
            if (helper.adapterPosition == 0){
                helper.setGone(R.id.view_line,true)
            }

            val tvGetTxt = helper.getView<TextView>(R.id.tv_get_txt)
            tvGetTxt.text = item.name

            if (item.select){
                tvGetTxt.setTextColor(Color.RED)
            }else{
                tvGetTxt.setTextColor(Color.GRAY)
            }

            if (gradle != null){
                //界面高度
                if (gradle!!.itemHeight != 0){
                    val lp: ViewGroup.LayoutParams = clGetList.layoutParams
                    lp.height = gradle!!.itemHeight
                    clGetList.layoutParams = lp
                }
                //字体大小
                if (gradle!!.itemSize != 0f){
                    tvGetTxt.textSize = gradle!!.itemSize
                }

            }
        }

    }
}
item_get_list
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    android:id="@+id/cl_get_list"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <View
        android:id="@+id/view_line"
        android:layout_width="0dp"
        android:layout_height="1px"
        android:background="#CC666666"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <TextView
        android:id="@+id/tv_get_txt"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        tools:text = "哈哈哈"/>

</androidx.constraintlayout.widget.ConstraintLayout>
AddListActivity
/**
 * 动态创建多级列表*/
class AddListActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_add_list)

        //这个集合存储的是每一层级的样式以及信息,会根据该集合的长度去创建最大多少级
        val mList: ArrayList<GetListUtils.GetListData> = arrayListOf()
        //第一级样式
        mList.add(GetListUtils.GetListData(width = 200,itemSize = 16f,itemHeight = 160, bGround = "#CC00FFFF"))
        //第二级样式
        mList.add(GetListUtils.GetListData(itemSize = 14f,itemHeight = 140,leftMargin = 60, bDrawable = getDrawable(R.mipmap.ic_launcher)))
        //第三极样式
        mList.add(GetListUtils.GetListData(width = 180,itemSize = 12f,itemHeight = 120,leftMargin = 80,bGround = "#CC33ff00"))
        //第四级样式
        mList.add(GetListUtils.GetListData(itemSize = 10f,itemHeight = 100,leftMargin = 30,bGround = "#CCFFFF33"))
        //第五级样式
        mList.add(GetListUtils.GetListData(itemSize = 8f,itemHeight = 80,leftMargin = 70))

        //这里是布局里的主布局,要用约束布局!!!
        val clAll = findViewById<ConstraintLayout>(R.id.cl_all)
        //层级列表和主布局传进去
        GetListUtils.find(clAll,context = this,mList)

        //模拟数据 type当前类型 parentType 父级,默认parentType = 0 为一级
        val mListAll: ArrayList<GetListUtils.TestData> = arrayListOf()

        mListAll.add(GetListUtils.TestData(name = "美食",type = 1, parentType = 0))
        mListAll.add(GetListUtils.TestData("饮品",2,0))

        mListAll.add(GetListUtils.TestData("西瓜",3,1))
        mListAll.add(GetListUtils.TestData("火龙果",4,1))
        mListAll.add(GetListUtils.TestData("葡萄",5,1))
        mListAll.add(GetListUtils.TestData("橘子",6,1))
        mListAll.add(GetListUtils.TestData("可乐",7,2))
        mListAll.add(GetListUtils.TestData("雪碧",8,2))
        mListAll.add(GetListUtils.TestData("美年达",9,2))

        mListAll.add(GetListUtils.TestData("西瓜汁",10,3))
        mListAll.add(GetListUtils.TestData("冰镇西瓜",11,3))
        mListAll.add(GetListUtils.TestData("火龙果块",12,4))
        mListAll.add(GetListUtils.TestData("冰葡萄",13,5))
        mListAll.add(GetListUtils.TestData("橘子汁",14,6))
        mListAll.add(GetListUtils.TestData("无糖可乐",15,7))
        mListAll.add(GetListUtils.TestData("满糖可乐",16,7))

        mListAll.add(GetListUtils.TestData("西瓜皮",17,11))
        mListAll.add(GetListUtils.TestData("西瓜籽",18,11))
        mListAll.add(GetListUtils.TestData("西瓜瓤",19,11))
        mListAll.add(GetListUtils.TestData("火龙果籽",20,12))
        mListAll.add(GetListUtils.TestData("橘子皮",21,14))
        mListAll.add(GetListUtils.TestData("橘子核",22,14))

        mListAll.add(GetListUtils.TestData("西瓜子",23,18))


        //筛选一级目录
        val mList1: ArrayList<GetListUtils.TestData> = arrayListOf()
        mListAll.forEach {
            if (it.parentType == 0){
                mList1.add(it)
            }
        }
        //设置一级目录
        GetListUtils.setListData(1,mList1,object :GetListUtils.OnListener{
            override fun onClick(l: GetListUtils.TestData) {
                //点击一级目录后筛选二级
                val mList2: ArrayList<GetListUtils.TestData> = arrayListOf()
                mListAll.forEach {
                    //还原选中状态,如果默认选中第一个用for循环去设置
                    it.select = false
                    if (l.type == it.parentType){
                        mList2.add(it)
                    }
                }
                //设置二级目录
                GetListUtils.setListData(2,mList2,object :GetListUtils.OnListener{
                    override fun onClick(l: GetListUtils.TestData) {
                        //点击二级目录后筛选三级
                        val mList3: ArrayList<GetListUtils.TestData> = arrayListOf()
                        mListAll.forEach {
                            //还原选中状态,如果默认选中第一个用for循环去设置
                            it.select = false
                            if (l.type == it.parentType){
                                mList3.add(it)
                            }
                        }
                        //设置三级目录
                        GetListUtils.setListData(3,mList3,object :GetListUtils.OnListener{
                            override fun onClick(l: GetListUtils.TestData) {
                                //点击三级目录筛选四级目录
                                val mList4: ArrayList<GetListUtils.TestData> = arrayListOf()
                                mListAll.forEach {
                                    //还原选中状态,如果默认选中第一个用for循环去设置
                                    it.select = false
                                    if (l.type == it.parentType){
                                        mList4.add(it)
                                    }
                                }
                                //设置四级目录
                                GetListUtils.setListData(4,mList4,object :GetListUtils.OnListener{
                                    override fun onClick(l: GetListUtils.TestData) {
                                        //点击四级目录筛选五级目录
                                        val mList5: ArrayList<GetListUtils.TestData> = arrayListOf()
                                        mListAll.forEach {
                                            //还原选中状态,如果默认选中第一个用for循环去设置
                                            it.select = false
                                            if (l.type == it.parentType){
                                                mList5.add(it)
                                            }
                                        }
                                        GetListUtils.setListData(5,mList5,object :GetListUtils.OnListener{
                                            override fun onClick(l: GetListUtils.TestData) {
                                                Toast.makeText(this@AddListActivity,l.name,Toast.LENGTH_SHORT).show()
                                            }
                                        })
                                    }
                                })
                            }
                        })
                    }
                })

            }
        })

    }

    override fun onDestroy() {
        super.onDestroy()
        GetListUtils.clearList()
    }
}
activity_add_list
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    android:id="@+id/cl_all"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".AddListActivity">

</androidx.constraintlayout.widget.ConstraintLayout>

自测效果基本满意~ 就是要修改对应的TestData比较繁琐,后续看看能不能集中处理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/883025.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

回归预测 | MATLAB实现GRNN广义回归神经网络多输入多输出预测

回归预测 | MATLAB实现GRNN广义回归神经网络多输入多输出预测 目录 回归预测 | MATLAB实现GRNN广义回归神经网络多输入多输出预测预测效果基本介绍程序设计往期精彩参考资料 预测效果 基本介绍 MATLAB实现GRNN广义回归神经网络多输入多输出预测&#xff0c;输入10个特征&#x…

每日一题——合并二叉树

题目 已知两颗二叉树&#xff0c;将它们合并成一颗二叉树。合并规则是&#xff1a;都存在的结点&#xff0c;就将结点值加起来&#xff0c;否则空的位置就由另一个树的结点来代替。例如&#xff1a; 两颗二叉树是: Tree 1 Tree 2 合并后的树为 数据范围&#xff1a;树上节点数…

【笔试题心得】排序算法总结整理

排序算法汇总 常用十大排序算法_calm_G的博客-CSDN博客 以下动图参考 十大经典排序算法 Python 版实现&#xff08;附动图演示&#xff09; - 知乎 冒泡排序 排序过程如下图所示&#xff1a; 比较相邻的元素。如果第一个比第二个大&#xff0c;就交换他们两个。对每一对相邻…

快速入门vue3组合式API

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 使用create-vue创建项目 1. 前提环境条件 已安装 16.0 或更高版本的 Node.js node -v 2. 创建一个Vue应用 npm…

第三章nginx详解

nginx&#xff1a;高性能&#xff0c;轻量级的web服务软件。 特点&#xff1a; 1&#xff0c;稳定性高。&#xff08;没有apache稳定&#xff09; 2&#xff0c;系统资源消耗地较低。&#xff08;处理http请求的并发能力非常高&#xff0c;单台物理服务器可以处理30000-5000…

【漏洞通知】JeecgBoot 修复 Freemarker 模板注入漏洞, 漏洞危害等级:高危

Freemarker模板注入导致远程命令执行, 远程攻击者可利用该漏洞调用在系统上执行任意命令。 JeecgBoot官方已修复&#xff0c;建议大家尽快升级至相关底层依赖和源码 一、漏洞描述 Freemarker模板注入导致远程命令执行, 远程攻击者可利用该漏洞调用在系统上执行任意命令。漏洞…

神经网络基础-神经网络补充概念-14-逻辑回归中损失函数的解释

概念 逻辑回归损失函数是用来衡量逻辑回归模型预测与实际观测之间差异的函数。它的目标是找到一组模型参数&#xff0c;使得预测结果尽可能接近实际观测。 理解 在逻辑回归中&#xff0c;常用的损失函数是对数似然损失&#xff08;Log-Likelihood Loss&#xff09;&#xff…

流程挖掘in汽车丨宝马的流程效能提升实例

汽车行业在未来10年里&#xff0c;可能会面临比过去50年更多的变化。电动化、智能化、共享化和自动驾驶等方面的趋势可能给企业流程带来以下挑战&#xff1a; 供应链管理-电动化和智能化的发展可能导致供应链中的零部件和系统结构发生变化&#xff0c;企业需要重新评估和优化供…

【Linux】IO多路转接——epoll

目录 epoll初识 epoll的相关系统调用 epoll工作原理 epoll服务器 epoll的优点 epoll工作方式 对比LT和ET epoll初识 epoll也是系统提供的一个多路转接接口。 epoll系统调用也可以让我们的程序同时监视多个文件描述符上的事件是否就绪&#xff0c;与select和poll的定位是…

torch_geometric实现GCN和LightGCN

torch_geometric实现GCN和LightGCN 题记demo示意图GCN代码LightGCN代码参考博文及感谢 题记 使用torch_geometric实现GCN和LightGCN&#xff0c;以后可能要用&#xff0c;做一下备份 demo示意图 GCN代码 X ′ D ^ − 1 / 2 A ^ D ^ − 1 / 2 X Θ \mathbf{X}^{\prime} \mat…

Linux 僵死进程

fork复制进程之后&#xff0c;会产生一个进程叫做子进程&#xff0c;被复制的进程就是父进程。不管父进程先结束&#xff0c;还是子进程先结束&#xff0c;对另外一个进程完全没有影响&#xff0c;父进程和子进程是两个不同的进程。 一、孤儿进程 现在有以下代码&#xff1a;…

【Vue-Router】路由元信息

路由元信息&#xff08;Route Meta Information&#xff09;是在路由配置中为每个路由定义的一组自定义数据。这些数据可以包含任何你希望在路由中传递和使用的信息&#xff0c;比如权限、页面标题、布局设置等。Vue Router 允许你在路由配置中定义元信息&#xff0c;然后在组件…

国产32位单片机XL32F001,带1 路 12bit ADC,I2C、SPI、USART 等外设

XL32F001 系列单片机采用高性能的 32 位 ARM Cortex-M0内核&#xff0c;宽电压工作范围的 MCU。嵌入 24KbytesFlash 和 3Kbytes SRAM 存储器&#xff0c;最高工作频率 24MHz。包含多种不同封装类型多款产品。芯片集成 I2C、SPI、USART 等通讯外设&#xff0c;1 路 12bit ADC&am…

【校招VIP】测试方案之测试用例分析

考点介绍 测试用例是测试岗面试和工作后的核心&#xff0c;在面试里对测试用例的分析是高频考查点。但是很多同学因为没有真实的商业产品需求&#xff0c;只能简单的看别人的用例学习&#xff0c;导致面试时被一个陌生问题卡住。 比如最简单的用户名密码输入&#xff0c;在商业…

2023年网络安全比赛--综合渗透测试(超详细)

一、竞赛时间 180分钟 共计3小时 二、竞赛阶段 竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 1.扫描目标靶机将靶机开放的所有端口,当作flag提交(例:21,22,23); 2.扫描目标靶机将靶机的http服务版本信息当作flag提交(例:apache 2.3.4); 3.靶机网站存在目录遍历漏洞,请将…

数据库--SQL关键字的执行顺序

一条sql语句通常包括&#xff1a; select from join where group by having order by 聚合函数 limit top 浅谈执行顺序&#xff1a; 1&#xff09;、首先确定一点&#xff0c;并不是按照我们写的语句顺序&#xff0c;从左—>右执行的 2&#xff09;、…

JVM——分代收集理论和垃圾回收算法

一、分代收集理论 1、三个假说 弱分代假说&#xff1a;绝大多数对象都是朝生夕灭的。 强分代假说&#xff1a;熬过越多次垃圾收集过程的对象越难以消亡。 这两个分代假说共同奠定了多款常用的垃圾收集器的一致的设计原则&#xff1a;收集器应该将Java堆划分出不同的区域&…

R语言实现免疫浸润分析(1)

免疫浸润分析是生物信息学研究中的一项关键内容&#xff0c;它旨在评估肿瘤微环境中不同类型的免疫细胞组成。免疫细胞在肿瘤发展和治疗中起着至关重要的作用&#xff0c;因为它们可以影响肿瘤的生长、扩散和对治疗的响应。 为了了解免疫细胞在肿瘤中的分布和数量&#xff0c;…

【潮州饶平】联想 IBM x3850 x6 io主板故障 服务器维修

哈喽 最近比较忙也好久没有更新服务器维修案例了&#xff0c;这次分享一例潮州市饶平县某企业工厂一台IBM System x3850 x6服务器亮黄灯告警且无法正常开机的服务器故障问题。潮州饶平ibm服务器维修IO主板故障问题 故障如下图所示&#xff1a; 故障服务器型号&#xff1a;IBM 或…

客达天下项目案例

本资料转载于传智播客https://www.itheima.com/ https://space.bilibili.com/3493265607232348 黑马程序员主办的全日制统招大学——大同互联网职业技术学院 预计2024年开始招生&#xff0c;敬请持续关注&#xff01; B站视频入口&#xff1a;002_接口项目介绍_哔哩哔哩_bili…