【Android】通知的使用

使用通知

通知(notification)是Android系统中比较有特色的一个功能,当某个应用程序希望向用户发出一些提示信息,而该应用程序又不在前台运行时,就可以借助通知来实现。发出一条通知后,手机最上方的状态栏中会显示一个通知的图标,下拉状态栏后可以看到通知的详细内容。

创建通知渠道

什么是通知渠道呢?顾名思义,就是每条通知都要属于一个对应的渠道。每个应用程序都可以自由地创建当前应用拥有哪些通知渠道,但是这些通知渠道的控制权是掌握在用户手上的。用户可以自由地选择这些通知渠道的重要程度,是否响铃、是否振动或者是否要关闭这个渠道的通知。拥有了这些控制权之后,用户就再也不用害怕那些垃圾通知的打扰了,因为用户可以自主地选择关心哪些通知、不关心哪些通知。以刚才的场景举例,微博就可以创建两种通知渠道,一个关注,一个推荐。而我作为用户,如果对推荐类的通知不感兴趣,那么我就可以直接将推荐通知渠道关闭,这样既不影响我接收关心的通知,又不会让那些我不关心的通知来打扰我了。对于每个应用来说,通知渠道的划分是非常考究的,因为通知渠道一旦创建之后就不能再修改了,因此开发者需要仔细分析自己的应用程序一共有哪些类型的通知,然后再去创建相应的通知渠道。

使用方法

1.NotificationManager对通知进行管理

首先需要一个NotificationManager对通知进行管理,可以通过调用Context的getSystemService()方法获取。getSystemService()方法接收一个字符串参数用于确定获取系统的哪个服务,这里我们传入Context.NOTIFICATION_SERVICE即可。因此,获取NotificationManager的实例就可以写成:

NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

接下来要使用NotificationChannel类构建一个通知渠道,并调用NotificationManager的createNotificationChannel()方法完成创建。由于NotificationChannel类和createNotificationChannel()方法都是Android 8.0系统中新增的API,因此我们在使用的时候还需要进行版本判断才可以,写法如下:

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {// 获取NotificationManager服务android.app.NotificationManager manager = (android.app.NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);// 定义通知渠道的ID、名称和重要性String channelId = "your_channel_id"; // 这里替换成您的渠道IDString channelName = "Your Channel Name"; // 这里替换成您的渠道名称int importance = android.app.NotificationManager.IMPORTANCE_DEFAULT; // 设置通知的重要性等级// 创建NotificationChannel对象android.app.NotificationChannel channel = new android.app.NotificationChannel(channelId, channelName, importance);// 配置NotificationChannel的属性(可选)channel.setDescription("Your channel description"); // 设置渠道描述// 注册通知渠道manager.createNotificationChannel(channel);
}

创建一个通知渠道至少需要渠道ID、渠道名称以及重要等级这3个参数,其中渠道ID可以随便定义,只要保证全局唯一性就可以。渠道名称是给用户看的,需要可以清楚地表达这个渠道的用途。通知的重要等级主要有IMPORTANCE_HIGH、IMPORTANCE_DEFAULT、IMPORTANCE_LOW、IMPORTANCE_MIN这几种,对应的重要程度依次从高到低。不同的重要等级会决定通知的不同行为,后面我们会通过具体的例子进行演示。当然这里只是初始状态下的重要等级,用户可以随时手动更改某个通知渠道的重要等级,开发者是无法干预的。

通知的基本用法

了解了如何创建通知渠道之后,下面我们就来看一下通知的使用方法吧。通知的用法还是比较灵活的,既可以在Activity里创建,也可以在BroadcastReceiver里创建,当然还可以在后面我们即将学习的Service里创建。相比于BroadcastReceiver和Service,在Activity里创建通知的场景还是比较少的,因为一般只有当程序进入后台的时候才需要使用通知。

2.使用一个Builder构造器来创建Notification对象(NotificationCompat)

