解锁Android RemoteViews:跨进程UI更新的奥秘
一、RemoteViews 简介
在 Android 开发的广阔领域中,RemoteViews 是一个独特且重要的概念,它为开发者提供了一种在其他进程中显示视图结构的有效方式。从本质上讲,RemoteViews 并非传统意义上在当前应用进程内直接渲染和操作的 View,而是属于 SystemServer 进程的特殊 View 结构。
想象一下,在开发一个音乐播放应用时,我们希望在通知栏中展示播放控制界面,或者创建一个桌面小部件来快速启动播放、暂停等操作。这些场景下,通知栏和桌面小部件的界面并非在我们应用自身的进程中直接显示,而是运行在系统的 SystemServer 进程中。这时,RemoteViews 就发挥了关键作用,它允许我们在其他进程中展示特定的视图结构,实现跨进程的界面显示和交互。
由于 RemoteViews 是在其他进程中显示,其更新机制与普通 View 有很大不同。普通 View 可以在当前进程中直接通过 findViewById 获取控件并进行属性修改等操作,而 RemoteViews 为了实现跨进程更新界面,提供了一组基础操作方法 。这些方法是 View 全部方法的子集,大部分是通过反射来完成的。例如,我们无法像操作普通 TextView 那样直接调用 setText 方法来设置文本,而是需要使用 RemoteViews 提供的 setTextViewText 方法,传入对应的 viewId 和文本内容来实现。
二、RemoteViews 的使用场景
2.1 通知栏(Notification)
在通知栏中,RemoteViews 主要用于自定义通知的布局,使通知呈现出更丰富的内容和交互形式。比如在音乐播放应用中,通知栏不仅可以显示歌曲名称、歌手信息,还能添加播放、暂停、上一曲、下一曲等按钮,方便用户在不打开应用的情况下控制音乐播放 。下面通过代码示例来展示如何使用 RemoteViews 自定义通知栏布局:
// 1. 创建RemoteViews对象,加载自定义布局
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.custom_notification_layout);
// 2. 设置布局中的文本内容
remoteViews.setTextViewText(R.id.notification_title, "新消息提醒");
remoteViews.setTextViewText(R.id.notification_content, "您有一条新的消息,请查看。");
// 3. 设置布局中的图片
remoteViews.setImageViewResource(R.id.notification_icon, R.drawable.notification_icon);
// 4. 设置按钮的点击事件
Intent intent = new Intent(this, NotificationClickReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.notification_button, pendingIntent);
// 5. 创建通知构建器
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID).setSmallIcon(R.drawable.ic_notification_small).setContent(remoteViews).setPriority(NotificationCompat.PRIORITY_DEFAULT);
// 6. 获取通知管理器并发送通知
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(notificationId, builder.build());
上述代码中,首先通过RemoteViews加载了一个自定义的通知布局custom_notification_layout。然后,使用setTextViewText方法设置了通知的标题和内容,setImageViewResource方法设置了通知图标 。对于按钮的点击事件,通过创建一个Intent和PendingIntent,并使用setOnClickPendingIntent方法将其与通知布局中的按钮关联起来。最后,通过NotificationCompat.Builder构建通知,并使用NotificationManager发送通知。
2.2 桌面小部件(AppWidget)
桌面小部件是应用展示在用户桌面上的一个可视化组件,能提供简化信息和交互功能,像天气应用的桌面小部件可实时显示天气状况,日历应用的小部件能展示日程安排。使用 RemoteViews 开发桌面小部件,主要涉及布局定义、AppWidgetProvider 实现以及配置信息设置等步骤。具体如下:
- 定义 Widget 布局文件:在res/layout目录下创建布局文件,如widget_layout.xml,用于定义小部件的 UI。
<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="16dp"><TextViewandroid:id="@+id/widget_text"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Hello, Widget!"android:textSize="18sp"android:textColor="#000" /><Buttonandroid:id="@+id/widget_button"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Click Me" />
</LinearLayout>
- 创建 AppWidgetProvider 类:该类继承自AppWidgetProvider,用于处理小部件的生命周期事件和用户交互事件。
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
import android.widget.RemoteViews;
public class MyAppWidgetProvider extends AppWidgetProvider {@Overridepublic void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {for (int appWidgetId : appWidgetIds) {// 创建RemoteViews对象,加载布局RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout);// 设置按钮点击事件Intent intent = new Intent(context, MyAppWidgetProvider.class);intent.setAction("com.example.ACTION_BUTTON_CLICK");PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);views.setOnClickPendingIntent(R.id.widget_button, pendingIntent);// 更新小部件appWidgetManager.updateAppWidget(appWidgetId, views);}}@Overridepublic void onReceive(Context context, Intent intent) {super.onReceive(context, intent);if ("com.example.ACTION_BUTTON_CLICK".equals(intent.getAction())) {// 处理按钮点击事件// 例如:更新小部件内容}}
}
- 定义 AppWidgetProviderInfo 文件:在res/xml目录下创建文件,如widget_info.xml,用于指定小部件的布局、更新频率等信息。
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"android:minWidth="250dp"android:minHeight="100dp"android:updatePeriodMillis="1800000" <!--自动更新频率,单位为毫秒,这里设置为30分钟 -->android:initialLayout="@layout/widget_layout"android:resizeMode="horizontal|vertical"android:widgetCategory="home_screen" />
- 在 AndroidManifest.xml 中注册小部件:在AndroidManifest.xml文件中声明小部件的AppWidgetProvider。
<receiver android:name=".MyAppWidgetProvider"><intent-filter><action android:name="android.appwidget.action.APPWIDGET_UPDATE" /></intent-filter><meta-dataandroid:name="android.appwidget.provider"android:resource="@xml/widget_info" />
</receiver>
通过以上步骤,一个简单的桌面小部件就开发完成了。用户可以在主屏幕上添加该小部件,并与小部件进行交互,如点击按钮触发相应的操作 。
三、RemoteViews 的使用方法
3.1 创建 RemoteViews 对象
创建 RemoteViews 对象时,需要传入两个关键参数:当前应用的包名和对应的布局文件资源 ID。通过这两个参数,RemoteViews 能够准确关联到我们定义的布局文件,从而构建出相应的视图结构。例如:
RemoteViews remoteViews = new RemoteViews(getPackageName(), R.layout.custom_layout);
上述代码中,getPackageName()用于获取当前应用的包名,R.layout.custom_layout则是自定义布局文件的资源 ID。通过这行代码,我们成功创建了一个 RemoteViews 对象,并将其与custom_layout布局文件关联起来 。在实际开发中,布局文件可以包含各种支持的 View 组件,如 TextView、ImageView、Button 等,开发者可以根据需求进行灵活设计和布局。
3.2 设置 View 属性
RemoteViews 提供了一系列方法来设置 View 的属性,以满足不同的界面展示需求。以下是一些常用的设置 View 属性的方法:
- setText:用于设置 TextView 或 Button 的文本内容。例如:
remoteViews.setTextViewText(R.id.text_view_id, "这是设置后的文本");
这里的R.id.text_view_id是 TextView 或 Button 在布局文件中的 ID,"这是设置后的文本"是要设置的具体文本内容。
- setImageViewResource:用于设置 ImageView 或 ImageButton 的图片资源。例如:
remoteViews.setImageViewResource(R.id.image_view_id, R.drawable.icon);
其中[R.id].image_view_id是 ImageView 或 ImageButton 的 ID,R.drawable.icon是要设置的图片资源 ID。
- setViewVisibility:用于设置 View 的可见性。可以设置为View.VISIBLE(可见)、View.INVISIBLE(不可见但占据空间)、View.GONE(不可见且不占据空间)。例如:
remoteViews.setViewVisibility(R.id.view_id, View.GONE);
R.id.view_id是要设置可见性的 View 的 ID 。
- setTextColor:用于设置 TextView 或 Button 的文本颜色。例如:
remoteViews.setTextColor(R.id.text_view_id, Color.RED);
Color.RED表示红色,开发者可以根据需要选择不同的颜色值。
3.3 处理点击事件
由于 RemoteViews 运行在其他进程中,不能像普通 View 那样直接设置点击事件监听器 。为了实现点击事件的处理,需要借助 PendingIntent。PendingIntent 可以理解为一种 “延迟意图”,它允许我们在未来某个时刻执行特定的 Intent 操作。
具体实现步骤如下:
- 创建 Intent:定义点击事件触发后要执行的操作,例如启动一个 Activity、发送一个广播或启动一个 Service。
Intent intent = new Intent(this, TargetActivity.class);
这里TargetActivity.class是要启动的目标 Activity 。
- 创建 PendingIntent:通过 PendingIntent 的静态方法getActivity、getBroadcast或getService来创建 PendingIntent 对象,根据不同的需求选择相应的方法。
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
getBroadcast方法用于创建与广播相关的 PendingIntent,getService方法用于创建与服务相关的 PendingIntent 。
- 设置点击事件:使用 RemoteViews 的setOnClickPendingIntent方法,将 PendingIntent 与对应的 View 关联起来。
remoteViews.setOnClickPendingIntent(R.id.button_id, pendingIntent);
[R.id].button_id是要设置点击事件的按钮的 ID 。通过以上步骤,当用户点击关联了 PendingIntent 的 View 时,系统会在合适的时机执行 PendingIntent 中定义的操作,从而实现点击事件的处理。
3.4 应用 RemoteViews
在通知栏和桌面小部件中应用 RemoteViews 的步骤和使用的类有所不同,下面分别进行介绍:
- 通知栏应用 RemoteViews:
-
- 创建 RemoteViews 对象:如前文所述,创建并关联布局文件。
-
- 设置 RemoteViews 属性和点击事件:使用上述设置 View 属性和处理点击事件的方法进行相应设置。
-
- 创建 Notification 构建器:使用NotificationCompat.Builder来构建通知,并将 RemoteViews 设置为通知的内容。
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_ID).setSmallIcon(R.drawable.ic_notification_small).setContent(remoteViews).setPriority(NotificationCompat.PRIORITY_DEFAULT);
CHANNEL_ID是通知渠道 ID,在 Android 8.0 及以上版本需要设置通知渠道 。
- 发送通知:获取NotificationManager,并调用notify方法发送通知。
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(notificationId, builder.build());
notificationId是通知的唯一标识,用于区分不同的通知。
- 桌面小部件应用 RemoteViews:
-
- 定义小部件布局文件:在res/layout目录下创建布局文件,定义小部件的 UI 结构。
-
- 创建 AppWidgetProvider 类:继承自AppWidgetProvider,在onUpdate方法中处理小部件的更新逻辑。
public class MyAppWidgetProvider extends AppWidgetProvider {@Overridepublic void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {for (int appWidgetId : appWidgetIds) {RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout);// 设置属性和点击事件appWidgetManager.updateAppWidget(appWidgetId, views);}}
}
- 定义 AppWidgetProviderInfo 文件:在res/xml目录下创建文件,指定小部件的各种属性,如布局、最小尺寸、更新频率等。
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"android:minWidth="250dp"android:minHeight="100dp"android:updatePeriodMillis="1800000"android:initialLayout="@layout/widget_layout"android:resizeMode="horizontal|vertical"android:widgetCategory="home_screen" />
- 在 AndroidManifest.xml 中注册小部件:声明小部件的AppWidgetProvider。
<receiver android:name=".MyAppWidgetProvider"><intent-filter><action android:name="android.appwidget.action.APPWIDGET_UPDATE" /></intent-filter><meta-dataandroid:name="android.appwidget.provider"android:resource="@xml/widget_info" />
</receiver>
通过以上步骤,即可在通知栏和桌面小部件中成功应用 RemoteViews,实现丰富的界面展示和交互功能。
四、RemoteViews 的工作原理
4.1 跨进程通信机制
在 Android 系统中,进程间通信(IPC)是实现不同进程之间数据交互和功能调用的关键机制。而 Binder 机制则是 Android 中一种高效的 IPC 方式,RemoteViews 正是利用 Binder 机制来实现跨进程通信。
Binder 机制基于客户端 - 服务器(C/S)架构,主要由 Binder 驱动程序、ServiceManager、Server 端和 Client 端组成。Binder 驱动程序是 Linux 内核的一部分,负责处理跨进程通信的底层细节,如内存映射、数据传输等 。ServiceManager 是一个特殊的系统服务,它维护着一个服务列表,所有通过 Binder 进行通信的服务都需要在 ServiceManager 中注册,其他组件可以通过 ServiceManager 查询并获取服务的引用。
在 RemoteViews 的应用场景中,以通知栏为例,当我们在应用中创建一个包含 RemoteViews 的通知时,应用进程(Client 端)通过 Binder 机制将 RemoteViews 对象以及相关的操作指令发送到 SystemServer 进程(Server 端)中的 NotificationManagerService。NotificationManagerService 接收到这些信息后,根据 RemoteViews 中的包名等信息去获取该应用中的资源,然后进行相应的处理和显示。在这个过程中,Binder 机制确保了数据能够在不同进程之间安全、高效地传输 。同样,在桌面小部件的场景中,AppWidgetProvider 所在的应用进程与 SystemServer 进程中的 AppWidgetService 之间也是通过 Binder 机制进行通信,实现小部件的创建、更新等操作。
4.2 序列化与反序列化
为了在进程间传递 RemoteViews 对象及其相关操作,需要将其转换为可传输的字节流形式,这就涉及到序列化与反序列化。RemoteViews 实现了 Parcelable 接口,该接口提供了一种高效的序列化和反序列化机制,专门用于 Android 系统中的数据传输。
在序列化过程中,RemoteViews 将自身的状态信息,如布局资源 ID、设置的 View 属性以及点击事件等相关信息,按照 Parcelable 接口的规范写入到 Parcel 对象中。例如,当我们调用remoteViews.setTextViewText(R.id.text_view_id, “这是设置后的文本”);方法时,这个设置文本的操作以及相关的参数(如 View 的 ID 和文本内容)都会被封装到一个 Action 对象中,然后这个 Action 对象会被写入到 Parcel 中。
当 RemoteViews 对象被传输到目标进程(如 SystemServer 进程)后,目标进程会对接收到的 Parcel 进行反序列化操作。通过 Parcelable 接口的CREATOR成员,从 Parcel 中读取数据并重新构建出 RemoteViews 对象及其相关的操作信息,从而在目标进程中恢复 RemoteViews 的状态,以便进行后续的布局加载和更新操作 。
4.3 内部操作流程
当我们在应用中创建一个 RemoteViews 对象并对其进行一系列设置后,如设置 View 属性、添加点击事件等,这些操作并不会立即执行。RemoteViews 会将这些操作封装成一个个 Action 对象,并存储在一个列表中。例如,当调用setTextViewText方法时,会创建一个ReflectionAction对象(它是 Action 的子类,用于通过反射调用 View 的方法),并将其添加到 RemoteViews 的操作列表中。
接下来,当我们通过NotificationManager的notify方法或者AppWidgetManager的updateAppWidget方法提交更新时,RemoteViews 对象会通过 Binder 机制被传递到 SystemServer 进程。在 SystemServer 进程中,首先会根据 RemoteViews 中的布局资源 ID,使用LayoutInflater加载布局文件,创建出实际的 View 对象。然后,会遍历 RemoteViews 中的 Action 列表,依次执行每个 Action 的apply方法 。在apply方法中,会通过反射调用 View 的相应方法,从而实现对 View 属性的设置和点击事件的绑定等操作。例如,对于前面提到的ReflectionAction对象,其apply方法会反射调用 View 的setText方法,将设置的文本内容显示在对应的 TextView 上。
以一个简单的通知栏更新场景为例,假设我们创建了一个 RemoteViews 对象,并设置了 TextView 的文本和一个按钮的点击事件。当调用NotificationManager.notify方法后,RemoteViews 对象被传递到 SystemServer 进程,系统先加载布局文件创建出包含 TextView 和按钮的 View 结构,然后执行setText操作的 Action,将 TextView 的文本设置为指定内容,再执行设置按钮点击事件的 Action,将按钮与对应的 PendingIntent 绑定,这样当用户点击通知栏中的按钮时,就能触发相应的操作。
五、RemoteViews 的局限性
5.1 支持的 View 类型有限
RemoteViews 并非支持所有的 View 和布局类型,这是其在使用过程中需要特别注意的一点。目前,RemoteViews 支持的布局类型主要有 FrameLayout、LinearLayout、RelativeLayout、GridLayout 。在 View 类型方面,支持 AnalogClock、Button、Chronometer、ImageButton、ImageView、ProgressBar、TextView、ViewFlipper、ListView、GridView、StackView、AdapterViewFlipper、ViewStub 等。然而,它不支持自定义 View 及其子类 。例如,如果开发者尝试在 RemoteViews 中使用自定义的 View,如继承自 View 并实现了特殊绘制逻辑和交互功能的自定义控件,会抛出InflateException异常,导致布局加载失败。这就要求开发者在设计布局时,充分考虑 RemoteViews 的支持范围,避免使用不支持的 View 类型,以确保应用的稳定性和兼容性。
5.2 事件处理的限制
在事件处理方面,RemoteViews 存在明显的局限性。它不能像普通 View 那样直接设置点击事件监听器,例如无法使用setOnClickListener方法来处理点击事件。这是因为 RemoteViews 运行在其他进程中,直接设置点击事件监听器会涉及到跨进程通信的复杂问题,并且可能带来安全风险。为了实现点击等交互功能,RemoteViews 需要借助PendingIntent来实现。通过PendingIntent,可以将一个 Intent 操作封装起来,并在未来某个时刻由系统触发执行 。虽然这种方式能够实现基本的交互需求,但相比于普通 View 的事件处理方式,它的灵活性和实时性较差。例如,在处理复杂的事件逻辑时,使用PendingIntent可能会导致代码结构变得复杂,难以维护。而且,由于PendingIntent是在未来某个不确定的时刻执行,对于一些需要实时反馈的交互场景,可能无法满足需求。
5.3 性能开销
RemoteViews 在实现跨进程通信和视图更新的过程中,不可避免地会带来一定的性能开销。首先,由于 RemoteViews 需要通过 Binder 机制进行跨进程通信,在数据传输过程中,会涉及到序列化和反序列化操作,这会消耗一定的时间和系统资源。特别是当布局文件较大或者包含较多的操作指令时,序列化和反序列化的时间开销会更加明显,可能导致界面更新的延迟 。其次,在 SystemServer 进程中,加载布局文件和执行一系列的操作指令也需要消耗 CPU 和内存资源。如果频繁地更新 RemoteViews,可能会导致系统资源的紧张,影响应用的整体性能,甚至出现卡顿现象。例如,在一个频繁更新通知栏的应用中,如果每次更新都包含大量的 View 属性设置和复杂的布局,可能会导致通知栏的响应速度变慢,影响用户体验。因此,在使用 RemoteViews 时,开发者需要充分考虑性能因素,尽量优化布局和操作指令,减少不必要的更新,以提高应用的性能。
六、总结
RemoteViews 作为 Android 开发中实现跨进程界面展示和交互的重要工具,在通知栏和桌面小部件等场景中发挥着不可替代的作用。通过 RemoteViews,开发者能够突破进程的限制,为用户提供更加丰富和便捷的交互体验,如在通知栏中实现音乐播放控制,在桌面小部件上展示实时信息等。
尽管 RemoteViews 存在支持的 View 类型有限、事件处理不够灵活以及性能开销等局限性,但在合适的应用场景下,这些问题可以通过合理的设计和优化来缓解。例如,在布局设计时,充分考虑 RemoteViews 支持的 View 类型,避免使用不支持的自定义 View;在处理点击事件时,巧妙利用 PendingIntent 来实现基本的交互需求;在性能优化方面,尽量减少不必要的布局更新和复杂操作,以提高应用的响应速度 。
对于 Android 开发者来说,掌握 RemoteViews 的使用方法和工作原理,能够极大地拓展应用的功能边界,提升应用的用户体验。在未来的开发中,随着 Android 系统的不断演进,我们也期待 RemoteViews 能够不断完善和发展,为开发者提供更多的便利和更强大的功能。希望开发者们在实际项目中,积极探索 RemoteViews 的应用,充分发挥其优势,打造出更加出色的 Android 应用。
相关文章:
解锁Android RemoteViews:跨进程UI更新的奥秘
一、RemoteViews 简介 在 Android 开发的广阔领域中,RemoteViews 是一个独特且重要的概念,它为开发者提供了一种在其他进程中显示视图结构的有效方式。从本质上讲,RemoteViews 并非传统意义上在当前应用进程内直接渲染和操作的 View…...
编译可以在Android手机上运行的ffmpeg程序
下载代码 git clone gitgithub.com:FFmpeg/FFmpeg.git git checkout n7.0建立build目录 mkdir build cd build创建build.sh脚本 vim build.sh这段脚本的主要功能是配置和编译 FFmpeg,使其能够在 Android 平台上运行,通过设置不同的架构和 API 级别&am…...

Verilog学习方法—基础入门篇(一)
前言: 在FPGA开发中,Verilog HDL(硬件描述语言)是工程师必须掌握的一项基础技能。它不仅用于描述数字电路,还广泛应用于FPGA的逻辑设计与验证。对于初学者来说,掌握Verilog的核心概念和基本语法࿰…...

本地jar包添加到 maven
进入到 你的 maven bin文件夹下 执行cmd ,然后执行命令 mvn install:install-file -Dfilepath/to/your/artifact.jar -DgroupIdyour.group.id -DartifactIdyour-artifact-id -Dversion1.0 -Dpackagingjar 替换path/to/your/artifact.jar为你的JAR文件路径…...

C# Unity 唐老狮 No.6 模拟面试题
本文章不作任何商业用途 仅作学习与交流 安利唐老狮与其他老师合作的网站,内有大量免费资源和优质付费资源,我入门就是看唐老师的课程 打好坚实的基础非常非常重要: 全部 - 游习堂 - 唐老狮创立的游戏开发在线学习平台 - Powered By EduSoho 如果你发现了文章内特殊的字体格式,…...
项目工坊 | Python驱动淘宝信息爬虫
目录 前言 1 完整代码 2 代码解读 2.1 导入模块 2.2 定义 TaoBao 类 2.3 search_infor_price_from_web 方法 2.3.1 获取下载路径 2.3.2 设置浏览器选项 2.3.3 反爬虫处理 2.3.4 启动浏览器 2.3.5 修改浏览器属性 2.3.6 设置下载行为 2.3.7 打开淘宝登录页面 2.3.…...
Java8-Stream流介绍和使用案例
Java 8 引入了 Stream API,它提供了一种高效且声明式的方式来处理集合数据。Stream 的核心思想是将数据的操作分为中间操作(Intermediate Operations)和终端操作(Terminal Operations),并通过流水线&#x…...
setlocale()的参数,“zh_CN.UTF-8“, “chs“, “chinese-simplified“的差异。
在 C/C 中,setlocale() 函数的参数 zh_CN.UTF-8、chs 和 chinese-simplified 均用于设置中文简体环境,但它们的语义、平台支持和编码行为存在显著差异: 1. zh_CN.UTF-8(推荐) 含义: zh_CN: 中文&…...

docker 安装达梦数据库(离线)
docker安装达梦数据库,官网上已经下载不了docker版本的了,下面可通过百度网盘下载 通过网盘分享的文件:dm8_20240715_x86_rh6_rq_single.tar.zip 链接: https://pan.baidu.com/s/1_ejcs_bRLZpICf69mPdK2w?pwdszj9 提取码: szj9 上传到服务…...
FastGPT 引申:如何基于 LLM 判断知识库的好坏
文章目录 如何基于 LLM 判断知识库的好坏方法概述示例 Prompt声明抽取器 Prompt声明检查器 Prompt 判断机制总结 下面介绍如何基于 LLM 判断知识库的好坏,并展示了如何利用声明抽取器和声明检查器这两个 prompt 构建评价体系。 如何基于 LLM 判断知识库的好坏 在知…...

关于2023新版PyCharm的使用
考虑到大家AI编程的需要,建议大家安装新版Python解释器和新版PyCharm,下载地址都可以官网进行: Python:Download Python | Python.org(可以根据需要自行选择,建议选择3.11,保持交流版本一致&am…...
Leetcode 112: 路径总和
Leetcode 112: 路径总和 问题描述: 给定一个二叉树的根节点 root 和一个目标和 targetSum,判断是否存在从根节点到叶子节点的路径,使路径上所有节点的值相加等于目标和 targetSum。 适合面试的解法:递归 解法特点: …...

华为云IAM 用户名和IAM ID
账号 当您首次使用华为云时注册的账号,该账号是您的华为云资源归属、资源使用计费的主体,对其所拥有的资源及云服务具有完全的访问权限,可以重置用户密码、分配用户权限等。账号统一接收所有IAM用户进行资源操作时产生的费用账单。 账号不能…...

Compose Multiplatform+Kotlin Multiplatfrom 第四弹跨平台
文章目录 引言功能效果开发准备依赖使用gradle依赖库MVIFlow设计富文本显示 总结 引言 Compose Multiplatformkotlin Multiplatfrom 今天已经到compose v1.7.3,从界面UI框架上实战开发看,很多api都去掉实验性注解,表示稳定使用了!…...

【Proteus仿真】【STM32单片机】全自动养护智能生态雨林缸
文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真STM32单片机控制器,使用按键、LCD1602液晶、DS18B20模块、PCF8591 ADC、浑浊传感器、PH传感器、液位传感器、继电器、水泵、酸碱调节剂、加热降温装置等。 主要功能&am…...
GBT32960 协议编解码器的设计与实现
GBT32960 协议编解码器的设计与实现 引言 在车联网领域,GBT32960 是一个重要的国家标准协议,用于新能源汽车与监控平台之间的数据交互。本文将详细介绍如何使用 Rust 实现一个高效可靠的 GBT32960 协议编解码器。 整体架构 编解码器的核心由三个主要组…...
SolidWorks 转 PDF3D 技术详解
在现代工程设计与制造流程中,不同软件间的数据交互与格式转换至关重要。将 SolidWorks 模型转换为 PDF3D 格式,能有效解决模型展示、数据共享以及跨平台协作等问题。本文将深入探讨 SolidWorks 转 PDF3D 的技术原理、操作流程及相关注意事项,…...

OpenMCU(二):GD32E23xx FreeRTOS移植
概述 本文主要描述了GD32E230移植FreeRTOS的简要步骤。移植描述过程中,忽略了Keil软件的部分使用技巧。默认读者熟练使用Keil软件。本文的描述是基于OpenMCU_FreeRTOS这个工程,该工程已经下载放好了移植GD32E230 FreeRTOS的所有文件 OpenMCU_FreeRTOS工程…...
Codeforces Round 835 (Div. 4)题解ABCDEFG
Problem - A - Codeforces 题意:你有 t 组数据,每组有两两不同的三个数 a,b,c,现在需要你求出他们的中位数。 思路:模拟即可 // Code Start Here int t;cin >> t;while(t--){vector<int> a(3);for(int i 0;i<3…...

NO1.C++语言基础|四种智能指针|内存分配情况|指针传擦和引用传参|const和static|c和c++的区别
1. 说⼀下你理解的 C 中的四种智能指针 智能指针的作用是管理指针,可以避免内存泄漏的发生。 智能指针就是一个类,当超出了类的作用域时,就会调用析构函数,这时就会自动释放资源。 所以智能指针作用的原理就是在函数结束时自动释…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
在Ubuntu24上采用Wine打开SourceInsight
1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...

VisualXML全新升级 | 新增数据库编辑功能
VisualXML是一个功能强大的网络总线设计工具,专注于简化汽车电子系统中复杂的网络数据设计操作。它支持多种主流总线网络格式的数据编辑(如DBC、LDF、ARXML、HEX等),并能够基于Excel表格的方式生成和转换多种数据库文件。由此&…...
CppCon 2015 学习:Time Programming Fundamentals
Civil Time 公历时间 特点: 共 6 个字段: Year(年)Month(月)Day(日)Hour(小时)Minute(分钟)Second(秒) 表示…...

2025年- H71-Lc179--39.组合总和(回溯,组合)--Java版
1.题目描述 2.思路 当前的元素可以重复使用。 (1)确定回溯算法函数的参数和返回值(一般是void类型) (2)因为是用递归实现的,所以我们要确定终止条件 (3)单层搜索逻辑 二…...

Xcode 16 集成 cocoapods 报错
基于 Xcode 16 新建工程项目,集成 cocoapods 执行 pod init 报错 ### Error RuntimeError - PBXGroup attempted to initialize an object with unknown ISA PBXFileSystemSynchronizedRootGroup from attributes: {"isa">"PBXFileSystemSynchro…...
13.10 LangGraph多轮对话系统实战:Ollama私有部署+情感识别优化全解析
LangGraph多轮对话系统实战:Ollama私有部署+情感识别优化全解析 LanguageMentor 对话式训练系统架构与实现 关键词:多轮对话系统设计、场景化提示工程、情感识别优化、LangGraph 状态管理、Ollama 私有化部署 1. 对话训练系统技术架构 采用四层架构实现高扩展性的对话训练…...