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

Android Snackbar

1.Snackbar

Snackbar是Material Design中的一个控件,用来代替Toast。Snackbar是一个类似Toast的快速弹出消息提示的控件。Snackbar在显示上比Toast丰富,而且提供了用户交互的接口。

①默认情况下,Snackbar显示在屏幕底部,它出现在屏幕所有元素之上,且同时最多只能显示一个Snackbar。

②Snackbar与某些视图相关联,并且仅当视图在屏幕上时才会显示Snackbar。

③Snackbar出现时不会阻碍用户在屏幕上的输入。Snackbar可以自定义时长。

④当Snackbar在CoordinatorLayout下使用时,支持右滑删除功能。

 

2.Snackbar的用法

Snackbar的用法很简单,不需要在xml中写布局,像Toast一样直接在代码里使用即可。

首先需要添加依赖:

implementation "com.google.android.material:$latest_version" 

然后就可以在代码中使用了:

①最基本的用法

Snackbar.make(view, "Show some message here",Snackbar.LENGTH_LONG)

.setAction("Action", v1 -> {

        Log.e(TAG, "点击了确定按钮");

}).show();

92ff9ab3f82449e09f7f41086249ca7a.png

注意:Snackbar不支持设置多个action,如果设置多个action,只有最后一个生效。

②设置颜色

Snackbar.make(view, "Show some message here", Snackbar.LENGTH_SHORT)

.setBackgroundTint(ContextCompat.getColor(this, R.color.baseCyan))

.setActionTextColor(ContextCompat.getColor(this, R.color.white))

.setTextColor(ContextCompat.getColor(this,R.color.black))

.setAction("Action") { 

     Log.e(TAG, "点击了确定按钮");

}

.show()

fbef3ab2c7344652804db1b9abdcbeb8.png

 ③添加回调

addCallback()用于给snackbar添加回调,回调Snackbar弹出和关闭动作。

Snackbar.make(view, "Show some message here", Snackbar.LENGTH_SHORT)

.addCallback(new Snackbar.Callback() {

    public void onShown(Snackbar sb) {

        super.onShown(sb)

        Log.d(TAG, "onShown")

    }

    public void onDismissed( transientBottomBar: Snackbar?, event: Int) {

        super.onDismissed(transientBottomBar, event)

        Log.d(TAG, "onDismissed")

    }

}).show();

④在文本前面添加图片

Snackbar snackbar = Snackbar.make(view, "这是一个snackbar", Snackbar.LENGTH_SHORT);

snackbar.setAction("取消", new View.OnClickListener() {

    @Override

    public void onClick(View v) {

    }

});

TextView textView = snackbar.getView().findV iewById(R.id.snackbar_text);

Drawable drawable = getResources().getDrawa ble(R.mipmap.ic_launcher_round);

drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());

textView.setCompoundDrawables(drawable, null, null, null);

//增加文字和图标的距离

textView.setCompoundDrawablePadding(20);

textView.setGravity(Gravity.CENTER);

snackbar.show();

65eea4a867334a5bb4662aa344078bfd.webp

⑤自定义布局

自定义布局的步骤:

1)通过Snackbar.getView获取到view;

1)通过LayoutInflater去加载布局得到自定义的布局view;

3)通过①中获取到的view添加②中加载好的布局view;

4)通过①中得到的自定义布局获取里面的控件去执行一些操作,比如点击事件,设置文字和文字颜色等。

View rootView = getWindow().getDecorView();

View coordinatorLayout = rootView.findViewById(android.R.id.content);

Snackbar snackbar = Snackbar.make( coordinatorLayout, "", Snackbar.LENGTH_SHORT);

// 获取到Snackbar.getView获取的Snackbar的view

Snackbar.SnackbarLayout snackbarView = (Snackbar.SnackbarLayout) snackbar.getView();

// 加载自定义布局

View inflate = LayoutInflater.from( snackbar.getView().getContext()).inflate(R.layout.snacbar_layout, null);

// 获取自定义布局中的控件

TextView text = inflate.findViewById( R.id.textView);

text.setText("自定义布局的Snackbar");

ImageView imageView = inflate.findViewById( R.id.imageView);

imageView.setOnClickListener(v1 -> Log.d("TAG", "点击了自定义布局中的控件"));

// 将自定义布局view添加到SnackbarView中