首先需要使用一个Builder构造器来创建Notification对象,但问题在于,Android系统的每一个版本都会对通知功能进行或多或少的修改,API不稳定的问题在通知上凸显得尤其严重,比方说刚刚介绍的通知渠道功能在Android 8.0系统之前就是没有的。那么该如何解决这个问题呢?其实解决方案我们之前已经见过好几回了,就是使用AndroidX库中提供的兼容API。AndroidX库中提供了一个NotificationCompat类,使用这个类的构造器创建Notification对象,就可以保证我们的程序在所有Android系统版本上都能正常工作了,代码如下所示:

    // 使用NotificationChannel的ID创建NotificationCompat.Buildernotification = new NotificationCompat.Builder(context, channelId).setSmallIcon(R.drawable.ic_notification) // 设置小图标.setContentTitle("Your Title") // 设置通知标题.setContentText("Your Content") // 设置通知内容.setChannelId(channelId) // 设置通知渠道ID.build();

NotificationCompat.Builder的构造函数中接收两个参数:

第一个参数是context,这个没什么好说的;

第二个参数是渠道ID,需要和我们在创建通知渠道时指定的渠道ID相匹配才行。

当然,上述代码只是创建了一个空的Notification对象,并没有什么实际作用,我们可以在最终的build()方法之前连缀任意多的设置方法来创建一个丰富的Notification对象,

  • setContentTitle()方法用于指定通知的标题内容,下拉系统状态栏就可以看到这部分内容。
  • setContentText()方法用于指定通知的正文内容,同样下拉系统状态栏就可以看到这部分内容。
  • setSmallIcon()方法用于设置通知的小图标,注意,只能使用纯alpha图层的图片进行设置,小图标会显示在系统状态栏上。
  • setLargeIcon()方法用于设置通知的大图标,当下拉系统状态栏时,就可以看到设置的大图标了。
3.NotificationManager的notify()方法

以上工作都完成之后,只需要调用NotificationManager的notify()方法就可以让通知显示出来了。

notify()方法接收两个参数:

第一个参数是id,要保证为每个通知指定的id都是不同的;

第二个参数则是Notification对象,这里直接将我们刚刚创建好的Notification对象传入即可。

因此,显示一个通知就可以写成:

manager.notify(1, notification)

新建一个NotificationTest项目,并修改activity_main.xml中的代码,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"><Button android:id="@+id/sendNotice"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Send Notice" />
</LinearLayout>

布局文件非常简单,里面只有一个“Send Notice”按钮,用于发出一条通知。接下来修改MainActivity中的代码,如下所示:

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {private Button sendNotice;private NotificationManager manager;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);// 获取系统服务中的NotificationManagermanager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);// 检查Android版本是否在O(API级别26)及以上if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {// 创建一个新的通知渠道NotificationChannel channel = new NotificationChannel("normal", "Normal", NotificationManager.IMPORTANCE_DEFAULT);// 注册通知渠道到系统中manager.createNotificationChannel(channel);}sendNotice = findViewById(R.id.sendNotice);sendNotice.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Notification.Builder builder = new Notification.Builder(MainActivity.this, "normal").setContentTitle("This is content title").setContentText("This is content text").setSmallIcon(R.drawable.ic_launcher_background).setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_foreground));Notification notification = builder.build();manager.notify(1, notification);}});}
}

在这里插入图片描述

应用程序尝试在目标SDK为Android 13(API级别33)或更高版本的设备上发送通知,但没有正确请求或检查POST_NOTIFICATIONS权限。从Android 13开始,应用必须在运行时动态请求此权限才能发送通知。

为了修复这个问题,需要确保应用在尝试发送通知之前已经获得了POST_NOTIFICATIONS权限。这通常涉及到两步:

  1. 在应用的AndroidManifest.xml文件中声明POST_NOTIFICATIONS权限。
  2. 在应用的代码中动态请求这个权限。

我们首先获取了NotificationManager的实例,并创建了一个ID为normal通知渠道。创建通知渠道的代码只在第一次执行的时候才会创建,当下次再执行创建代码时,系统会检测到该通知渠道已经存在了,因此不会重复创建,也并不会影响运行效率。

接下来在“Send Notice”按钮的点击事件里完成了通知的创建工作,创建的过程正如前面所描述的一样。

注意,在NotificationCompat.Builder的构造函数中传入的渠道ID也必须叫normal,如果传入了一个不存在的渠道ID,通知是无法显示出来的

这个时候就可以发送通知了

PendingIntent

如果你使用过Android手机,此时应该会下意识地认为这条通知是可以点击的。但是当你去点击它的时候,会发现没有任何效果。不对啊,每条通知被点击之后都应该有所反应呀。其实要想实现通知的点击效果,我们还需要在代码中进行相应的设置,这就涉及了一个新的概念——PendingIntent。

