当前位置: 首页 > news >正文

Android APP 基于RecyclerView框架工程(知识体系积累)

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


1 基于RecyclerView框架工程实现原理说明

该工程通过config.xml配置文件获取每一个网格中的基本信息,并将其存储到itemlist中。应用启动后,点击网格中的按键,每个按键可以按需启动一个应用。适用于长期积累自己的知识体系。

接下来直接上干货,粘过去可以直接用的那种~。平台是基于Android12的。

框架工程代码完整解读(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框架工程(知识体系积累)

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

【iOS】GCD

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

C语言 | Leetcode C语言题解之第282题给表达式添加运算符

题目&#xff1a; 题解&#xff1a; #define MAX_COUNT 10000 // 解的个数足够大 #define NUM_COUNT 100 // 操作数的个数足够大 long long num[NUM_COUNT] {0};long long calc(char *a) { // 计算表达式a的值// 将数字和符号&#xff0c;入栈memset(num, 0, sizeof(num));in…...

如何使用 API list 极狐GitLab 容器镜像仓库中的 tag?

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab &#xff1a;https://gitlab.cn/install?channelcontent&utm_sourcecsdn 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署…...

粒子群算法PSO优化BP神经网络(PSO-BP)回归预测——Python和MATLAB实现

下面是一个使用Python实现的粒子群算法&#xff08;PSO&#xff09;优化反向传播神经网络&#xff08;BP&#xff09;的示例代码。 以下是具体的代码实现&#xff1a; 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编程设计学习视频&#xff0c;从入门开始讲解_哔哩哔哩_bilibili...

linux系统查历史cpu使用数据(使用sar 查询cpu和网络占用最近1个月历史数据)。

一 sar 指令介绍 在 Linux 系统中&#xff0c;sar 是 System Activity Reporter 的缩写&#xff0c;是一个用于收集、报告和保存系统活动信息的工具。它是 sysstat 软件包的一部分&#xff0c;提供了丰富的系统性能数据&#xff0c;包括 CPU、内存、网络、磁盘等使用情况&am…...

Edge浏览器加载ActiveX控件

背景介绍 新版Edge浏览器也是采用Chromium内核&#xff0c;虽然没有谷歌浏览器市场占有率高&#xff0c;但是依托微软操作系统的优势&#xff0c;Edge浏览器还是发展很强劲&#xff0c;占据着市场第二的位置。随着微软停止服务IE浏览器&#xff0c;曾经风光无限的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留言&#xff1a; Blue的推荐&#xff1a; 什么是poi库&#xff1f; 实现动态替换 第一步&#xff1a;依赖 第二步&#xff1a;实现word模板中替换文字 模板word&#xff1a; 通过以下代码&#xff1a;&#xff08;自己建一个类&#xff0c;随意取名&#xf…...

机器人开源调度系统OpenTcs6二开-车辆表定义

前面已经知道opentcs 需要车辆的模型结构数据&#xff0c;将里面的数据结构化&#xff0c;已表的形式生成&#xff0c;再找一个开源的基础框架项目对车辆进行增删改的管理 表结构&#xff1a; CREATE TABLE Vehicle (id INT AUTO_INCREMENT PRIMARY KEY COMMENT 唯一标识符,n…...

麦歌恩MT6521-第三代汽车磁性角度传感器芯片

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

【数据结构】堆,优先级队列

目录 堆堆的性质大根堆的模拟实现接口实现构造方法建堆入堆判满删除判空获取堆顶元素 Java中的PriorityQueue实现的接口构造方法常用方法PriorityQueue注意事项 练习 堆 如果有一个集合K {k0&#xff0c;k1&#xff0c; k2&#xff0c;…&#xff0c;kn-1}&#xff0c;把它的…...

2024 暑假友谊赛 2

Tree Queries - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 思路:LCA好题&#xff0c;也有看见用时间戳写的&#xff0c;不是很明白. 用LCA非常好写。 要想到,给出k个节点&#xff0c;要确定一条路径&#xff0c;使得给出的k个点要么在路径上&#xff0c;要么和路径中某点的…...

c++ 线程

在 C 中&#xff0c;std::thread 构造函数可以用于将参数传递给线程。这里是一个基本的示例&#xff0c;展示了如何使用 std::thread 来传递参数&#xff1a; #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…...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

汽车生产虚拟实训中的技能提升与生产优化​

在制造业蓬勃发展的大背景下&#xff0c;虚拟教学实训宛如一颗璀璨的新星&#xff0c;正发挥着不可或缺且日益凸显的关键作用&#xff0c;源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例&#xff0c;汽车生产线上各类…...

oracle与MySQL数据库之间数据同步的技术要点

Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异&#xff0c;它们的数据同步要求既要保持数据的准确性和一致性&#xff0c;又要处理好性能问题。以下是一些主要的技术要点&#xff1a; 数据结构差异 数据类型差异&#xff…...

在 Spring Boot 项目里,MYSQL中json类型字段使用

前言&#xff1a; 因为程序特殊需求导致&#xff0c;需要mysql数据库存储json类型数据&#xff0c;因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...

【堆垛策略】设计方法

堆垛策略的设计是积木堆叠系统的核心&#xff0c;直接影响堆叠的稳定性、效率和容错能力。以下是分层次的堆垛策略设计方法&#xff0c;涵盖基础规则、优化算法和容错机制&#xff1a; 1. 基础堆垛规则 (1) 物理稳定性优先 重心原则&#xff1a; 大尺寸/重量积木在下&#xf…...

算法—栈系列

一&#xff1a;删除字符串中的所有相邻重复项 class Solution { public:string removeDuplicates(string s) {stack<char> st;for(int i 0; i < s.size(); i){char target s[i];if(!st.empty() && target st.top())st.pop();elsest.push(s[i]);}string ret…...

Springboot 高校报修与互助平台小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;高校报修与互助平台小程序被用户普遍使用&#xff0c;为…...

STL 2迭代器

文章目录 1.迭代器2.输入迭代器3.输出迭代器1.插入迭代器 4.前向迭代器5.双向迭代器6.随机访问迭代器7.不同容器返回的迭代器类型1.输入 / 输出迭代器2.前向迭代器3.双向迭代器4.随机访问迭代器5.特殊迭代器适配器6.为什么 unordered_set 只提供前向迭代器&#xff1f; 1.迭代器…...

第2课 SiC MOSFET与 Si IGBT 静态特性对比

2.1 输出特性对比 2.2 转移特性对比 2.1 输出特性对比 器件的输出特性描述了当温度和栅源电压(栅射电压)为某一具体数值时,漏极电流(集电极电流...

Qt 按钮类控件(Push Button 与 Radio Button)(1)

文章目录 Push Button前提概要API接口给按钮添加图标给按钮添加快捷键 Radio ButtonAPI接口性别选择 Push Button&#xff08;鼠标点击不放连续移动快捷键&#xff09; Radio Button Push Button 前提概要 1. 之前文章中所提到的各种跟QWidget有关的各种属性/函数/方法&#…...