snackbarView.addView(inflate);

snackbar.show();

⑥修改Snackbar的位置

自定义位置的步骤:

1)获取到SnackbarView的LayoutParams;

2)通过①中获取到的LayoutParams创建新的LayoutParams;

③给②中的LayoutParams设置Gravity;

④将新的LayoutParams设置给SnackbarView。

View rootView = getWindow().getDecorView();

View coordinatorLayout = rootView.findViewById(android.R.id.content);

Snackbar snackbar = Snackbar.make(coordinatorLayout, "", Snackbar.LENGTH_SHORT);

// 设置SnackbarView的padding都为0,避免上图中出现黑色边框背景的情况

snackbar.getView().setPadding(0,0,0,0);

// 将SnackbarView的背景颜色设置为透明,避免在自定义布局中有圆角或者自适应宽度的时候显示一块黑色背景的情况

snackbar.getView().setBackgroundColor(Color.TRANSPARENT);

// 获取到Snackbar.getView获取的Snackbar的view

Snackbar.SnackbarLayout snackbarView = (Snackbar.SnackbarLayout) snackbar.getView();

// 获取到SnackbarView的LayoutParams

ViewGroup.LayoutParams layoutParams = snackbarView.getLayoutParams();

// 新建一个LayoutParams将SnackbarView的LayoutParams的宽高传入

FrameLayout.LayoutParams fl = new FrameLayout.LayoutParams(layoutParams.width, layoutParams.height);

// 设置新的元素位置

fl.gravity = Gravity.CENTER;

// 将新的LayoutParams设置给SnackbarView

snackbarView.setLayoutParams(fl);

// 自定义的布局

View inflate = LayoutInflater.from( snackbar.getView().getContext()).inflate(R.layout.snacbar_layout, null);

TextView text = inflate.findViewById( R.id.textView);

text.setText("自定义布局的Snackbar");

ImageView imageView = inflate.findViewById(R.id.imageView);

imageView.setOnClickListener(v1 -> Log.d("TAG", "点击了自定义布局中的控件"));

snackbarView.addView(inflate);

snackbar.show();

 

3.Snackbar源码

①Snackbar使用静态方法make()创建实例

public static Snackbar make(View view, int resId, int duration) {

    return make(view, view.getResources().getText(resId), duration);

}

public static Snackbar make(View view, CharSequence text, int duration) {

    ViewGroup parent = findSuitableParent( view);

    if (parent == null) {

        throw new IllegalArgumentException("No suitable parent found from the given view. Please provide a valid view.");

    }

    final LayoutInflater inflater = LayoutInflater.from(parent.getContext());

    final SnackbarContentLayout content =(SnackbarContentLayout) inflater.inflate( R.layout.design_layout_snackbar_include, parent, false);

    final Snackbar snackbar = new Snackbar( parent, content, content);

    snackbar.setText(text);

    snackbar.setDuration(duration);

    return snackbar;

}

②findSuitableParent()

创建Snackbar实例,需要寻找合适的父视图,优先选择CoordinatorLayout作为父视图。

private static ViewGroup findSuitableParent( View view) {

    ViewGroup fallback = null;

    do {

        if (view instanceof CoordinatorLayout) {

            return (ViewGroup) view;

        } else if (view instanceof FrameLayout) {

            if(view.getId() == android.R.id.content) {

                return (ViewGroup) view;

            } else {

                fallback = (ViewGroup) view;

            }

        }

        if (view != null) {

            final ViewParent parent = view.getParent();

            view = parent instanceof View ? (View) parent : null;

        }

    } while (view != null);

    return fallback;

}

③SnackbarContentLayout

SnackbarContentLayout继承LinearLayout,并实现了BaseTransientBottomBar.ContentViewC allback,包含一个TextView和Button。

design_layout_snackbar_include.xml文件:

<view xmlns:android="http://schemas.andro id.com/apk/res/android"

    class="android.support.design.internal.Sna ckbarContentLayout"

    android:theme="@style/ThemeOverlay.Ap pCompat.Dark"

    android:layout_width="match_parent"

    android:layout_height="wrap_content"

    android:layout_gravity="bottom">

    <TextView

        android:id="@+id/snackbar_text"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_weight="1"

        android:paddingTop="@dimen/design_sn ackbar_padding_vertical"

        android:paddingBottom="@dimen/desig n_snackbar_padding_vertical"

        android:paddingLeft="@dimen/design_sn ackbar_padding_horizontal"

        android:paddingRight="@dimen/design_s nackbar_padding_horizontal"

        android:textAppearance="@style/TextAp pearance.Design.Snackbar.Message"

        android:maxLines="@integer/design_sna ckbar_text_max_lines"

        android:layout_gravity="center_vertical| left|start"

        android:ellipsize="end"

        android:textAlignment="viewStart"/>

        <Button

        android:id="@+id/snackbar_action"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:layout_marginLeft="@dimen/de sign_snackbar_extra_spacing_horizontal"

        android:layout_marginStart="@dimen/de sign_snackbar_extra_spacing_horizontal"

        android:layout_gravity="center_vertical| right|end"

        android:minWidth="48dp"

        android:visibility="gone"

        android:textColor="?attr/colorAccent"

        style="?attr/borderlessButtonStyle"/>

</view>

④SnackbarManager类

SnackbarManager用来管理Snackbar控件的状态。

Snackbar的show()方法会调用SnackbarManager的show(int, Callback)方法,而mManagerCallback会回调Snackbar的showView()和hideView(int)方法。

static {

    sHandler = new Handler( Looper.getMainLooper(), new Handler.Callback() {

        @Override

        public boolean handleMessage(Message message) {

            switch (message.what) {

                case MSG_SHOW:

                    ((BaseTransientBottomBar) message.obj).showView();

                    return true;

                case MSG_DISMISS:

                    ((BaseTransientBottomBar) message.obj).hideView(message.arg1);

                    return true;

            }

            return false;

        }

    });

}

final SnackbarManager.Callback mManagerCallback = new SnackbarManager.Callback() {

    @Override

    public void show() {

        sHandler.sendMessage( sHandler.obtainMessage(MSG_SHOW, BaseTransientBottomBar.this));

    }

    @Override

    public void dismiss(int event) {

        sHandler.sendMessage( sHandler.obtainMessage(MSG_DISMISS, event, 0, BaseTransientBottomBar.this));

    }

};

public void show() {

    SnackbarManager.getInstance().show( mDuration, mManagerCallback);

}

SnackbarManager内部包含两个记录mCurrentSnackbar和mNextSnackbar。在SnackbarManager的show(int, Callback)方法中,①查看是否是当前Snackbar,如果是,更新超时时间,结束。②查看是否是NextSnackbar,如果是,更新数据,如果不是创建新的NextSnackbar。③取消当前Snackbar或者显示NextSnackbar。

⑤show(int, Callback)方法

public void show(int duration, Callback callback) {

    synchronized (mLock) {

        if (isCurrentSnackbarLocked(callback)) {

            // 如果是当前Snackbar,更新duration和超时提示

            mCurrentSnackbar.duration = duration;

            mHandler.removeCallbacksAndMessag es( mCurrentSnackbar);

            scheduleTimeoutLocked( mCurrentSnackbar);

            return;

        } else if (isNextSnackbarLocked(callback)){

            // 如果是NextSnackbar,更新duration

            mNextSnackbar.duration = duration;

        } else {

            // 否则就创建新的NextSnackbar

            mNextSnackbar = new SnackbarRecord(duration, callback);

        }

        if (mCurrentSnackbar != null && cancelSnackbarLocked(mCurrentSnackbar, Snackbar.Callback.DISMISS_EVENT_CONSECUTIVE)) {

            // 如果当前Snackbar存在,取消显示当前Snackbar                

            return;

        } else {                

            mCurrentSnackbar = null;

            // 如果当前Snackbar不存在,显示NextSnackbar

            showNextSnackbarLocked();

        }

    }

}

// 取消显示当前Snackbar,调用callback的dismiss(DISMISS_EVENT_CONSECUTIVE)方法

private boolean cancelSnackbarLocked( SnackbarRecord record, int event) {

    final Callback callback = record.callback.get();

    if (callback != null) {

        mHandler.removeCallbacksAndMessages( record);

        callback.dismiss(event);

        return true;

    }

    return false;

}

private boolean isCurrentSnackbarLocked( Callback callback) {

    return mCurrentSnackbar != null && mCurrentSnackbar.isSnackbar(callback);

}