PendingIntent从名字上看起来就和Intent有些类似,它们确实存在不少共同点。比如它们都可以指明某一个“意图”,都可以用于启动Activity、启动Service以及发送广播等。不同的是,Intent倾向于立即执行某个动作,而PendingIntent倾向于在某个合适的时机执行某个动作。所以,也可以把PendingIntent简单地理解为延迟执行的Intent。

PendingIntent的用法同样很简单,它主要提供了几个静态方法用于获取PendingIntent的实例,可以根据需求来选择是使用getActivity()方法、getBroadcast()方法,还是getService()方法。

这几个方法所接收的参数都是相同的:

第一个参数依旧是Context,不用多做解释;

第二个参数一般用不到,传入0即可;

第三个参数是一个Intent对象,我们可以通过这个对象构建出PendingIntent的“意图”;

第四个参数用于确定PendingIntent的行为,有FLAG_ONE_SHOT、FLAG_NO_CREATE、FLAG_CANCEL_CURRENT和FLAG_UPDATE_CURRENT这4种值可选,每种值的具体含义你可以查看文档,通常情况下这个参数传入0就可以了

对PendingIntent有了一定的了解后,我们再回过头来看一下NotificationCompat.Builder。这个构造器还可以连缀一个setContentIntent()方法,接收的参数正是一个PendingIntent对象。因此,这里就可以通过PendingIntent构建一个延迟执行的“意图”,当用户点击这条通知时就会执行相应的逻辑。

现在我们来优化一下NotificationTest项目,给刚才的通知加上点击功能,让用户点击它的时候可以启动另一个Activity

首先需要准备好另一个Activity,右击com.example.notificationtest包→New→Activity→Empty Activity,新建NotificationActivity。然后修改activity_notification.xml中的代码,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent" ><TextView android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:textSize="24sp"android:text="This is notification layout" />
</RelativeLayout>

这样就把NotificationActivity准备好了,下面我们修改MainActivity中的代码,给通知加入点击功能,如下所示:

sendNotice.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Intent intent = new Intent(MainActivity.this, noticebestart.class);PendingIntent pi = PendingIntent.getActivity(MainActivity.this, 0, intent, PendingIntent.FLAG_IMMUTABLE);NotificationCompat.Builder builder = new NotificationCompat.Builder(MainActivity.this, "normal").setContentTitle("This is content title").setContentText("This is content text").setSmallIcon(R.drawable.ic_launcher_background).setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_foreground)).setContentIntent(pi).setAutoCancel(true);Notification notification = builder.build();manager.notify(1, notification);}});
}

可以看到,这里先是使用Intent表达出我们想要启动NotificationActivity的“意图”,然后将构建好的Intent对象传入PendingIntent的getActivity()方法里,以得到PendingIntent的实例,接着在NotificationCompat.Builder中调用setContentIntent()方法,把它作为参数传入即可。现在重新运行一下程序,并点击“Send Notice”按钮,依旧会发出一条通知。然后下拉系统状态栏,点击一下该通知,就会打开NotificationActivity的界面了

setAutoCancel()方法传入true,就表示当点击这个通知的时候,通知会自动取消。

显式地调用NotificationManager的cancel()方法将它取消。这里我们在cancel()方法中传入了1,这个1是什么意思呢?还记得在创建通知的时候给每条通知指定的id吗?当时我们给这条通知设置的id就是1。因此,如果你想取消哪条通知,在cancel()方法中传入该通知的id就行了。

通知的进阶技巧

setStyle()方法

这个方法允许我们构建出富文本的通知内容。也就是说,通知中不光可以有文字和图标,还可以包含更多的东西。setStyle()方法接收一个NotificationCompat.Style参数,这个参数就是用来构建具体的富文本信息的,如长文字、图片等。在开始使用setStyle()方法之前,我们先来做一个试验吧,之前的通知内容都比较短,如果设置成很长的文字会是什么效果呢?(会发现我们的信息被省略掉了)

如果你真的非常需要在通知当中显示一段长文字通过setStyle()方法就可以做到,具体写法如下:

.setStyle(NotificationCompat.BigTextStyle().bigText("Learn how to buildnotifications, send and sync data, and use voice actions. Get the officialAndroid IDE and developer tools to build apps for Android.")).build()

