Android APP 基于RecyclerView框架工程(知识体系积累)
说明:这个简单的基于RecyclerView的框架作用在于自己可以将平时积累的一些有效demo整合起来(比如音视频编解码的、opengles的以及其他也去方向的、随着项目增多,工程量的增加,后期想高效的分析和查找并不容易),不用搞太多的工程,不像多个工程过于分散也占空间。
1 基于RecyclerView框架工程实现原理说明
该工程通过config.xml配置文件获取每一个网格中的基本信息,并将其存储到itemlist中。应用启动后,点击网格中的按键,每个按键可以按需启动一个应用。适用于长期积累自己的知识体系。
接下来直接上干货,粘过去可以直接用的那种~。平台是基于Android12的。
2 框架工程代码完整解读(android Q)
2.1 layout布局文件解读
res/layout 主界面 activity_main.xml内容如下:
<androidx.constraintlayout.widget.ConstraintLayout 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:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"tools:ignore="ExtraText"><androidx.recyclerview.widget.RecyclerViewandroid:id="@+id/recyclerview"android:layout_width="match_parent"android:layout_height="500dp"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toTopOf="parent" /><TextViewandroid:id="@+id/textviewMainMenu"android:layout_width="match_parent"android:layout_height="200dp"android:text="@string/title"android:background="@color/white"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toRightOf="parent"app:layout_constraintTop_toBottomOf="@+id/recyclerview" />
</androidx.constraintlayout.widget.ConstraintLayout>
RecycleView中需要使用的配置文件item参考实现如下:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"><TextViewandroid:id="@+id/textView"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginStart="4dp"android:layout_marginTop="18dp"android:text="@string/title"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent" /><Buttonandroid:id="@+id/button"android:layout_height="wrap_content"android:layout_width="wrap_content"android:text="@string/h264_decode_demo"app:layout_constraintStart_toStartOf="@+id/textView"app:layout_constraintTop_toBottomOf="@+id/textView"tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>
2.2 配置文件体系构建
使用res/xml 配置文件 config.xml内容如下:
<?xml version="1.0" encoding="utf-8"?>
<items><item><description>H264解码一个download目录下的out.h264码流</description><buttonName>H264解码</buttonName><activityName>com.wds.videoexample.Activity1</activityName></item><item><description>通过mediaprojection获取投屏数据,使用H264编码一个sdcard/路径下的codec.h264码流</description><buttonName>H264编码</buttonName><activityName>com.example.app.Activity2</activityName></item><item><description>通过camerax获取投屏数据,使用H264编码一个sdcard/路径下的codec.h264码流</description><buttonName>Button03</buttonName><activityName>com.example.app.Activity3</activityName></item>。。。
<items>
关于元素的个数和tag,大家可以自己按照自己的需求自定义。接下来有了配置文件,还要有配套的解析器,这里命名为ParseConfig,代码实现如下:
public class ParserConfig {private final static String TAG = "ParserConfig";private static List<Item> itemList;public static List<Item> getItemList() {return itemList;}private static String fullDescription = "";@SuppressLint("DefaultLocale")public static void initItemList(Context context) {itemList = new ArrayList<>();XmlResourceParser parser = context.getResources().getXml(R.xml.config);Log.d(TAG,"initItemLis");String description = null;String buttonName = null;String activityName = null;String tagName = null;//String fullDescription = "";int index= 0;try {int eventType = parser.getEventType();while (eventType != XmlPullParser.END_DOCUMENT) {if (eventType == XmlPullParser.START_TAG) {tagName = parser.getName();if ("item".equals(tagName)) {index++;while (parser.next() != XmlPullParser.END_TAG) {if (parser.getEventType() == XmlPullParser.TEXT) {description = parser.getText();fullDescription += "\ndemo"+String.format("%03d",index)+":"+description+"\n";}}while (parser.next() != XmlPullParser.END_TAG) {if (parser.getEventType() == XmlPullParser.TEXT) {buttonName = parser.getText();}}while (parser.next() != XmlPullParser.END_TAG) {if (parser.getEventType() == XmlPullParser.TEXT) {activityName = parser.getText();}}if (buttonName != null && activityName != null) {itemList.add(new Item(description,buttonName, activityName));}}}eventType = parser.next();}} catch (XmlPullParserException | IOException e) {e.printStackTrace();}}public static String getFullDescription(){return fullDescription;}
}
这里涉及的itemlist中的元素item定义如下:
public class Item {public String buttonName; //点击按键内容private String activityName;private String description;public Item(String description, String buttonName, String activityName) {this.buttonName = buttonName;this.activityName = activityName;this.description = description;}public String getDescription() {return description;}public void setDescription(String description) {this.description = description;}public String getButtonName() {return buttonName;}public void setButtonName(String buttonName) {this.buttonName = buttonName;}public String getActivityName() {return activityName;}public void setActivityName(String activityName) {this.activityName = activityName;}
}
2.3 权限的处理
关于权限,使用了一个Permission 专门的类来做运行时权限的处理,代码实现如下:
public class Permission {public static final int REQUEST_MANAGE_EXTERNAL_STORAGE = 1;//需要申请权限的数组private static final String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE,Manifest.permission.CAMERA};//保存真正需要去申请的权限private static final List<String> permissionList = new ArrayList<>();public static int RequestCode = 100;public static void requestManageExternalStoragePermission(Context context, Activity activity) {if (!Environment.isExternalStorageManager()) {showManageExternalStorageDialog(activity);}}private static void showManageExternalStorageDialog(Activity activity) {AlertDialog dialog = new AlertDialog.Builder(activity).setTitle("权限请求").setMessage("请开启文件访问权限,否则应用将无法正常使用。").setNegativeButton("取消", null).setPositiveButton("确定", (dialogInterface, i) -> {Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);activity.startActivityForResult(intent, REQUEST_MANAGE_EXTERNAL_STORAGE);}).create();dialog.show();}public static void checkPermissions(Activity activity) {for (String permission : permissions) {if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {permissionList.add(permission);}}if (!permissionList.isEmpty()) {requestPermission(activity);}}public static void requestPermission(Activity activity) {ActivityCompat.requestPermissions(activity,permissionList.toArray(new String[0]),RequestCode);}
}
这样,如果后面又更多的权限,都可以使用该方法来处理,处理方式为:
Permission.checkPermissions(this);
Permission.requestManageExternalStoragePermission(getApplicationContext(), this);
2.4 基于RecyclerView的框架工程 | 主流程代码参考实现
这里给出框架工程的代码的实现。具体如下:
public class MainActivity extends AppCompatActivity {private static final String TAG = "MainActivity";private RecyclerView mRecyclerView;MyAdapter mMyAdapter ;private List<Item> itemList;private TextView mTextViewMainmenu;@SuppressLint("DefaultLocale")@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);EdgeToEdge.enable(this);setContentView(R.layout.activity_main);ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);return insets;});mTextViewMainmenu = findViewById(R.id.textviewMainMenu);mTextViewMainmenu.setMovementMethod(ScrollingMovementMethod.getInstance());mRecyclerView = findViewById(R.id.recyclerview);ParserConfig.initItemList(this);mTextViewMainmenu.setText(ParserConfig.getFullDescription());itemList = ParserConfig.getItemList();mMyAdapter = new MyAdapter();mRecyclerView.setAdapter(mMyAdapter);GridLayoutManager layoutManager = new GridLayoutManager(MainActivity.this,3);mRecyclerView.setLayoutManager(layoutManager);DividerItemDecoration mDivider = newDividerItemDecoration(this, DividerItemDecoration.VERTICAL);mRecyclerView.addItemDecoration(mDivider);DividerItemDecoration mDivider2 = newDividerItemDecoration(this, DividerItemDecoration.HORIZONTAL);mRecyclerView.addItemDecoration(mDivider2);}class MyAdapter extends RecyclerView.Adapter<MyViewHoder> {@NonNull@Overridepublic MyViewHoder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {View view = View.inflate(MainActivity.this, R.layout.item_list, null);return new MyViewHoder(view);}@Overridepublic void onBindViewHolder(@NonNull MyViewHoder holder, int position) {Item item = itemList.get(position);@SuppressLint("DefaultLocale") String title_text = getString(R.string.wbs_demo) + String.format("%03d", position+1);holder.mTitleTv.setText(title_text);holder.mButton.setText(item.buttonName);holder.mButton.setTag(position);holder.mButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View view) {int position = (int)view.getTag();mTextViewMainmenu.setText(itemList.get(position).getDescription());Handler handler = new Handler();handler.postDelayed(new Runnable() {@Overridepublic void run() {if (position == 0) {Intent intent = new Intent(MainActivity.this, H264decoderActivity.class);startActivity(intent);} else if (position == 1) {Intent intent = new Intent(MainActivity.this, H264encoderMediaProjActivity.class);startActivity(intent);} else if (position == 2) {Intent intent = new Intent(MainActivity.this, H264encoderCameraXActivity.class);startActivity(intent);}}}, 3000); //Log.d(TAG,"onclick"+view.getTag());}});}@Overridepublic int getItemCount() {return itemList.size();}}static class MyViewHoder extends RecyclerView.ViewHolder {TextView mTitleTv;Button mButton;public MyViewHoder(@NonNull View itemView) {super(itemView);mTitleTv = itemView.findViewById(R.id.textView);mButton = itemView.findViewById(R.id.button);}}
}
2.5 主框架 demo实现效果
实际运行效果展示如下:
相关文章:

Android APP 基于RecyclerView框架工程(知识体系积累)
说明:这个简单的基于RecyclerView的框架作用在于自己可以将平时积累的一些有效demo整合起来(比如音视频编解码的、opengles的以及其他也去方向的、随着项目增多,工程量的增加,后期想高效的分析和查找并不容易)…...

【iOS】GCD
参考文章:GCD函数和队列原理探索 之前写项目的时候,进行耗时的网络请求使用GCD处理过异步请求,但对一些概念都很模糊,这次就来系统学习一下GCD相关 相关概念 什么是GCD? Grand Center Dispatch简称GCD,是…...

C语言 | Leetcode C语言题解之第282题给表达式添加运算符
题目: 题解: #define MAX_COUNT 10000 // 解的个数足够大 #define NUM_COUNT 100 // 操作数的个数足够大 long long num[NUM_COUNT] {0};long long calc(char *a) { // 计算表达式a的值// 将数字和符号,入栈memset(num, 0, sizeof(num));in…...
如何使用 API list 极狐GitLab 容器镜像仓库中的 tag?
GitLab 是一个全球知名的一体化 DevOps 平台,很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab :https://gitlab.cn/install?channelcontent&utm_sourcecsdn 是 GitLab 在中国的发行版,专门为中国程序员服务。可以一键式部署…...
粒子群算法PSO优化BP神经网络(PSO-BP)回归预测——Python和MATLAB实现
下面是一个使用Python实现的粒子群算法(PSO)优化反向传播神经网络(BP)的示例代码。 以下是具体的代码实现: python import numpy as np from sklearn.datasets import make_regression from sklearn.model_selection…...
React-router路由配置及跳转
1、V6对比V5的修改内容 1、API: useNavigate 代替了useHistory 。 2、废弃了Route组件的exact属性。 3、组件 <Routes>代替了<Switch> 4、组件NavLink中移除了 activeStyle activeClassName 属性。 2、安装依赖react-router-dom npm install react-router-dom…...

vue3【实战】可编辑的脱敏信息
<script lang"ts" setup> import { ref, onMounted } from "vue"; let real_name ref("朝阳");let name ref("");onMounted(() > {name.value des_name(real_name.value); });function focusing() {name.value real_name…...

S71200 - 笔记
1 S71200 0 ProfiNet - 2 PLC编程 01.如何零基础快速上手S7-1200_哔哩哔哩_bilibili 西门子S7-1200PLC编程设计学习视频,从入门开始讲解_哔哩哔哩_bilibili...

linux系统查历史cpu使用数据(使用sar 查询cpu和网络占用最近1个月历史数据)。
一 sar 指令介绍 在 Linux 系统中,sar 是 System Activity Reporter 的缩写,是一个用于收集、报告和保存系统活动信息的工具。它是 sysstat 软件包的一部分,提供了丰富的系统性能数据,包括 CPU、内存、网络、磁盘等使用情况&am…...

Edge浏览器加载ActiveX控件
背景介绍 新版Edge浏览器也是采用Chromium内核,虽然没有谷歌浏览器市场占有率高,但是依托微软操作系统的优势,Edge浏览器还是发展很强劲,占据着市场第二的位置。随着微软停止服务IE浏览器,曾经风光无限的IE浏览器页退出…...

BUG与测试用例设计
一.软件测试的生命周期 需求分析→测试计划→测试设计,测试开发→测试执行→测试评估→上线→运行维护 二.BUG 1.bug的概念 (1)当且仅当规格说明(需求文档)是存在的并且正确,程序与规格说明之间的不匹配才是错误. (2)当需求规格说明书没有提到的功能,判断标准以最终用户为准…...
怎么在使用select2时,覆盖layui的下拉框样式
目录 1.覆盖下拉框样式代码 2.自定义样式 3.样式使用 1.覆盖下拉框样式代码 .layui-form-select .layui-select-title {border: none !important; /* 去除边框 */background-color: transparent !important; /* 去除背景色 */display: none;/* 其他你想要覆盖的样式 */} 2.自…...
MacOSM1 配置Miniconda环境,并设置自启动
文章目录 设置环境变量设置自启动参考 设置环境变量 cd vim .zshrc输入一下内容 # 配置Conda CONDA_HOME/Users/hanliqiang/miniconda3 PATH$CONDA_HOME/bin:$PATH生效配置 source .zshrc设置自启动 conda init zsh.zshrc 文件中将会出现以下内容 # >>> conda i…...

poi库简单使用(java如何实现动态替换模板Word内容)
目录 Blue留言: Blue的推荐: 什么是poi库? 实现动态替换 第一步:依赖 第二步:实现word模板中替换文字 模板word: 通过以下代码:(自己建一个类,随意取名…...

机器人开源调度系统OpenTcs6二开-车辆表定义
前面已经知道opentcs 需要车辆的模型结构数据,将里面的数据结构化,已表的形式生成,再找一个开源的基础框架项目对车辆进行增删改的管理 表结构: CREATE TABLE Vehicle (id INT AUTO_INCREMENT PRIMARY KEY COMMENT 唯一标识符,n…...

麦歌恩MT6521-第三代汽车磁性角度传感器芯片
磁性编码芯片 -在线编程角度位置IC 描述: MT6521是麦歌恩微电子推出的新一代基于水平霍尔及聚磁片(IMC)技术原理的磁性角度和位置检测传感器芯片。该芯片内部包含了两对互成90放置的水平霍尔阵列及聚磁片,能够根据不同的型号配置来实现对XY࿰…...

【数据结构】堆,优先级队列
目录 堆堆的性质大根堆的模拟实现接口实现构造方法建堆入堆判满删除判空获取堆顶元素 Java中的PriorityQueue实现的接口构造方法常用方法PriorityQueue注意事项 练习 堆 如果有一个集合K {k0,k1, k2,…,kn-1},把它的…...
2024 暑假友谊赛 2
Tree Queries - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 思路:LCA好题,也有看见用时间戳写的,不是很明白. 用LCA非常好写。 要想到,给出k个节点,要确定一条路径,使得给出的k个点要么在路径上,要么和路径中某点的…...
c++ 线程
在 C 中,std::thread 构造函数可以用于将参数传递给线程。这里是一个基本的示例,展示了如何使用 std::thread 来传递参数: #include <iostream> #include <thread>// 定义一个被线程调用的函数 void threadFunc(int arg1, doubl…...
【SpringBoot】URL映射之consumes和produces匹配、params和header匹配
4.2.3 consumes和produces匹配 //处理request Content-Type为"application/json"类型的请求 RequestMapping(value"/Content",methodRequestMethod.POST,consumes"application/json") public String Consumes(RequestBody Map param){ return…...

RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...

AI语音助手的Python实现
引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...
go 里面的指针
指针 在 Go 中,指针(pointer)是一个变量的内存地址,就像 C 语言那样: a : 10 p : &a // p 是一个指向 a 的指针 fmt.Println(*p) // 输出 10,通过指针解引用• &a 表示获取变量 a 的地址 p 表示…...
uniapp 实现腾讯云IM群文件上传下载功能
UniApp 集成腾讯云IM实现群文件上传下载功能全攻略 一、功能背景与技术选型 在团队协作场景中,群文件共享是核心需求之一。本文将介绍如何基于腾讯云IMCOS,在uniapp中实现: 群内文件上传/下载文件元数据管理下载进度追踪跨平台文件预览 二…...

认识CMake并使用CMake构建自己的第一个项目
1.CMake的作用和优势 跨平台支持:CMake支持多种操作系统和编译器,使用同一份构建配置可以在不同的环境中使用 简化配置:通过CMakeLists.txt文件,用户可以定义项目结构、依赖项、编译选项等,无需手动编写复杂的构建脚本…...
uniapp 集成腾讯云 IM 富媒体消息(地理位置/文件)
UniApp 集成腾讯云 IM 富媒体消息全攻略(地理位置/文件) 一、功能实现原理 腾讯云 IM 通过 消息扩展机制 支持富媒体类型,核心实现方式: 标准消息类型:直接使用 SDK 内置类型(文件、图片等)自…...
上位机开发过程中的设计模式体会(1):工厂方法模式、单例模式和生成器模式
简介 在我的 QT/C 开发工作中,合理运用设计模式极大地提高了代码的可维护性和可扩展性。本文将分享我在实际项目中应用的三种创造型模式:工厂方法模式、单例模式和生成器模式。 1. 工厂模式 (Factory Pattern) 应用场景 在我的 QT 项目中曾经有一个需…...