private boolean isNextSnackbarLocked( Callback callback) {

    return mNextSnackbar != null && mNextSnackbar.isSnackbar(callback);

}

// 更新超时提示

private void scheduleTimeoutLocked( SnackbarRecord r) {

    if (r.duration == Snackbar.LENGTH_INDEFINITE) {

        return;

    }

    int durationMs = LONG_DURATION_MS;

    if (r.duration > 0) {

        durationMs = r.duration;

    } else if (r.duration == Snackbar.LENGTH_SHORT) {

        durationMs = SHORT_DURATION_MS;

    }

    mHandler.removeCallbacksAndMessages(r);

    mHandler.sendMessageDelayed( Message.obtain(mHandler, MSG_TIMEOUT, r), durationMs);

}

// 显示NextSnackbar,调用callback的show方法

private void showNextSnackbarLocked() {

    if (mNextSnackbar != null) {

        mCurrentSnackbar = mNextSnackbar;

        mNextSnackbar = null;

        final Callback callback = mCurrentSnackbar.callback.get();

        if (callback != null) {

            callback.show();

        } else {

            mCurrentSnackbar = null;

        }

    }

}

Snackbar的showView()会调用onViewShown(),hideView(int)会调用onViewHidden(int):

final void showView() {

    ... ...

    if (shouldAnimate()) {

        // If animations are enabled, animate it in

        animateViewIn();

    } else {

        // Else if anims are disabled just call back now

        onViewShown();

    }

    ... ...

}

final void hideView(final int event) {

    if (shouldAnimate() && mView.getVisibility() == View.VISIBLE) {

        animateViewOut(event);

    } else {

        // If anims are disabled or the view isn't visible, just call back now

        onViewHidden(event);

    }

}

void onViewShown() {

    SnackbarManager.getInstance().onShown( mManagerCallback);

}

void onViewHidden(int event) {    

    SnackbarManager.getInstance().onDismi ssed(mManagerCallback);

}

SnackbarManager的onShown(Callback)和onDismissed(Callback)方法:

public void onShown(Callback callback) {

    synchronized (mLock) {

        if (isCurrentSnackbarLocked(callback)) {

            scheduleTimeoutLocked( mCurrentSnackbar);

        }

    }

}

public void onDismissed(Callback callback) {

    synchronized (mLock) {

        if (isCurrentSnackbarLocked(callback)) {

            // If the callback is from a Snackbar currently show, remove it and show a new one

            mCurrentSnackbar = null;

            if (mNextSnackbar != null) {

                showNextSnackbarLocked();

            }

        }

    }

}

 

相关文章:

Android Snackbar

1.Snackbar Snackbar是Material Design中的一个控件&#xff0c;用来代替Toast。Snackbar是一个类似Toast的快速弹出消息提示的控件。Snackbar在显示上比Toast丰富&#xff0c;而且提供了用户交互的接口。 ①默认情况下&#xff0c;Snackbar显示在屏幕底部&#xff0c;它出现…...

详解API接口如何安全的传输数据(内附商品详情API接口接入方式)

概述 API接口的安全传输是确保数据在API请求和响应之间的传输过程中不被截获、篡改或泄露的重要步骤。以下是一些用于增强API接口安全传输的常见技术和最佳实践&#xff1a; 使用HTTPS&#xff1a;使用HTTPS协议而不是HTTP&#xff0c;以确保数据在传输过程中的安全性。HTTPS使…...

网工内推 | 大专以上,福利待遇好,IE认证优先(云厂商)

01 主动脉科技有限公司 招聘岗位&#xff1a;网络工程师 职责描述&#xff1a; 1.负责云计算&#xff0c;IDC&#xff0c;BGP网络&#xff0c;通过团队协作&#xff0c;构建云业务后台技术支持服务体系。 2.通过工单、其他通讯工具等线上方式完成对客户的实施售后支持&#x…...

Python time strptime()和strftime()

1 strptime()方法 根据指定的格式把一个时间字符串解析为时间元组 重要的时间日期格式化符号 %y 两位数的年份表示&#xff08;00-99&#xff09; %Y 四位数的年份表示&#xff08;000-9999&#xff09; %m 月份&#xff08;01-12&#xff09; %d 月内中的一天&#xff08;0-…...

是谁家班主任还不知道 怎么发布期中成绩啊。