这里使用了setStyle()方法替代setContentText()方法。在setStyle()方法中,我们创建了一个NotificationCompat.BigTextStyle对象,这个对象就是用于封装长文字信息的,只要调用它的bigText()方法并将文字内容传入就可以了。

除了显示长文字之外,通知里还可以显示一张大图片,具体用法是基本相似的:

.setStyle(NotificationCompat.BigPictureStyle().bigPicture(BitmapFactory.decodeResource(resources, R.drawable.big_image)))

可以看到,这里仍然是调用的setStyle()方法,这次我们在参数中创建了一个NotificationCompat.BigPictureStyle对象,这个对象就是用于设置大图片的,然后调用它的bigPicture()方法并将图片传入。这里我事先准备好了一张图片,通过BitmapFactory的decodeResource()方法将图片解析成Bitmap对象,再传入bigPicture()方法中就可以了。

重要等级

接下来,我们学习一下不同重要等级的通知渠道对通知的行为具体有什么影响。其实简单来讲,就是通知渠道的重要等级越高,发出的通知就越容易获得用户的注意。

比如高重要等级的通知渠道发出的通知可以弹出横幅、发出声音,而低重要等级的通知渠道发出的通知不仅可能会在某些情况下被隐藏,而且可能会被改变显示的顺序,将其排在更重要的通知之后。

但需要注意的是,开发者只能在创建通知渠道的时候为它指定初始的重要等级,如果用户不认可这个重要等级的话,可以随时进行修改,开发者对此无权再进行调整和变更,因为通知渠道一旦创建就不能再通过代码修改了。

既然无法修改之前创建的通知渠道,那么我们就只好再创建一个新的通知渠道来测试了。修改MainActivity中的代码,如下所示:

public class MainActivity extends AppCompatActivity {private Button sendNotice;private NotificationManager manager;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// setContentView(R.layout.your_layout); // 请替换为你的布局文件// 初始化按钮等组件sendNotice = findViewById(R.id.send_notice_button); // 请替换为实际的按钮IDmanager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);// 设置按钮的点击事件sendNotice.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// 创建IntentIntent intent = new Intent(MainActivity.this, NotificationActivity.class);PendingIntent pi = PendingIntent.getActivity(MainActivity.this, 0, intent, 0);// 检查Android版本,如果是8.0以上,则创建通知渠道if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {NotificationChannel channel2 = new NotificationChannel("important", "Important", NotificationManager.IMPORTANCE_HIGH);manager.createNotificationChannel(channel2);}// 创建通知Notification notification = new NotificationCompat.Builder(MainActivity.this, "important").setContentTitle("Your Title") // 设置通知标题.setContentText("Your Text") // 设置通知内容.setSmallIcon(R.drawable.ic_notification) // 设置通知小图标.setContentIntent(pi) // 设置通知点击后的行为.build();// 发送通知manager.notify(1, notification); // 1是通知的ID,可以自定义}});}
}

在这里插入图片描述

可以看到,这次的通知不是在系统状态栏显示一个小图标了,而是弹出了一个横幅,并附带了通知的详细内容,表示这是一条非常重要的通知。不管用户现在是在玩游戏还是看电影,这条通知都会显示在最上方,以此引起用户的注意。当然,使用这类通知时一定要小心,确保你的通知内容的确是至关重要的,不然如果让用户产生排斥感的话,可能会造成适得其反的效果。

  • MMKV简介: MMKV是一种专为Android设计的键值存储方案,支持多进程访问,能够提供比SharedPreferences更快的读写速度。
  • 使用场景: MMKV适用于需要快速读写操作和跨进程数据共享的应用场景,例如用户偏好设置、应用配置等。
  • 初始化方法: 文章介绍了如何初始化MMKV,包括创建实例和配置选项,以便开发者能够根据自己的需求进行设置。
  • 数据读取原理: 通过视频教程,作者详细解释了MMKV的数据存储和读取机制,帮助开发者理解其工作原理。
  • 与其他存储方案的比较: 文章还对比了MMKV与传统的SharedPreferences以及文件存储方案,突出了MMKV在性能和多进程支持方面的优势。

