Android進階之多級列表

遇到一個需求需要顯示多級列表,因為界面是在平板上的,所以層級是從左向右往下排的,類似于
在這里插入圖片描述
我當時的寫法是在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? = nullfun find(view: ConstraintLayout, //父控件context: Context, //上下文gradle: ArrayList<GetListData>, //幾級){clearList()mParentView = viewfor (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.idlayoutParams.topToTop = view.idif (mGradle.leftMargin != 0){layoutParams.leftMargin = mGradle.leftMargin}}else{layoutParams.startToEnd = mRVList[i-1].idlayoutParams.topToTop = mRVList[i-1].idif (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 = layoutParamsmRecyclerView.layoutManager = LinearLayoutManager(context)mRecyclerView.itemAnimator = DefaultItemAnimator()val mAdapter = QnZtListAdapter(R.layout.item_get_list,mGradle)mRecyclerView.adapter = mAdaptermAdapterList.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 = trueadapter.notifyDataSetChanged()}}}//獲取對應層級的列表private fun getList(i: Int): RecyclerView?{var mL: RecyclerView? = nullif (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? = nullif (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.Serializableclass QnZtListAdapter : BaseQuickAdapter<GetListUtils.TestData, BaseViewHolder> {constructor(layoutResId: Int) : super(layoutResId) {}private var gradle: GetListUtils.GetListData? = nullconstructor(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.nameif (item.select){tvGetTxt.setTextColor(Color.RED)}else{tvGetTxt.setTextColor(Color.GRAY)}if (gradle != null){//界面高度if (gradle!!.itemHeight != 0){val lp: ViewGroup.LayoutParams = clGetList.layoutParamslp.height = gradle!!.itemHeightclGetList.layoutParams = lp}//字體大小if (gradle!!.itemSize != 0f){tvGetTxt.textSize = gradle!!.itemSize}}}}
}
item_get_list
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayoutandroid: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"><Viewandroid: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"/><TextViewandroid: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 = falseif (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 = falseif (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 = falseif (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 = falseif (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.ConstraintLayoutandroid: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.pswp.cn/news/41472.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/41472.shtml
英文地址,請注明出處:http://en.pswp.cn/news/41472.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

69 # 強制緩存的配置

強制緩存 強制緩存&#xff1a;以后的請求都不需要訪問服務器&#xff0c;狀態碼為 200協商緩存&#xff1a;每次都判斷一下&#xff0c;告訴是否需要找緩存&#xff0c;狀態碼為 304 默認強制緩存&#xff0c;不緩存首頁&#xff08;如果已經斷網&#xff0c;那這個頁面應該…

Python發送QQ郵件

使用Python的smtplib可以發送QQ郵件&#xff0c;代碼如下 #!/usr/bin/python3 import smtplib from email.mime.text import MIMEText from email.header import Headersender 111qq.com # 發送郵箱 receivers [222qq.com] # 接收郵箱 auth_code "abc" # 授權…

Dockerfile概念、鏡像原理、制作及案例講解

1.Docker鏡像原理 Linux文件操作系統講解 2.鏡像如何制作 3.Dockerfile概念 Docker網址&#xff1a;https://hub.docker.com 3.1 Dockerfile關鍵字 4.案例

【數據結構OJ題】鏈表分割

原題鏈接&#xff1a;https://www.nowcoder.com/practice/0e27e0b064de4eacac178676ef9c9d70?tpId8&&tqId11004&rp2&ru/activity/oj&qru/ta/cracking-the-coding-interview/question-ranking 目錄 1. 題目描述 2. 思路分析 3. 代碼實現 1. 題目描述 2…

AMD卡啟動Stable Diffusion AI繪畫的方法

WindowsAMD安裝法 1.安裝python 3.10.6&#xff0c;在python官網上下載安裝程序&#xff0c;***重要*** 在安裝的第一個窗口下方勾選“將python添加到path”。 2.安裝git 3.WindowsAMD使用AUTOMATIC1111的directml這一個fork&#xff0c;在這個頁面的第一段&#xff1a;https:/…

題目:2614.對角線上的質數

??題目來源&#xff1a; leetcode題目&#xff0c;網址&#xff1a;2614. 對角線上的質數 - 力扣&#xff08;LeetCode&#xff09; 解題思路&#xff1a; 遍歷對角線上的元素&#xff0c;返回最大的質數或 0 即可。 解題代碼&#xff1a; class Solution {public int dia…

e.target.value和 binding.value 區別

e.target.value 和 binding.value 都是在 Vue.js 中用于處理事件綁定時的值&#xff0c;但它們的使用場景和含義有所不同&#xff0c;分別用于普通的 DOM 事件和自定義指令。 e.target.value&#xff1a; 這是常用于原生 DOM 事件處理函數中的一個屬性&#xff0c;用于獲取事件…

爬蟲逆向實戰(十七)--某某丁簡歷登錄

一、數據接口分析 主頁地址&#xff1a;某某丁簡歷 1、抓包 通過抓包可以發現數據接口是submit 2、判斷是否有加密參數 請求參數是否加密&#xff1f; 通過查看“載荷”模塊可以發現有一個enPassword加密參數 請求頭是否加密&#xff1f; 通過查看請求頭可以發現有一個To…

【面試高頻題】難度 3/5,字典樹熱門運用題

題目描述 這是 LeetCode 上的 「745. 前綴和后綴搜索」 &#xff0c;難度為 「困難」。 Tag : 「字典樹」 設計一個包含一些單詞的特殊詞典&#xff0c;并能夠通過前綴和后綴來檢索單詞。 實現 WordFilter 類&#xff1a; WordFilter(string[] words) 使用詞典中的單詞 words 初…

單片機之從C語言基礎到專家編程 - 4 C語言基礎 - 4.9 變量與常量

基本數據類型可以作為變量與常量使用,顧名思義&#xff0c;變量運行時可以改變其值&#xff0c;常量運行時不會改變其值。 常量分為整型常量、浮點型常量、字符常量、字符串常量和符號常量。 通常用#define來定義一個標識符來表示一個常量 用type name 常量來定義一個變量,…

無法將“環境變量”項識別為 cmdlet、函數、腳本文件或可運行程序的名稱(pycharm)

無法將“配置的任何一個環境變量”項識別為 cmdlet、函數、腳本文件或可運行程序的名稱。 記錄解決“無法將“C:......conda.exe”項識別為 cmdlet、函數、腳本文件或可運行程序的名稱”以及“表達式或語句中包含意外的標記”的系列問題(VSCode開發環境)一、Conda.exe無法正常識…

ROS2 學習(三)話題

話題 節點之間的通信。 叫話題很形象。發布者發布一定數據類型的話題&#xff0c;訂閱者訂閱發布者。 訂閱者發布者不唯一。 異步通信&#xff0c;適用于周期發布的數據而不是邏輯性強的數據。 .msg 格式的消息結構&#xff0c;一種通信接口。 每個話題 topic 有話題名&a…

【Java高級開發高頻面試題】面試者角度的口述版

文章目錄 1.具備扎實的Java基礎集合HashMap底層工作原理HashMap版本問題HashMap并發修改異常HashMap影響HashMap性能的因素HashMap使用優化 SynchronizedThreadLocalAQS線程池JVM內存模型類加載機制與雙親委派垃圾回收算法、垃圾回收器、空間分配擔保策略引用計數器算法、可達性…

創建 Web 內容目錄

創建 Web 內容目錄 按照下方所述&#xff0c;創建一個名為 /home/curtis/ansible/webcontent.yml 的 playbook &#xff1a; 該 playbook 在 dev 主機組中的受管節點上運行 創建符合下列要求的目錄 /webdev &#xff1a; 所有者為 webdev 組 具有常規權限&#xff1a;ownerread…

Nginx反向代理

目錄 一.簡介1.反向代理 二.案例1.案例12.案例2 一.簡介 1.反向代理 1.1反向代理&#xff1a; 是指代理服務器來接收Internet上的客戶端請求&#xff0c;然后將請求轉發給內部網絡上的服務器&#xff0c;并將從服務器上得到的結果返回給客戶端。此時代理服務器對外就表現為一…

循環隊列的實現(c語言)

前言 循環隊列是隊列的一種特殊的結構&#xff0c;在生產者——消費者模型中常常使用它&#xff0c; 它在邏輯上是一個環形的連續的結構。在物理可以使用數組來實現。 目錄 1.循環隊列的邏輯結構 2.空的循環隊列和滿的循環隊列 3.循環隊列插入和刪除 4.代碼實現 …

淺談Redis的maxmemory設置以及淘汰策略

推薦閱讀 AI文本 OCR識別最佳實踐 AI Gamma一鍵生成PPT工具直達鏈接 玩轉cloud Studio 在線編碼神器 玩轉 GPU AI繪畫、AI講話、翻譯,GPU點亮AI想象空間 資源分享 「java、python面試題」來自UC網盤app分享&#xff0c;打開手機app&#xff0c;額外獲得1T空間 https://dr…

音視頻實時通話解決方案

1、問題提出 想要實現音視頻通話,對于大部分人可能會覺得很難,但是實際上,有些事情并沒有大家想的那樣困難,只要功夫深,鐵杵磨成針。 機緣巧合下,在業務中,我也遇到了一個業務場景需要實現音視頻通話,我們不可能自己從零開始干,我本次用到的核心是WebRTC。 2、WebRT…

治療偏頭痛等亞疼痛的遠程電神經調控(REN)設備

原文鏈接&#xff1a; NERIVIO CE標志適應癥擴展到青少年和成人偏頭痛的預防和急性治療 (prnewswire.com) 公司官網&#xff1a; Homepage - Theranica APP下載鏈接&#xff1a; Migraine Headache Treatment - Nerivio 使用過程問題&#xff1a; 常見問題 - 無藥物偏頭痛兩…

統計XML標注文件中各標注類別的標簽數量

目標檢測任務重&#xff0c;擔心數據集中各標簽類別不均衡&#xff0c;想統計XML標注文件中各標注類別的標簽數量&#xff0c;可以使用以下腳本&#xff1a; import os import glob import xml.etree.ElementTree as etdef count_labels(source_dir):file_list glob.glob(os.…