你知道吗&#xff1f;居然还有班主任不知道怎么发布期中成绩&#xff01; 发布成绩并不是一件难事&#xff0c;只需几个步骤&#xff0c;就能轻松搞定&#xff01; 给大家讲一下成绩查询是什么。成绩查询是指学生通过一定的方式&#xff0c;如输入学号、姓名等&#xff0c;在指…...

损失函数(Loss Function)一文详解-聚类问题常见损失函数Python代码实现+计算原理解析

损失函数(Loss Function)一文详解-聚类问题常见损失函数Python代码实现计算原理解析 前言 损失函数无疑是机器学习和深度学习效果验证的核心检验功能&#xff0c;用于评估模型预测值与实际值之间的差异。我们学习机器学习和深度学习或多或少都接触到了损失函数&#xff0c;但…...

测试用例设计方法 —— 场景法详解

场景法是通过运用场景来对系统的功能点或业务流程的描述&#xff0c;从而提高测试效果的一种方法。 场景法一般包含基本流和备用流&#xff0c;从一个流程开始&#xff0c;通过描述经过的路径来确定的过程&#xff0c;经过遍历所有的基本流和备用流来完成整个场景。 场景主要…...

el-table表格设置——动态修改表头

(1) 首先是form表单写表单设置按钮&#xff1a; &#xff08;1.1&#xff09;使用el-popover&#xff0c;你需要修改的是this.colOptions&#xff0c;colSelect: <el-popover id"popover" popper-class"planProver" placement"bottom" width&…...

京东数据分析:2023年9月京东洗地机行业品牌销售排行榜

鲸参谋监测的京东平台9月份洗地机市场销售数据已出炉&#xff01; 9月份&#xff0c;洗地机市场的销售额增长。根据鲸参谋电商数据分析平台的相关数据显示&#xff0c;9月京东平台上洗地机的销量为9.2万&#xff0c;销售额将近2.2亿&#xff0c;同比增长约9%。从价格上看&#…...

使用 TensorFlow SSD 网络进行对象检测

使用 TensorFlow SSD 网络进行对象检测 目录 描述这个示例是如何工作的&#xff1f; 处理输入图准备数据sampleUffSSD 插件验证输出TensorRT API 层和操作 先决条件运行示例 示例 --help 选项 附加资源许可证更改日志已知问题 描述 该示例 sampleUffSSD 预处理 TensorFlow …...

(2)STM32单片机上位机

使用VX小程序开发上位机&#xff0c; 样式如何创建&#xff1f; 在你所在页面 开辟空间 使用 view 在view 中 输入class 就是样式&#xff0c;在编辑样式的时候&#xff0c;如何寻找哪一块的样式 就是通过这个class寻找的 按钮使用switch...

从InnoDB索引的数据结构,去理解索引

从InnoDB索引的数据结构&#xff0c;去理解索引 1、InnoDB 中的 BTree1.1、BTree 的组成1.2、BTree中的数据页 2、聚簇索引2.1、聚簇索引的特点2.2、聚簇索引的结构示例2.3、聚簇索引的优缺点 3、非聚簇索引3.1、非聚簇索引结构示例3.2、关于回表3.3、聚簇索引和非聚簇索引的区…...

Nacos:动态服务发现与配置管理的终极解决方案

今天我想和大家分享一下Nacos&#xff0c;这是一个由阿里巴巴开源的动态服务发现、配置和服务管理平台。我将详细介绍Nacos的主要特性&#xff0c;并通过实例来演示如何使用它。同时&#xff0c;我还会指出Nacos的优点&#xff0c;希望这篇文章能够帮助大家更好地理解和使用Nac…...

易思无人值守智能物流系统Sys_ReportFile文件上传漏洞复现

文章目录 易思无人值守智能物流系统Sys_ReportFile文件上传漏洞复现0x01 前言0x02 漏洞描述0x03 影响版本0x04 漏洞环境0x05 漏洞复现1.访问漏洞环境2.构造POC3.复现 0x06 修复建议 易思无人值守智能物流系统Sys_ReportFile文件上传漏洞复现 0x01 前言 免责声明&#xff1a;请…...

java Map List转化,通过Map保存数据,通过List排序。取前三名

java Map List转化&#xff0c;通过Map保存数据&#xff0c;通过List排序。取前三名 package yo;import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map;public class a {public static void …...