MMKV是一种专为Android设计的键值存储方案,支持多进程访问,能够提供比SharedPreferences更快的读写速度。

  • 使用场景: MMKV适用于需要快速读写操作和跨进程数据共享的应用场景,例如用户偏好设置、应用配置等。
  • 初始化方法: 文章介绍了如何初始化MMKV,包括创建实例和配置选项,以便开发者能够根据自己的需求进行设置。
  • 数据读取原理: 通过视频教程,作者详细解释了MMKV的数据存储和读取机制,帮助开发者理解其工作原理。
  • 与其他存储方案的比较: 文章还对比了MMKV与传统的SharedPreferences以及文件存储方案,突出了MMKV在性能和多进程支持方面的优势。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/391852.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

YOLO:VOC格式数据集转换为YOLO数据集格式

作者&#xff1a;CSDN _养乐多_ 本文将介绍如何将目标检测中常用的VOC格式数据集转换为YOLO数据集&#xff0c;并进行数据集比例划分&#xff0c;从而方便的进行YOLO目标检测。 文章目录 一、将VOC格式数据集转换为YOLO格式数据集二、YOLO格式数据集划分&#xff08;训练、验…

FreeRTOS中的动态内存管理(heap_1、heap_2、heap_3、heap_4)

FreeRTOS 提供了多种动态内存分配方案&#xff0c;这些方案通过不同的内存管理器&#xff08;heap managers&#xff09;实现&#xff0c;主要位于 FreeRTOS/Source/portable/MemMang 目录下。以下是几种常见的动态内存分配方案&#xff1a; heap_1 特点&#xff1a; 简单性…

电脑添加虚拟网卡与ensp互联,互访

一、按照过程 1、打开设备管理器 2、点击网络适配器&#xff0c;点击左上角操作&#xff0c;点击“添加过时硬件” 3、下一页 4、选择“安装我手动从列表选择的硬件”&#xff0c;下一页 5、下拉&#xff0c;选择“网络适配器”&#xff0c;下一页 6、厂商选择“Microsoft”&…

内网穿透--LCX+portmap转发实验

实验背景 通过公司带有防火墙功能的路由器接入互联网&#xff0c;然后由于私网IP的缘故&#xff0c;公网 无法直接访问内部web服务器主机&#xff0c;通过内网其它主机做代理&#xff0c;穿透访问内网web 服务器主机 实验设备 1. 路由器、交换机各一台 2. 外网 kali 一台&…

设计测试用例的具体方法

一.等价类 等价类分为: 1.有效等价类 [6~15] 2.无效等价类 :小于6位,大于15位(不在数据范围内) 组合规则: 有效等价类组合的时候,尽可能一条测试用例尽可能多的覆盖有效等价类 无效等价类组合的时候,一条测试点,之恶能覆盖一个无效等价类 二.边界值 1.上点,离点,内点 上…

Shader入门精要总结(二)矩阵

1. 矩阵乘法 一个rn的矩阵A和一个nc的矩阵B相乘&#xff0c;它们的结果AB将会是一个rc大小的矩阵&#xff0c;不满足此规则不能相乘 矩阵乘法满足一些性质 矩阵乘法不满足交换律 即AB≠BA矩阵乘法满足结合律 (AB)CA(BC) 2. 特殊矩阵 方块矩阵 指行和列数目相等的矩阵&#x…

谷粒商城实战笔记-103~104-全文检索-ElasticSearch-Docker安装ES和Kibana

文章目录 一&#xff0c;103-全文检索-ElasticSearch-Docker安装ES1&#xff0c;下载镜像文件2&#xff0c;Elasticsearch安装3&#xff0c;验证 二&#xff0c;104-全文检索-ElasticSearch-Docker安装Kibana1&#xff0c;下载镜像文件2&#xff0c;kibana的安装3&#xff0c;验…

繁简之争:为什么手机芯片都是 ARM

RISC 和 CISC 指令集 之前的文章《揭秘 CPU 是如何执行计算机指令的》中说到&#xff0c;如果从软件的角度来讲&#xff0c;CPU 就是一个执行各种计算机指令&#xff08;Instruction Code&#xff09;的逻辑机器。 计算机指令集是计算机指令的集合&#xff0c;包括各种类型的…

【Android Studio】彻底卸载

文章目录 卸载程序控制面板卸载安全软件卸载 删除文件重启计算机 我们在Android开发时涉及重装时&#xff0c;如果卸载不干净&#xff0c;再次安装是不会正常运行项目的&#xff0c;接下来就让我教你如何删除干净吧。 卸载程序 控制面板卸载 control控制面板一>程序一>…

wxPython中wx.adv.DatePickerCtrl用法

