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

【Android】碎片—动态添加、创建Fragment生命周期、通信

简单用法

在一个活动中添加两个碎片,并让这两个碎片平分活动空间

先新建一个左侧碎片布局和一个右侧碎片布局

左侧碎片

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"><Buttonandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:text="Button"/></LinearLayout>

右侧碎片

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:background="#00ff00"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:textSize="20sp"android:text="这是文本"/></LinearLayout>

然后新建一个LeftFragment类和一个RightFragment类继承Fragment

package com.example.fragmentpractice;import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;public class LeftFragment extends Fragment {@Nullable@Overridepublic View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {View view = inflater.inflate(R.layout.left_fragment, container, false);return view;}
}
package com.example.fragmentpractice;import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;public class RightFragment extends Fragment {@Nullable@Overridepublic View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {View view = inflater.inflate(R.layout.right_fragment, container, false);return view;}
}

修改activity_main

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="horizontal"><fragmentandroid:id="@+id/left_fragment"android:name="com.example.fragmentpractice.LeftFragment"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"/><fragmentandroid:id="@+id/right_fragmgent"android:name="com.example.fragmentpractice.RightFragment"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1" /></LinearLayout>

使用了<fragment>添加碎片,需要用android:name属性来显示指明要添加的碎片类名

动态添加碎片

步骤

  1. 创建待添加的碎片实例
  2. 获取FragmentManager,在活动中可直接通过调用getSupportFragmentManager()方法得到
  3. 开启一个事务,通过调用beginTransaction()方法开启
  4. 向容器内添加或替换碎片,一般使用replace()方法实现,需要传入容器的id和待添加的碎片实例
  5. 提交事务,调用commit()方法来完成

代码

新建another_rigth_fragment

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:background="#ffff00"android:layout_width="match_parent"android:layout_height="match_parent"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center_horizontal"android:textSize="20sp"android:text="这是另一个文本"/></LinearLayout>

创建AnotherRightFragment(和之前的操作一样)

package com.example.fragmentpractice;import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;public class AnotherRightFragment extends Fragment {@Nullable@Overridepublic View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {View view = inflater.inflate(R.layout.another_right_fragment, container, false);return view;}
}

修改activity_main代码

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="horizontal"><fragmentandroid:id="@+id/left_fragment"android:name="com.example.fragmentpractice.LeftFragment"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"/><FrameLayoutandroid:id="@+id/right_layout"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"></FrameLayout></LinearLayout>

修改MainActivity中的代码

package com.example.fragmentpractice;import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;// 主活动类,继承自 AppCompatActivity,并实现 View.OnClickListener 接口
public class MainActivity extends AppCompatActivity implements View.OnClickListener {// 活动创建时调用@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 启用 Edge-to-Edge 模式EdgeToEdge.enable(this);// 设置活动的布局setContentView(R.layout.activity_main);// 找到布局中的按钮Button button = (Button) findViewById(R.id.button);// 为按钮设置点击监听器button.setOnClickListener(this);// 初始化时替换碎片replaceFragment(new RightFragment());}// 点击事件处理@Overridepublic void onClick(View v) {if (v.getId() == R.id.button) {// 当按钮被点击时,替换碎片replaceFragment(new AnotherRightFragment());}}// 替换碎片的方法private void replaceFragment(Fragment fragment) {// 获取 FragmentManagerFragmentManager fragmentManager = getSupportFragmentManager();// 开始一个新的事务FragmentTransaction transaction = fragmentManager.beginTransaction();// 替换指定布局中的碎片transaction.replace(R.id.right_layout, fragment);// 提交事务transaction.commit();}
}

在碎片中模拟返回栈

在上面的例子中,点击按钮后返回会直接退出,如果想让他返回到上一个界面得模仿类似于栈的效果

只需要给MainActivity中的replaceFragment中添加:

transaction.replace(R.id.right_layout, fragment);

就行了。

