Android studio学习之路(八)---Fragment碎片化页面的使用
fragment的用法很常见,你可能经常看见这样的画面:
通过滑动来进行切换页面,今天我们就来实现这样的形式
介绍
使用 Fragment 的核心价值在于 模块化设计 和 动态适配能力,尤其适合以下场景:
需要复用界面组件。
适配不同屏幕尺寸(手机/平板)。
管理复杂界面生命周期。
结合 Jetpack 组件构建现代化架构。
掌握 Fragment 的使用,可以显著提升代码可维护性和用户体验。
模块化与代码复用
1.场景:
当需要将界面拆分为多个独立功能块(如新闻列表 + 详情页)时,每个功能块可以用 Fragment 实现。
23优势:
复用性:同一 Fragment 可在多个 Activity 中重复使用(如登录模块)。
解耦性:将界面逻辑分离到 Fragment,Activity 仅负责整体协调。
动态界面适配
3.场景:
在手机和平板上,同一功能可能需要不同布局(如手机单窗 vs 平板多窗)。
4.优势:
响应式设计:通过配置不同布局文件(如 res/layout-sw600dp),自动切换 Fragment 组合。
运行时调整:根据屏幕方向或窗口大小动态增减 Fragment。
何时不使用 Fragment?
简单界面:单一静态界面直接使用 Activity。
性能敏感场景:频繁动态切换 Fragment 可能影响性能,需谨慎设计。
OK,我们接下来实现代码
初级的代码形式(解释都放在注释里了)
我们今天的代码都是通过动态形式进行实现的,相对与静态,动态的随用随加载的形式更有利于减少内存,提高运行效率:
首先我们需要给页面中的信息的属性进行一个初始化(这里我们可以去找几张手机的图片和文本信息,这次我们做一个类似于淘宝中产品介绍的页面)
GoodsInfo.java
package com.example.tttplean;import com.example.tttplean.R;import java.util.ArrayList;
import java.util.List;public class GoodsInfo {public long rowid; // 行号public int xuhao; // 序号public String name; // 名称public String desc; // 描述public float price; // 价格public String pic_path; // 大图的保存路径public int pic; // 大图的资源编号public GoodsInfo() {rowid = 0L;xuhao = 0;name = "";desc = "";price = 0;pic_path = "";pic = 0;}// 声明一个手机商品的名称数组private static String[] mNameArray = {"iPhone11", "Mate30", "小米10", "OPPO Reno3", "vivo X30", "荣耀30S"};// 声明一个手机商品的描述数组private static String[] mDescArray = {"Apple iPhone11 256GB 绿色 4G全网通手机","华为 HUAWEI Mate30 8GB+256GB 丹霞橙 5G全网通 全面屏手机","小米 MI10 8GB+128GB 钛银黑 5G手机 游戏拍照手机","OPPO Reno3 8GB+128GB 蓝色星夜 双模5G 拍照游戏智能手机","vivo X30 8GB+128GB 绯云 5G全网通 美颜拍照手机","荣耀30S 8GB+128GB 蝶羽红 5G芯片 自拍全面屏手机"};// 声明一个手机商品的价格数组private static float[] mPriceArray = {6299, 4999, 3999, 2999, 2998, 2399};// 声明一个手机商品的大图数组private static int[] mPicArray = {R.drawable.iphone, R.drawable.huawei, R.drawable.xiaomi,R.drawable.oppo, R.drawable.vivo, R.drawable.rongyao};// 获取默认的手机信息列表public static List<GoodsInfo> getDefaultList() {List<GoodsInfo> goodsList = new ArrayList<GoodsInfo>();for (int i = 0; i < mNameArray.length; i++) {GoodsInfo info = new GoodsInfo();info.name = mNameArray[i];info.desc = mDescArray[i];info.price = mPriceArray[i];info.pic = mPicArray[i];goodsList.add(info);}return goodsList;}}
接下来,我们对手机的页面的图片显示做一个适配:
MobilePagerAdapter.java:
package com.example.tttplean;import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;import com.example.tttplean.GoodsInfo;
import com.example.tttplean.DynamicFragment;import java.util.ArrayList;
import java.util.List;
public class MobilePagerAdapter extends FragmentPagerAdapter{private List<GoodsInfo> mGoodsList = new ArrayList<GoodsInfo>(); // 声明一个商品列表// 碎片页适配器的构造方法,传入碎片管理器与商品信息列表public MobilePagerAdapter(FragmentManager fm, List<GoodsInfo> goodsList) {super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);mGoodsList = goodsList;}// 获取碎片Fragment的个数public int getCount() {return mGoodsList.size();}// 获取指定位置的碎片Fragmentpublic Fragment getItem(int position) {return DynamicFragment.newInstance(position,mGoodsList.get(position).pic, mGoodsList.get(position).desc);}// 获得指定碎片页的标题文本public CharSequence getPageTitle(int position) {return mGoodsList.get(position).name;}
}
接下来,我们来对fragment的属性与性质进行初始化与设定
DynamicFragment.java(并非activity)
package com.example.tttplean;import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;import androidx.fragment.app.Fragment;import com.example.tttplean.R;public class DynamicFragment extends Fragment {private static final String TAG = "DynamicFragment";protected View mView; // 声明一个视图对象protected Context mContext; // 声明一个上下文对象private int mPosition; // 位置序号private int mImageId; // 图片的资源编号private String mDesc; // 商品的文字描述// 获取该碎片的一个实例public static DynamicFragment newInstance(int position, int image_id, String desc) {DynamicFragment fragment = new DynamicFragment(); // 创建该碎片的一个实例Bundle bundle = new Bundle(); // 创建一个新包裹bundle.putInt("position", position); // 往包裹存入位置序号bundle.putInt("image_id", image_id); // 往包裹存入图片的资源编号bundle.putString("desc", desc); // 往包裹存入商品的文字描述fragment.setArguments(bundle); // 把包裹塞给碎片return fragment; // 返回碎片实例}// 创建碎片视图public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {mContext = getActivity(); // 获取活动页面的上下文if (getArguments() != null) { // 如果碎片携带有包裹,就打开包裹获取参数信息mPosition = getArguments().getInt("position", 0); // 从包裹取出位置序号mImageId = getArguments().getInt("image_id", 0); // 从包裹取出图片的资源编号mDesc = getArguments().getString("desc"); // 从包裹取出商品的文字描述}// 根据布局文件fragment_dynamic.xml生成视图对象mView = inflater.inflate(R.layout.fragment_dynamic, container, false);ImageView iv_pic = mView.findViewById(R.id.iv_pic);TextView tv_desc = mView.findViewById(R.id.tv_desc);iv_pic.setImageResource(mImageId);tv_desc.setText(mDesc);Log.d(TAG, "onCreateView position=" + mPosition);return mView; // 返回该碎片的视图对象}@Overridepublic void onAttach(Activity activity) { // 把碎片贴到页面上super.onAttach(activity);Log.d(TAG, "onAttach position=" + mPosition);}@Overridepublic void onCreate(Bundle savedInstanceState) { // 页面创建super.onCreate(savedInstanceState);Log.d(TAG, "onCreate position=" + mPosition);}@Overridepublic void onDestroy() { // 页面销毁super.onDestroy();Log.d(TAG, "onDestroy position=" + mPosition);}@Overridepublic void onDestroyView() { // 销毁碎片视图super.onDestroyView();Log.d(TAG, "onDestroyView position=" + mPosition);}@Overridepublic void onDetach() { // 把碎片从页面撕下来super.onDetach();Log.d(TAG, "onDetach position=" + mPosition);}@Overridepublic void onPause() { // 页面暂停super.onPause();Log.d(TAG, "onPause position=" + mPosition);}@Overridepublic void onResume() { // 页面恢复super.onResume();Log.d(TAG, "onResume position=" + mPosition);}@Overridepublic void onStart() { // 页面启动super.onStart();Log.d(TAG, "onStart position=" + mPosition);}@Overridepublic void onStop() { // 页面停止super.onStop();Log.d(TAG, "onStop position=" + mPosition);}@Overridepublic void onActivityCreated(Bundle savedInstanceState) { //在活动页面创建之后super.onActivityCreated(savedInstanceState);Log.d(TAG, "onActivityCreated position=" + mPosition);}}
页面的设计
fragment_dynamic.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><ImageViewandroid:id="@+id/iv_pic"android:layout_width="match_parent"android:layout_height="360dp"android:scaleType="fitCenter" /><TextViewandroid:id="@+id/tv_desc"android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="left"android:textColor="@color/black"android:textSize="17sp" /></LinearLayout>
接下来,我们创立activity来进行实现操作:
FragmentDynamicActivity.java:
package com.example.tttplean;import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.util.TypedValue;import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager.widget.PagerTabStrip;
import androidx.viewpager.widget.ViewPager;import com.example.tttplean.MobilePagerAdapter;
import com.example.tttplean.GoodsInfo;import java.util.List;public class FragmentDynamicActivity extends AppCompatActivity {private static final String TAG = "FragmentDynamicActivity";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_fragment_dynamic);Log.d(TAG, "onCreate");initPagerStrip(); // 初始化翻页标签栏initViewPager(); // 初始化翻页视图}// 初始化翻页标签栏private void initPagerStrip() {// 从布局视图中获取名叫pts_tab的翻页标签栏PagerTabStrip pts_tab = findViewById(R.id.pts_tab);// 设置翻页标签栏的文本大小pts_tab.setTextSize(TypedValue.COMPLEX_UNIT_SP, 20);// 设置翻页标签栏的文本颜色pts_tab.setTextColor(Color.BLACK);}// 初始化翻页视图private void initViewPager() {List<GoodsInfo> goodsList = GoodsInfo.getDefaultList();// 构建一个手机商品的碎片翻页适配器MobilePagerAdapter adapter = new MobilePagerAdapter(getSupportFragmentManager(), goodsList);// 从布局视图中获取名叫vp_content的翻页视图ViewPager vp_content = findViewById(R.id.vp_content);vp_content.setAdapter(adapter); // 设置翻页视图的适配器vp_content.setCurrentItem(0); // 设置翻页视图显示第一页}@Overrideprotected void onDestroy() {super.onDestroy();Log.d(TAG, "onDestroy");}@Overrideprotected void onStart() {super.onStart();Log.d(TAG, "onStart");}@Overrideprotected void onStop() {super.onStop();Log.d(TAG, "onStop");}@Overrideprotected void onResume() {super.onResume();Log.d(TAG, "onResume");}@Overrideprotected void onPause() {super.onPause();Log.d(TAG, "onPause");}}
activity_fragment_dynamic.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:padding="5dp"><androidx.viewpager.widget.ViewPagerandroid:id="@+id/vp_content"android:layout_width="match_parent"android:layout_height="wrap_content"><androidx.viewpager.widget.PagerTabStripandroid:id="@+id/pts_tab"android:layout_width="wrap_content"android:layout_height="wrap_content" /></androidx.viewpager.widget.ViewPager>
</LinearLayout>
效果图:
通过滑动进行页面的改变。
改善后的代码
改善后的代码,可以启动更快,代码的减少代码的耦合
LaunchImproveAdapter.java
package com.example.tttplean;import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;import com.example.tttplean.LaunchFragment;public class LaunchImproveAdapter extends FragmentPagerAdapter {private int[] mImageArray; // 声明一个图片数组// 碎片页适配器的构造方法,传入碎片管理器与图片数组public LaunchImproveAdapter(FragmentManager fm, int[] imageArray) {super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);mImageArray = imageArray;}// 获取碎片Fragment的个数public int getCount() {return mImageArray.length;}// 获取指定位置的碎片Fragmentpublic Fragment getItem(int position) {return LaunchFragment.newInstance(position, mImageArray[position]);}
}
LaunchFragment.java
package com.example.tttplean;import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Toast;import androidx.fragment.app.Fragment;import com.example.tttplean.R;public class LaunchFragment extends Fragment {protected View mView; // 声明一个视图对象protected Context mContext; // 声明一个上下文对象private int mPosition; // 位置序号private int mImageId; // 图片的资源编号private int mCount = 4; // 引导页的数量// 获取该碎片的一个实例public static LaunchFragment newInstance(int position, int image_id) {LaunchFragment fragment = new LaunchFragment(); // 创建该碎片的一个实例Bundle bundle = new Bundle(); // 创建一个新包裹bundle.putInt("position", position); // 往包裹存入位置序号bundle.putInt("image_id", image_id); // 往包裹存入图片的资源编号fragment.setArguments(bundle); // 把包裹塞给碎片return fragment; // 返回碎片实例}// 创建碎片视图public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {mContext = getActivity(); // 获取活动页面的上下文if (getArguments() != null) { // 如果碎片携带有包裹,就打开包裹获取参数信息mPosition = getArguments().getInt("position", 0); // 从包裹获取位置序号mImageId = getArguments().getInt("image_id", 0); // 从包裹获取图片的资源编号}// 根据布局文件item_launch.xml生成视图对象mView = inflater.inflate(R.layout.item_launch, container, false);ImageView iv_launch = mView.findViewById(R.id.iv_launch);RadioGroup rg_indicate = mView.findViewById(R.id.rg_indicate);Button btn_start = mView.findViewById(R.id.btn_start);iv_launch.setImageResource(mImageId); // 设置引导页的全屏图片// 每个页面都分配一个对应的单选按钮for (int j = 0; j < mCount; j++) {RadioButton radio = new RadioButton(mContext); // 创建一个单选按钮radio.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));radio.setButtonDrawable(R.drawable.launch_guide); // 设置单选按钮的图标radio.setPadding(10, 10, 10, 10); // 设置单选按钮的四周间距rg_indicate.addView(radio); // 把单选按钮添加到页面底部的单选组}// 当前位置的单选按钮要高亮显示,比如第二个引导页就高亮第二个单选按钮((RadioButton) rg_indicate.getChildAt(mPosition)).setChecked(true);// 如果是最后一个引导页,则显示入口按钮,以便用户点击按钮进入首页if (mPosition == mCount - 1) {btn_start.setVisibility(View.VISIBLE);btn_start.setOnClickListener(v -> {// 这里要跳到应用主页Toast.makeText(mContext, "欢迎您开启美好生活", Toast.LENGTH_SHORT).show();});}return mView; // 返回该碎片的视图对象}
}
xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><!-- 这是引导图片的图像视图 --><ImageViewandroid:id="@+id/iv_launch"android:layout_width="match_parent"android:layout_height="match_parent"android:scaleType="fitXY" /><!-- 这里容纳引导页底部的一排圆点 --><RadioGroupandroid:id="@+id/rg_indicate"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_centerHorizontal="true"android:orientation="horizontal"android:paddingBottom="20dp" /><!-- 这是最后一页的入口按钮 --><Buttonandroid:id="@+id/btn_start"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:text="立即开始美好生活"android:textColor="#ff3300"android:textSize="22sp"android:visibility="gone" />"
</RelativeLayout>
LaunchImproveActivity.java
package com.example.tttplean;import android.os.Bundle;import androidx.appcompat.app.AppCompatActivity;
import androidx.viewpager.widget.ViewPager;import com.example.tttplean.LaunchImproveAdapter;public class LaunchImproveActivity extends AppCompatActivity {// 声明引导页面的图片数组private int[] lanuchImageArray = {R.drawable.guide_bg1,R.drawable.guide_bg2, R.drawable.guide_bg3, R.drawable.guide_bg4};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_launch_improve);// 从布局视图中获取名叫vp_launch的翻页视图ViewPager vp_launch = findViewById(R.id.vp_launch);// 构建一个引导页面的碎片翻页适配器LaunchImproveAdapter adapter = new LaunchImproveAdapter(getSupportFragmentManager(), lanuchImageArray);vp_launch.setAdapter(adapter); // 设置翻页视图的适配器vp_launch.setCurrentItem(0); // 设置翻页视图显示第一页}
}
xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><androidx.viewpager.widget.ViewPagerandroid:id="@+id/vp_launch"android:layout_width="match_parent"android:layout_height="match_parent" /></LinearLayout>
效果图:
这里给予每个页面都有了表示和按钮,而且在最后一个页面中才会出现跳转页面的按钮:
尾言:
本次的更新还是非常有用的,在我见到的项目APP中几乎都离不开这个功能,所以非常建议大家去学习一下。我也会把代码放在资源库中供大家下载。
相关文章:
Android studio学习之路(八)---Fragment碎片化页面的使用
fragment的用法很常见,你可能经常看见这样的画面: 通过滑动来进行切换页面,今天我们就来实现这样的形式 介绍 使用 Fragment 的核心价值在于 模块化设计 和 动态适配能力,尤其适合以下场景: 需要…...
数据结构和算法(九)--红黑树
一、红黑树 1、红黑树 前面介绍了2-3树,可以看到2-3树能保证在插入元素之后,树依然保持平衡状态,它的最坏情况下所有子结点都是2-结点,树的高度为IgN,相比于我们普通的二叉查找树,最坏情况下树的高度为N,确…...
字节跳动开源数字人模型latentsync1.5,性能、质量进一步优化~
项目背景 LatentSync1.5 是由 ByteDance 开发的一款先进的 AI 模型,专门针对视频唇同步(lip synchronization)任务设计,旨在实现音频与视频唇部动作的高质量、自然匹配。随着 AI 技术的快速发展,视频生成和编辑的需求…...
Pygame入门:零基础打造你的第一个游戏窗口
Pygame入门:零基础打造你的第一个游戏窗口 大家好,欢迎来到本期的技术分享!今天,我们将一起探索如何使用Python中的Pygame库来创建一个简单的游戏窗口。无论你是编程新手,还是对游戏开发感兴趣的朋友,这篇文章都将帮助你迈出第一步。让我们开始吧! 什么是Pygame? 在…...
《ATPL地面培训教材13:飞行原理》——第13章:高速飞行
翻译:刘远贺;工具:Cursor & Cluade 3.7;过程稿 第13章:高速飞行 目录 引言声速马赫数恒定指示空速爬升对马赫数的影响恒定马赫数下真空速随高度的变化恒定飞行高度和指示空速下温度对马赫数的影响气动流动的细分…...
【C语言练习】004. 使用各种运算符进行计算
【C语言练习】004. 使用各种运算符进行计算 004. 使用各种运算符进行计算1. 算术运算符2. 关系运算符3. 逻辑运算符4. 位运算符5. 赋值运算符6. 逗号运算符综合示例输出结果004. 使用各种运算符进行计算 在C语言中,运算符用于执行各种数学和逻辑运算。以下是一些常见的运算符…...
Pygame事件处理详解:键盘、鼠标与自定义事件
Pygame事件处理详解:键盘、鼠标与自定义事件 在游戏开发中,玩家的交互是至关重要的。无论是移动角色、触发动作还是暂停游戏,都需要通过各种输入来实现。Pygame作为一个功能强大的Python库,提供了丰富的API来处理这些输入,包括键盘、鼠标以及自定义事件。本文将详细介绍如…...
16. LangChain自主智能体(Autonomous Agent):模拟人类工作流的进阶设计
引言:当AI学会"思考"与"行动" 2025年某跨国律所的合同审查智能体,通过自主规划任务流,将平均处理时间从8小时缩短至23分钟。本文将基于LangChain的AgentExecutor与Deepseek-R1,揭示如何构建能自主决策、动态…...
直接映射例题及解析
目录 基本单位换算 例题一 📁 Tag Directory(标签目录) 是什么? 例题二 例题三 例题四 串行访问还是并行访问的选择 例题五 例题六 例题七 🔵 P1:(按行访问) …...
MAVLink协议:原理、应用与实践
目录 1. 前言 2. MAVLink 协议的基本概念 2.1 协议概述 2.2 消息格式 2.3 协议版本 3. MAVLink 协议的适应场景 3.1 无人机地面站与飞行器通信 3.2 飞行器与传感器通信 3.3 无人机集群通信 3.4 飞行模拟与测试 4. 基于 Python 的 MAVLink 协议编程实践 4.1 开发环境…...
【记一次亚马逊普华永道审计流程】
1、2025年2月21日 收到审计邮件 2、2025年2月25日未及时关注注册开发者的邮箱导致一直未回复 3、2025年3月4日亚马逊警告邮件-依旧未回复 4、2025年3月13日APP正式被亚马逊开发者商店下架 停用影响: APP从官方商店下架,不能授权新店铺 停用原因: 由于此邮箱为注册…...
Java 异常处理全解析:从基础到自定义异常的实战指南
Java 异常处理全解析:从基础到自定义异常的实战指南 一、Java 异常体系:Error 与 Exception 的本质区别 1. 异常体系核心架构 Java把异常当作对象来处理,并定义一个基类java.lang.Throwable作为所有异常的超类。 在Java API中已经定义了许…...
二、UI自动化测试02--元素定位方法
目录 一、定位⼀组元素⽅法二、XPath 定位⽅法1. 路径策略1.1 路径值获取⽅法 2. 利⽤元素属性策略利⽤元素属性策略的注意事项 3. 属性和逻辑结合4. 层级和属性结合策略5. XPath 延伸⽅法 三、CSS 定位⽅法1. CSS 策略: id选择器/class选择器/元素选择器/属性选择器2. 属性选择…...
第二章 信息技术发展(2.1 信息技术及其发展)
2.1 信息技术及其发展 2.1.1 计算机软硬件 计算机硬件 (Computer Hardware) 是指计算机系统中由电 、机械和光电元件等组成 的各 种物理装置的总称计算机软件 (Computer Software) 是指计算机系统中的程序及其文档,程序是计 算任务的处理对象和处理规则的描述;文档是为了便千…...
【SwitchyOmega安装教程】
目录 一、插件安装 1. 下载安装文件 2. 打开浏览器扩展安装页面 3. 安装插件 二、界面详情 三、配置信息 3.1 设置IP 1、查看IP地址信息 2、批量测试IP是否有效 3、点击扩展程序,选择 Proxy SwitchyOmega 4、 点击选项进行配置 5、配置页面 一、插件安装 1…...
驱动开发硬核特训 · Day 21(上篇加强版):深入理解子系统机制与实战初探
📅 日期:2025-04-27 📚 技术平台:嵌入式Jerry(B站) 1. 为什么要有子系统?(深度版) 在 Linux 内核发展早期,设备管理较为混乱,每种设备࿰…...
GoFly快速开发框架新增UI素材库-帮助开发者快速开发管理后台UI基于ArcoDesign框架开发
说明: 为开发者提供管理台的UI素材,社区将持续为开发开发后台系统常用UI界面,让开发时能有一半的界面可以直接从UI库获取,减少开发者自己排版界面的时间,帮助开发者快速开发后台业务。 使用的前端版本要求࿱…...
Unity-Shader详解-其二
前向渲染和延迟渲染 前向渲染和延迟渲染总的来说是我们的两种主要的渲染方式。 我们在Unity的Project Settings中的Graphic界面能够找到渲染队列的设定: 我们也可以在Main Camera这里进行设置: 那这里我们首先介绍一下两种渲染(Forward R…...
Windows 安装 Neo4j 教程
Windows 安装 Neo4j 教程 Neo4j 是一个开源的图数据库,它以图形结构存储数据,适合用于处理高度连接的数据,广泛应用于社交网络、推荐系统、欺诈检测等场景。本文将为你介绍如何在 Windows 系统上安装和配置 Neo4j 数据库。 一、安装前准备 …...
Neo4j 常用查询语句
Neo4j 常用查询语句 Neo4j 是一个图数据库,查询语言是 Cypher,它类似于 SQL 但针对图形数据进行了优化。Cypher 语法直观易懂,适合用来处理图数据。本文将介绍一些 Neo4j 中常用的查询语句,帮助你快速掌握图数据的操作方法。 一…...
机器学习(10)——神经网络
文章目录 1. 神经网络基本原理1.1. 什么是神经网络1.2. 核心思想 2. 基础组件3. 前向传播(Forward Propagation)4. 反向传播(Backpropagation)5. 激活函数对比6. 网络架构类型7. 优化策略8. Python示例(PyTorch&#x…...
Qt软件开发-摄像头检测使用软件V1.1
系列文章目录 Qt软件开发-摄像头检测使用软件V1.1 文章目录 系列文章目录前言一、V1.1增加了哪些功能?二、代码构成1.总体结构2. 代码内容 三、效果展示图总结 前言 之前,在Qt软件开发-摄像头检测使用软件:https://blog.csdn.net/xuming204…...
AI日报 - 2025年04月26日
🌟 今日概览(60秒速览) ▎🤖 模型竞赛 | OpenAI与Google新模型在Arena榜单激烈角逐,性能指标各有千秋。 OpenAI发布o3/o4-mini等新模型,Gemini 2.5 Pro紧随其后,数学、编程能力成焦点。 ▎💼 商业动向 | 并…...
ES6 Map/WeakMap/Set/WeakSet 全解指南
一、设计思想与核心概念 1. 解决传统结构的痛点 Object:键只能是字符串/Symbol、无序、无size属性Array:查找效率低(O(n))、无自动去重机制核心突破:// 传统方式 vs ES6方式 const obj { [{}]: value }; // 键会被转为"[object Obje…...
【Python】使用uv管理python虚拟环境
本文介绍了python虚拟环境管理工具uv,包括uv的作用、uv的常用命令等等。 参考:UV - 管理Python 版本、环境、第三方包 1. 介绍uv 官网:https://docs.astral.sh/uv/ uv是一个python虚拟环境管理工具,可以用来替代pip、pyenv、vir…...
求解,如何控制三相无刷电机?欢迎到访评论
问题:通过一个集成的TF2104芯片控制H桥上桥臂和下桥臂,如何控制?还是说得需要PWM_UH和PWM_UL分开控制?...
002 六自由度舵机机械臂——姿态解算理论
00 DH模型的核心概念 【全程干货【六轴机械臂正逆解计算及仿真示例】】 如何实现机械臂的逆解计算-机器谱-robotway DH模型是机器人运动学建模的基础方法,通过四个参数描述相邻关节坐标系之间的变换关系。其核心思想是将复杂的空间位姿转换分解为绕轴旋转…...
部署大模型需要多少GPU显存?以DeepSeek R1部署为例
引言 部署大型语言模型(LLM)时究竟需要多少GPU显存?本文将进行一次简单测算。 如何计算 算法1 可以用一个简单的公式来计算显存占用(单位GB): 参数说明如下: 符号 含义 M 所需的 GPU 显存…...
C++?类和对象(下)!!!
一、前言 在之前我们已经讨论过了有关类和对象的前置知识以及类中的六大默认成员函数,在本期我们继续再讨论类和对象中剩余的友元、初始化列表等相关知识,如果需要再了解之前的知识的话,链接奉上:C?类和对象࿰…...
function,bind,lambda的用法
C中的std::function、std::bind与Lambda表达式详解 一、std::function std::function是C11标准引入的类模板,用于封装任意类型的可调用对象,例如函数指针、Lambda表达式、函数对象等。通过std::function可以实现不同形式可调用对象的统一存储与调用…...
Maven的聚合工程与继承
目录 一、为什么需要使用Maven工程 二、聚合工程的结构 三、聚合工程实现步骤 四、父工程统一管理版本 五、编译打包 大家好,我是jstart千语。想着平时开发项目似乎都是用maven来管理的,并且大多都是聚合工程。而且在maven的聚合工程中,…...
C/C++对时间的处理
1. 两种数据结构 time_t 是一个在C和C++编程语言中用于表示时间的类型。time_t类型通常是一个长整型(long int)或整数类型,用于表示从特定参考点(通常是1970年1月1日00:00:00 UTC)经过的秒数。 time_t定义在<ctime>头文件中,通常用于记录时间戳,比如获取当前时间…...
Spring Boot 支持政策
🧑💻 Spring Boot 支持政策 ✒️ Andy Wilkinson 于2023年12月7日编辑本页 32次修订 📌 核心政策 🛡️ VMware Tanzu 开源支持政策 Spring Boot 针对关键错误和安全问题提供支持 📆 版本支持周期 1️⃣ 主要版本&a…...
实验四 进程调度实验
一、实验目的 1、了解操作系统CPU管理的主要内容。 2、加深理解操作系统管理控制进程的数据结构--PCB。 3、掌握几种常见的CPU调度算法(FCFS、SJF、HRRF、RR)的基本思想和实现过程。 4、用C语言模拟实现CPU调度算法。 5、掌握CPU调度算法性能评价指…...
静态多态和动态多态的区别
C多态机制深度解析 多态是面向对象编程的核心特性,允许通过统一接口执行不同实现。在C中,多态表现为基类指针或引用调用虚函数时,根据实际对象类型执行对应派生类的函数逻辑。 基础实现示例 定义基类与派生类,演示动态绑定…...
现代化Android开发:Compose提示信息的最佳封装方案
在 Android 开发中,良好的用户反馈机制至关重要。Jetpack Compose 提供了现代化的 UI 构建方式,但提示信息(Toast/Snackbar)的管理往往显得分散。本文将介绍如何优雅地封装提示信息,提升代码可维护性。 一、基础封装方案 1. 简单 Snackbar …...
Android学习总结之Retrofit篇
1. 注解原理概述 在 Java 里,注解是一种元数据,它为代码提供额外信息但不影响程序的实际逻辑。注解可以在类、方法、字段等元素上使用,并且能在编译时、运行时通过反射机制被读取。Retrofit 充分利用了 Java 注解机制,通过自定义…...
Python 第 12、13 节课 - 元组和列表
- 第 94 篇 - Date: 2025 - 04 - 26 Author: 郑龙浩/仟墨 【Python 在校课堂笔记】 Python 第 12、13 节课 - 元组和列表 上课时间: 2025-04-21(12) 2025-04-24(13) 文章目录 Python 第 12、13 节课 - 元组和列表一 元组1 元组的…...
新特性版本升级指引
✨ 升级到新特性版本时的配置迁移 1️⃣ 🔧 配置迁移工具说明 当您将应用升级到新特性版本时,可能需要处理部分配置属性的重命名或移除问题。 2️⃣ 🚀 启用方法 Spring Boot 提供了环境分析工具: 应用启动时打印诊断信息运行时…...
6.1 客户服务:智能客服与自动化支持系统的构建
随着企业数字化转型的加速,客户服务作为企业与用户交互的核心环节,正经历从传统人工服务向智能化、自动化服务的深刻变革。基于大语言模型(LLM)和智能代理(Agent)的技术为构建智能客服与自动化支持系统提供…...
从新手到高手:小程序开发进阶技巧分享
小程序开发从入门到精通需要经历技术积累、架构优化和工程化实践等多个阶段。以下是结合真实项目经验的进阶路线与核心技术要点,涵盖性能优化、架构设计、跨平台开发等关键领域: 一、性能调优实战技巧 1. 首屏渲染加速方案 // 预请求关键数据ÿ…...
S参数的含义
S参数的含义: 在低速设计时代,工程界普遍使用等效集总电路模型来描述互连通道的过孔、连接器等各部分。对于上升时间达到几个ns的低速数字信号,甚至可以使用一个0Ω电阻代替连接器,分析的结果也不会和实际情况有太大的差别。但是当…...
职场十二法则-马方
马方老师的《职场十二法则》,献给初入职场工作中迷茫的自己。 1.挣钱是能力的副产品,能力比挣钱重要,让自己值钱比有钱更重要。成长比赚钱重要,年轻时把成长放第一位,挣钱放第二位,通过提升能力实现长期收益。 2.成长…...
安装docker,在docker上安装mysql,docker上安装nginx
目录 一.安装docker 1.1查看Linux版本的命令这里推荐两种: 1.2查看内核版本有三种方式: 2.安装 2.1 如果之前安装了docker,先删除旧版本的doker 2.2 安装需要的软件包,yum-util提供yum-config-manager功能,另外两…...
Java基础第五章、面向对象程序设计
1.package包 如果引入的不同包里面有相同的类名时,需要对要使用的类进行完整的限定名指定。 2.访问修饰符 子类对父类的方法重写也遵循上面的原则 一个java文件中最多只能有一个public(和文件同名)的类。 3.初始化块 //Driver.java public class Driver {private lo…...
RD电子实验记录本选用贴士A-B-C
传统的实验记录本,令人又爱又恨本 如何挑选电子实验室记录本(ELN)的品牌/服务商/供应商? 电子实验记录本,又名为ELN,Electronic lab notebook,enotebook,研发电子管理系统…...
Python 第 11 节课 - string 与 random 的方法
- 第 93 篇 - Date: 2025 - 04 - 26 Author: 郑龙浩/仟墨 【Python 在校课堂笔记】 Python 第 11 节课 - string 与 random 的方法 上课时间: 2025-04-14 文章目录 Python 第 11 节课 - string 与 random 的方法一 string 的方法1 s.split()2 s.find()3 s.replace()4 s.strip…...
proxychains4系统代理for linux(加速国内github下载速度,pip安装)
1.proxychains4代理安装: sudo apt-get install proxychains42.找到配置文件/etc/proxychains4.conf在[ProxyList]后面添加以下内容: socks5 127.0.0.1 10808 配置如下: 3.使用proxychains4(git clone): proxychains4 git c…...
LLM基础之源码一
transformers 核心源码梳理 Trainer部分: __init__() 初始化函数: def __init__(xxx):if args is None:output_dir "tmp_trainer"args TrainingArguments(output_diroutput_dir) self.args argsself.compute_loss_func compute_loss_fun…...
蛮荒tv桌面永不升级版app下载-蛮荒桌面安卓电视版下载
蛮荒桌面是一款具有丰富桌面内容的生活应用软件,可以连接电视上使用,用户将需要的软件添加到桌面上,系统就会自动分类管理软件,小编今天为大家推荐一款功能更大强大的电视桌面应用——乐看家桌面。 乐看家桌面功能亮点: 1.官网下载刷入机顶盒…...