wx.adv.DatePickerCtrl是一个日期选择组件&#xff0c;支持键盘手工录入日期和弹出日历窗口选择日期两种方式。 一、组件样式 wx.adv.DP_SPIN &#xff1a; 只允许键盘手工录入和组件右侧上下箭头调整日期。 wx.adv.DP_DROPDOWN &#xff1a; 只允许健盘手工录入和组件右侧打开…

一天攻克一个知识点 —— 设计模式之动态代理

一、设计模式之代理设计 代理设计是在Java开发中使用较多的一种设计模式&#xff0c;所谓的代理设计模式就是指一个代理主体操作真实主体&#xff0c;真实主体操作具体业务&#xff0c;代理主体负责给具体业务添砖加瓦。 就好比在生活中你有一套房子想要出租(你真实主体)&…

安卓控件RecyclerVieW

文章目录 导入依赖简单使用实现横向滚动瀑布式 RecyclerView是官方在5.0之后新添加的控件&#xff0c;推出用来替代ListView和GridView的列表控件。为了保证RecyclerView在所有Android系统版本上都能使用。Google将RecyclerView控件定义在了AndroidX中&#xff0c;只需要在项目…

完美平替navicat的数据库软件DBeaver,免费开源,功能强大,使用简单

DBeaver Community 是一个免费的跨平台数据库工具&#xff0c;适用于开发人员、数据库管理员、分析师和所有与数据打交道的人。它支持所有流行的 SQL 数据库&#xff0c;如 MySQL、MariaDB、PostgreSQL、SQLite、Apache Family 等 1.到官网下载win版本直接安装 https://dbeav…

苹芯科技发布新AI模型,引领全球轻量级AI应用革命

苹芯科技&#xff0c;一家在全球AI技术领域中不断创新的公司&#xff0c;于2月28日宣布推出其最新研发的轻量级AI模型。这款新模型旨在为开发者和企业提供更高效、更易访问的人工智能工具&#xff0c;尤其强调在数据敏感和计算资源受限的环境下的应用潜力。 在谷歌刚刚推出Gemm…

Python使用cProfile进行性能分析使用详解

概要 在Python开发中,代码性能分析是优化和调试的重要环节。通过性能分析,可以找出程序中性能瓶颈,进而进行优化。cProfile是Python内置的性能分析工具,它可以详细地分析代码的执行时间和函数调用情况。本文将详细介绍如何使用cProfile进行代码性能分析,涵盖安装、基本用…

代码随想录第29天|贪心

134.加油站 代码随想录 代码随想录 索引01234gas12345cost34512 计算每个加油站的剩余油量&#xff0c;累计sum&#xff0c;一旦<0就从下一个重新计数。 我还没理解为什么我们不需要计算环路的sum&#xff0c;而是只需要遍历一次。 因为使用了两个变量&#xff1a;curSu…

力扣-46.全排列

刷力扣热题–第二十六天:46.全排列 新手第二十六天 奋战敲代码&#xff0c;持之以恒&#xff0c;见证成长 1.题目简介 2.题目解答 这道题目想了会,思路比较好想,但一直没调试成功,所以就参考了力扣官网的代码,积累一下回溯算法的实现和基本实现思路,即先试探后回溯,结果在下面…

加密软件通常使用哪些算法

加密软件通常使用多种算法来确保数据的安全性&#xff0c;这些算法主要分为对称加密算法、非对称加密算法和哈希算法三大类。 一、对称加密算法 对称加密算法&#xff0c;也称为共享密钥加密算法&#xff0c;是加密和解密都使用相同密钥的算法。这类算法的特点是加密和解密速…

24/8/4算法笔记 梯度下降

通过迭代地调整参数&#xff0c;沿着目标函数梯度的反方向&#xff08;即最陡峭的下降方向&#xff09;进行搜索&#xff0c;从而找到函数的局部最小值。 导入库 import matplotlib.pyplot as plt import numpy as np 构建方程和导数 #构建方程 f lambda x:(x-3.5)**2-4.…

使用Docker+ollama部署大模型

Docker的安装----在 Ubuntu 系统上安装 Docker 一&#xff1a;配置系统的 APT 软件包管理器 首先添加 Docker 的官方 GPG 密钥 # Add Dockers official GPG key: sudo apt-get update sudo apt-get install ca-certificates curl gnupg sudo install -m 0755 -d /etc/apt/ke…