public class MainActivity extends AppCompatActivity implements View.OnClickListener {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);EdgeToEdge.enable(this);setContentView(R.layout.activity_main);Button button = (Button) findViewById(R.id.button);button.setOnClickListener(this);replaceFragment(new RightFragment());}@Overridepublic void onClick(View v) {if (v.getId() == R.id.button) {replaceFragment(new AnotherRightFragment());}}private void replaceFragment(Fragment fragment) {FragmentManager fragmentManager = getSupportFragmentManager();FragmentTransaction transaction = fragmentManager.beginTransaction();transaction.replace(R.id.right_layout, fragment);transaction.addToBackStack(null);transaction.commit();}
}

碎片与活动之间的通信

FragmentManager提供了一个类似于findViewById()的方法,用于从布局文件中获取碎片的实例:

RightFragment rightFragment = (RightFragment) getSupportFragmentManager().findFragmentById(R.id.right_layout);

碎片的生命周期

onAttach()

  • 用法:当 Fragment 与 Activity 关联时调用。
  • 常用操作:初始化需要与 Activity 交互的组件或回调,确保 Fragment 与其宿主 Activity 之间的通信。

onCreate()

  • 用法:Fragment 被创建时调用。
  • 常用操作:初始化不与 UI 相关的资源,如创建或恢复数据、启动后台线程等。

onCreateView()

  • 用法:为 Fragment 创建视图层次结构时调用。
  • 常用操作:通过 LayoutInflater 填充 Fragment 的布局,初始化与视图相关的资源。

onActivityCreated()

  • 用法:确保与 Activity 相关的工作已经完成时调用。
  • 常用操作:在 Activity 的 onCreate() 方法执行完成后调用,可以在这里与 Activity 交互。

onStart()

  • 用法:Fragment 可见时调用。
  • 常用操作:注册任何需要在 Fragment 可见时工作的广播接收器或其他组件。

onResume()

  • 用法:Fragment 准备与用户交互时调用。
  • 常用操作:恢复暂停的 UI 更新或交互。

onPause()

  • 用法:Fragment 不再与用户交互时调用。
  • 常用操作:暂停与 UI 相关的操作,保存重要数据或状态。

onStop()

  • 用法:Fragment 不再可见时调用。
  • 常用操作:停止耗时的操作,如动画或播放视频,注销在 onStart() 中注册的广播接收器。

onDestroyView()

  • 用法:销毁 Fragment 的视图层次结构时调用。
  • 常用操作:清理与视图相关的资源,避免内存泄漏。

onDestroy()

  • 用法:销毁 Fragment 时调用。
  • 常用操作:清理所有资源,包括后台线程、数据和其他持有的资源。

onDetach()

  • 用法:Fragment 与 Activity 解除关联时调用。
  • 常用操作:清理与 Activity 相关的资源或回调,确保 Fragment 可以正确地与新的 Activity 关联。

image-20240722112404028

动态加载布局

使用限定符

修改activity_main文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/main"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="horizontal"><fragmentandroid:id="@+id/left_fragment"android:name="com.example.fragmentpractice.LeftFragment"android:layout_width="match_parent"android:layout_height="match_parent" /></LinearLayout>

只留下一个左侧碎片

在res目录下新建layout-large文件夹,在这个文件夹下新建一个布局,也叫做activity_main

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="horizontal"android:layout_width="match_parent"android:layout_height="match_parent"><fragmentandroid:id="@+id/left_fragment"android:name="com.example.fragmentpractice.LeftFragment"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"/><fragmentandroid:id="@+id/right_fragment"android:name="com.example.fragmentpractice.RightFragment"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="3"/></LinearLayout>

添加方法如下:

image-20240722121554656

使用最小宽度限定符

在res目录下新建layout-sw600dp文件夹,新建activity_main布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="horizontal"android:layout_width="match_parent"android:layout_height="match_parent"><fragmentandroid:id="@+id/left_fragment"android:name="com.example.fragmentpractice.LeftFragm25ent"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"/><fragmentandroid:id="@+id/right_fragment"android:name="com.example.fragmentpractice.RightFragment"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="3"/>
</LinearLayout>

当程序运行在屏幕宽度大于等于600dp的设备上,会加载layout-sw600dp/activity_main布局,小于600dp加载默认的layout/activity_main布局

创建Fragment的生命周期