LEECODE 1480一维数组的动态和

class Solution { public:vector<int> runningSum(vector<int>& nums) {vector<int> runningSum;int sum 0;int len nums.size();for(int i 0; i < len; i){sum sum nums[i];runningSum.push_back(sum);}return runningSum;} };...

python文档链接

python与并行计算...

HTTP调试代理工具/Proxyman

Proxyman专为开发人员和网络爱好者设计&#xff0c;它允许用户拦截、查看和修改所有传入和传出的网络请求&#xff0c;并提供详细的分析和调试功能。 Proxyman支持HTTP、HTTPS和WebSocket协议&#xff0c;因此&#xff0c;可以轻松捕获和查看这些协议下的网络流量。用户可以使…...

搭建Qt5.7.1+kylinV10开发环境、运行环境

1.下载Qt源码 Index of / 2.编译Qt 解压缩qt-everywhere-opensource-src-5.7.1.tar.gz 进入到qt-everywhere-opensource-src-5.7.1/qtbase/mkspecs这个目录下&#xff0c; 2.1找到以下目录 复制他&#xff0c;然后改名linux-x86-arrch64&#xff0c;博主这里名字取的有些问…...

Ceph:关于Ceph 中创建和管理自定义 CRUSH Map

写在前面 准备考试&#xff0c;整理 Ceph 相关笔记博文内容涉及&#xff0c;管理和定制CRUSH Map以及管理OSD Map理解不足小伙伴帮忙指正 对每个人而言&#xff0c;真正的职责只有一个&#xff1a;找到自我。然后在心中坚守其一生&#xff0c;全心全意&#xff0c;永不停息。所…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻

在如今就业市场竞争日益激烈的背景下&#xff0c;越来越多的求职者将目光投向了日本及中日双语岗位。但是&#xff0c;一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧&#xff1f;面对生疏的日语交流环境&#xff0c;即便提前恶补了…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的&#xff0c;根据Excel列的需求预估的工时直接打骨折&#xff0c;不要问我为什么&#xff0c;主要…...

基于数字孪生的水厂可视化平台建设:架构与实践

分享大纲&#xff1a; 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年&#xff0c;数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段&#xff0c;基于数字孪生的水厂可视化平台的…...

Swagger和OpenApi的前世今生

Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章&#xff0c;二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑&#xff1a; &#x1f504; 一、起源与初创期&#xff1a;Swagger的诞生&#xff08;2010-2014&#xff09; 核心…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制

在数字化浪潮席卷全球的今天&#xff0c;数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具&#xff0c;在大规模数据获取中发挥着关键作用。然而&#xff0c;传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时&#xff0c;常出现数据质…...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配

目录 一、C 内存的基本概念​ 1.1 内存的物理与逻辑结构​ 1.2 C 程序的内存区域划分​ 二、栈内存分配​ 2.1 栈内存的特点​ 2.2 栈内存分配示例​ 三、堆内存分配​ 3.1 new和delete操作符​ 4.2 内存泄漏与悬空指针问题​ 4.3 new和delete的重载​ 四、智能指针…...

NPOI Excel用OLE对象的形式插入文件附件以及插入图片

static void Main(string[] args) {XlsWithObjData();Console.WriteLine("输出完成"); }static void XlsWithObjData() {// 创建工作簿和单元格,只有HSSFWorkbook,XSSFWorkbook不可以HSSFWorkbook workbook new HSSFWorkbook();HSSFSheet sheet (HSSFSheet)workboo…...

PHP 8.5 即将发布:管道操作符、强力调试

前不久&#xff0c;PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5&#xff01;作为 PHP 语言的又一次重要迭代&#xff0c;PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是&#xff0c;借助强大的本地开发环境 ServBay&am…...

go 里面的指针

指针 在 Go 中&#xff0c;指针&#xff08;pointer&#xff09;是一个变量的内存地址&#xff0c;就像 C 语言那样&#xff1a; a : 10 p : &a // p 是一个指向 a 的指针 fmt.Println(*p) // 输出 10&#xff0c;通过指针解引用• &a 表示获取变量 a 的地址 p 表示…...

使用SSE解决获取状态不一致问题

使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件&#xff0c;这个上传文件是整体功能的一部分&#xff0c;文件在上传的过程中…...