静态创建

  1. Fragment Constructor、onInflate、onCreate
  • Fragment Constructor
    • 当Fragment实例化时,调用其构造函数。此时可以进行一些初始设置,但不应涉及视图创建或其他可能耗时的操作。
  • onInflate
    • 当Fragment需要从布局文件中加载视图时调用。此时可以进行视图的初步配置。该方法在Fragment被附加到Activity之前调用。
  • onCreate
    • Fragment在创建时调用。此时可以进行非视图相关的初始化工作,比如初始化变量、设置配置等。
  1. Activity onCreate
  • 当Activity首次创建时调用。在这个方法中,通常会进行视图的初始化、设置事件监听器、初始化数据等操作。这是Activity生命周期中非常重要的一个方法。

动态创建

  1. Activity onCreate
  • 同静态创建中描述的一样,Activity在首次创建时调用onCreate方法。动态创建Fragment的步骤一般在这里进行,比如通过FragmentManager添加、替换Fragment。
  1. Fragment Constructor、onCreate
  • Fragment Constructor
    • 与静态创建类似,动态创建时Fragment实例化时也会调用构造函数进行初始设置。
  • onCreate
    • Fragment在创建时调用。动态创建时,可以在这里进行Fragment的初始化工作,比如从Activity传递过来的数据进行处理。与静态创建不同的是,这里通常会涉及到从Activity获取数据或传递数据给Activity。

工具

Fragment Transaction

Fragment Transaction是管理和操作Fragments的关键工具。

常用方法

  1. add():添加一个Fragment到Activity中。

    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    transaction.add(R.id.fragment_container, new ExampleFragment());
    transaction.commit();
    
  2. replace():替换当前的Fragment。

    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    transaction.replace(R.id.fragment_container, new ExampleFragment());
    transaction.addToBackStack(null); // 可选,将事务添加到返回栈
    transaction.commit();
    
  3. remove():从Activity中移除一个Fragment。

    Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.fragment_container);
    if (fragment != null) {FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();transaction.remove(fragment);transaction.commit();
    }
    
  4. hide():隐藏一个Fragment。

  5. show():显示一个隐藏的Fragment。

    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    transaction.hide(existingFragment);
    transaction.show(newFragment);
    transaction.commit();
    
  6. attach():重新附加一个Fragment到UI。

  7. detach():从UI中分离一个Fragment。

    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    transaction.detach(existingFragment);
    transaction.attach(existingFragment);
    transaction.commit();
    
  8. addToBackStack():将事务添加到返回栈中,以便用户可以按返回键撤销该事务。

  9. commit():提交事务。

// 获取FragmentManager
FragmentManager fragmentManager = getSupportFragmentManager();// 开始一个事务
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();// 创建一个新的Fragment实例
Fragment fragment = new ExampleFragment();// 添加Fragment到容器
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.addToBackStack(null); // 可选,将事务添加到返回栈
fragmentTransaction.commit(); // 提交事务

Fragment Manager

常用方法

  1. findFragmentById(int id):通过Fragment的容器视图ID来查找Fragment。

    FragmentManager fragmentManager = getSupportFragmentManager();
    Fragment fragment = fragmentManager.findFragmentById(R.id.fragment_container);if (fragment != null) {// 找到的Fragment实例
    }
    
  2. findFragmentByTag(String tag):通过Fragment的标签(tag)来查找Fragment。

    FragmentManager fragmentManager = getSupportFragmentManager();
    Fragment fragment = fragmentManager.findFragmentById(R.id.fragment_container);if (fragment != null) {// 找到的Fragment实例
    }
    
  3. getFragments():获取当前FragmentManager中所有的Fragment(API Level 26及以上可用)。

    FragmentManager fragmentManager = getSupportFragmentManager();
    List<Fragment> fragments = fragmentManager.getFragments();for (Fragment fragment : fragments) {// 处理每个Fragment实例
    }
    

增删查替

Fragment的增删查替是通过FragmentManagerFragmentTransaction来实现的

增加

添加一个Fragment到Activity中

  1. 获取FragmentManager:

    FragmentManager fragmentManager = getSupportFragmentManager();
    
  2. 开启一个事务:

    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    
  3. 添加Fragment:

    MyFragment myFragment = new MyFragment();
    fragmentTransaction.add(R.id.fragment_container, myFragment);
    
  4. 提交事务:

    fragmentTransaction.commit();
    

删除

从Activity中移除一个Fragment

  1. 获取FragmentManager:

    FragmentManager fragmentManager = getSupportFragmentManager();
    
  2. 找到要移除的Fragment:

    MyFragment myFragment = (MyFragment) fragmentManager.findFragmentById(R.id.fragment_container);
    
  3. 开启一个事务:

    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    
  4. 移除Fragment:

    if (myFragment != null) {fragmentTransaction.remove(myFragment);
    }
    
  5. 提交事务:

    fragmentTransaction.commit();
    

查找

根据ID或标签查找Fragment

  1. 获取FragmentManager:

    FragmentManager fragmentManager = getSupportFragmentManager();
    
  2. 根据ID查找:

    MyFragment myFragment = (MyFragment) fragmentManager.findFragmentById(R.id.fragment_container);
    
  3. 根据标签查找:

    MyFragment myFragment = (MyFragment) fragmentManager.findFragmentByTag("MY_FRAGMENT_TAG");
    

替换

替换Activity中的一个Fragment

  1. 获取FragmentManager:

    FragmentManager fragmentManager = getSupportFragmentManager();
    
  2. 开启一个事务:

    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    
  3. 替换Fragment:

    MyNewFragment newFragment = new MyNewFragment();
    fragmentTransaction.replace(R.id.fragment_container, newFragment);
    
  4. 提交事务:

    fragmentTransaction.commit();
    

Fragment与Activity之间的通信

Activity向Fragment

  1. 在Activity中设置数据:

    使用Fragment的setArguments方法来传递数据。在创建Fragment实例时,可以通过Bundle将数据传递给Fragment。

// 在Activity中
Bundle bundle = new Bundle();
bundle.putString("key", "value");MyFragment myFragment = new MyFragment();
myFragment.setArguments(bundle);getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, myFragment).commit();
  1. 在Fragment中接收数据:

    在Fragment的onCreate方法中获取传递过来的数据。

// 在Fragment中
@Override
public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);if (getArguments() != null) {String value = getArguments().getString("key");// 使用获取到的数据}
}

Fragment向Activity

  1. 定义一个接口:

    在Fragment中定义一个接口,Activity实现该接口来接收数据。

// 在Fragment中定义接口
public interface OnFragmentInteractionListener {void onFragmentInteraction(String data);
}private OnFragmentInteractionListener mListener;@Override
public void onAttach(Context context) {super.onAttach(context);if (context instanceof OnFragmentInteractionListener) {mListener = (OnFragmentInteractionListener) context;} else {throw new RuntimeException(context.toString()+ " must implement OnFragmentInteractionListener");}
}// 使用接口传递数据
public void sendDataToActivity(String data) {if (mListener != null) {mListener.onFragmentInteraction(data);}
}
  1. 在Activity中实现接口:

    实现Fragment定义的接口,在接口方法中处理接收到的数据。

// 在Activity中实现接口
public class MyActivity extends AppCompatActivity implements MyFragment.OnFragmentInteractionListener {@Overridepublic void onFragmentInteraction(String data) {// 处理从Fragment接收到的数据}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);MyFragment myFragment = new MyFragment();getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, myFragment).commit();}
}

Fragment之间的数据传递

Fragment之间的通信可以通过它们共同的Activity来实现。一个Fragment将数据传递给Activity,然后Activity将数据传递给另一个Fragment。

1.Fragment A 向 Activity 传递数据

使用上面描述的Fragment向Activity传递数据的方法。

2.Activity 接收数据并传递给 Fragment B

在Activity中接收数据:

@Override
public void onFragmentInteraction(String data) {FragmentB fragmentB = (FragmentB) getSupportFragmentManager().findFragmentById(R.id.fragment_b_container);if (fragmentB != null) {fragmentB.updateData(data);}
}

在Fragment B中定义方法来接收数据:

// 在Fragment B中
public void updateData(String data) {// 更新Fragment B中的数据
}

已经到底啦!

相关文章:

【Android】碎片—动态添加、创建Fragment生命周期、通信

简单用法 在一个活动中添加两个碎片&#xff0c;并让这两个碎片平分活动空间 先新建一个左侧碎片布局和一个右侧碎片布局 左侧碎片 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/…...

前端 SSE 长连接

使用 const options {withCredentials: true, // 默认 false}const eventSource new EventSource(/api, options);eventSource.addEventListener(open, () > {});eventSource.onmessage (event) > {}; // 或addEventListener(message,callback)eventSource.addEvent…...

.mp4格式的视频为何不能通过video标签在chrome浏览器中播放?

chrome浏览器目前只支持编解码格式为H264格式的视频&#xff0c;如果某个.mp4后缀的视频不能在chrome浏览器中播放&#xff0c;多半是这个视频的编码格式不是H264的&#xff01; 1、可以通过ffmpeg工具查看当前视频的编码格式&#xff1a; ffprobe -v error -select_streams v…...

Python酷库之旅-第三方库Pandas(051)

目录 一、用法精讲 186、pandas.Series.is_monotonic_increasing属性 186-1、语法 186-2、参数 186-3、功能 186-4、返回值 186-5、说明 186-6、用法 186-6-1、数据准备 186-6-2、代码示例 186-6-3、结果输出 187、pandas.Series.is_monotonic_decreasing属性 187…...

linux timestamp

驱动或应用中获取时间戳的接口。 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <sys/time.h> #if 0 #include <linux/ktime.h> /* 内核驱动中获取时间戳 */ static ktime_t get_kernel_time…...

Vue.js 搭建大屏可视化项目

引言 在数字化转型的时代背景下&#xff0c;大屏可视化项目因其直观的数据展示和实时的业务监控能力而变得日益重要。Vue.js&#xff0c;以其简洁的语法、高效的虚拟DOM和强大的组件化能力&#xff0c;成为了构建大屏可视化应用的首选框架之一。本文将从零开始&#xff0c;引导…...

Linux:进程信号(二.信号的保存与处理、递达、volatile关键字、SIGCHLD信号)

上次介绍了&#xff1a;(Linux&#xff1a;进程信号&#xff08;一.认识信号、信号的产生及深层理解、Term与Core&#xff09;)[https://blog.csdn.net/qq_74415153/article/details/140624810] 文章目录 1.信号保存1.1递达、未决、阻塞等概念1.2再次理解信号产生与保存1.3信号…...

最值得推荐的5个AI大模型API

在这个以人工智能为主导的新时代&#xff0c;选择一个卓越的AI模型API接口&#xff0c;对于企业和个人在AI驱动的商业和技术革新中取得成功至关重要。 在人工智能的浪潮中&#xff0c;大型AI模型API接口正成为推动技术创新和业务发展的重要力量。随着2024年技术的持续进步和应用…...

PyTest+Allure生成测试报告

一、官网文档&#xff08;权威&#xff09; 1. Allure Report 官网&#xff1a;Allure Report Docs — Introduction 2. Allure GitHub地址&#xff1a;GitHub - allure-framework/allure2: Allure Report is a flexible, lightweight multi-language test reporting tool. It …...

ROS2教程(10) - 编写接收程序、添加frame - Linux

注意 : 本篇文章接上节 (点击此处跳转到上节) 编写接收程序 cpp <the_work_ws>/src/learning_tf2_cpp/src/turtle_tf2_listener.cpp #include <chrono> #include <functional> #include <memory> #include <string>#include "geometry_…...

Arraylist与LinkedList的区别

Arraylist 概念 Arraylist非线程安全Arraylist 底层使用的是Object数组ArrayList 采用数组存储&#xff0c;插入和删除元素的时间复杂度受元素位置的影响ArrayList 支持快速随机访问,就是通过元素的序号快速获取元素对象ArrayList的空间浪费主要体现在列表的结尾会预留一定的容…...

Nestjs使用Redis的最佳实践

前几天在项目中有用到Redis JWT实现服务端对token的主动删除(退出登录功能)。故此介绍下如何在Nestjs中使用Redis&#xff0c;并做下总结。 知识准备 了解Redis - 网上很多简介。了解Nestjs如何使用jwt生成token - 可移步看下我之前的文章 效果展示 一、mac安装与使用 示…...

Cadence23学习笔记(十四)

ARC就是圆弧走线的意思&#xff1a; 仅打开网络的话可以只针对net进行修改走线的属性&#xff1a; 然后现在鼠标左键点那个走线&#xff0c;那个走线就会变为弧形&#xff1a; 添加差分对&#xff1a; 之后&#xff0c;分别点击两条线即可分配差分对&#xff1a; 选完差分对之后…...

socket 编程

1. socket 套接字 Socket 是一个用于网络通信的技术。Socket 通信允许客户端——服务器之间进行双向通信。它可以使任何客户端机器连接到任何服务器&#xff0c;安装在客户端和服务器两侧的程序就可以实现双向的通信。Socket的作用就是把连接两个计算机的通信软件“中间接”起来…...

如何使用 HTTPie 进行高效的 HTTP 请求

如何使用 HTTPie 进行高效的 HTTP 请求 引言 HTTPie 是一个命令行 HTTP 客户端&#xff0c;它以其简洁的语法和人性化的输出格式赢得了广大开发者的喜爱。与 curl 相比&#xff0c;HTTPie 提供了更加直观和用户友好的接口&#xff0c;使得执行 HTTP 请求变得轻松愉快。本文将…...

Lingo求解器百度云下载 ling 8.0/lingo 18安装包资源分享

如大家所熟悉的&#xff0c;Lingo是Linear Interaction and General Optimizer的缩写&#xff0c;中文名称为“交互式线性和通用优化求解器”&#xff0c;是一套专门用于求解最优化问题的软件包。 在大部分人认知里&#xff0c;Lingo可用于求解线性规划、二次规划、整数规划、…...

文献综述如何为研究的理论框架做出贡献

VersaBot一键生成文献综述 文献综述在几个关键方面对塑造和巩固研究的理论框架起着至关重要的作用&#xff1b; 1. 识别相关理论和概念&#xff1a; 通过对现有研究的探索&#xff0c;您将遇到与您的主题相关的突出理论和概念。这些可以作为您自己的理论框架的构建块。 2. 理…...

FastAPI(七十九)实战开发《在线课程学习系统》接口开发-- 加入课程和退出课程

源码见&#xff1a;"fastapi_study_road-learning_system_online_courses: fastapi框架实战之--在线课程学习系统" 加入课程 我们先看下加入课程 1.是否登录 2.课程是否存在 3.是否已经存在 4.添加 首先实现逻辑 def get_student_course(db: Session, course: int…...

【赛事推荐】2024中国高校计算机大赛人工智能创意赛

“中国高校计算机大赛”&#xff08;China Collegiate Computing Contest&#xff0c;简称C4&#xff09;是面向全国高校各专业在校学生的科技类竞赛活动&#xff0c;于2016年由教育部高等学校计算机类专业教学指导委员会、教育部高等学校大学软件工程专业教学指导委员会、教育…...

C++沉思:预处理和编译

预处理和编译 条件编译源代码使用方式典型示例原理 使用static_assert执行编译时断言检查使用方式原理 在C中&#xff0c;编译是将源代码转换为机器代码并组织在目标文件中&#xff0c;然后将目标文件链接在一起生成可执行文件的过程。编译器实际上一次只处理一个文件&#xff…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK&#xff0c;开始写第二篇的内容了。这篇博客主要能写一下&#xff1a; 如何给一些三方库按照xmake方式进行封装&#xff0c;供调用如何按…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

使用 SymPy 进行向量和矩阵的高级操作

在科学计算和工程领域&#xff0c;向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能&#xff0c;能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作&#xff0c;并通过具体…...

初学 pytest 记录

安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化

缓存架构 代码结构 代码详情 功能点&#xff1a; 多级缓存&#xff0c;先查本地缓存&#xff0c;再查Redis&#xff0c;最后才查数据库热点数据重建逻辑使用分布式锁&#xff0c;二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...

为什么要创建 Vue 实例

核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...

人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent

安全大模型训练计划&#xff1a;基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标&#xff1a;为安全大模型创建高质量、去偏、符合伦理的训练数据集&#xff0c;涵盖安全相关任务&#xff08;如有害内容检测、隐私保护、道德推理等&#xff09;。 1.1 数据收集 描…...