解锁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 实现以及配置信息设置等步骤。具体如下:

  1. 定义 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">
    <TextView
        android:id="@+id/widget_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello, Widget!"
        android:textSize="18sp"
        android:textColor="#000" />
    <Button
        android:id="@+id/widget_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Click Me" />
</LinearLayout>
  1. 创建 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 {
    @Override
    public 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);
        }
    }
    @Override
    public void onReceive(Context context, Intent intent) {
        super.onReceive(context, intent);
        if ("com.example.ACTION_BUTTON_CLICK".equals(intent.getAction())) {
            // 处理按钮点击事件
            // 例如:更新小部件内容
        }
    }
}
  1. 定义 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" />
  1. 在 AndroidManifest.xml 中注册小部件:在AndroidManifest.xml文件中声明小部件的AppWidgetProvider。
<receiver android:name=".MyAppWidgetProvider">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>
    <meta-data
        android: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 操作。

具体实现步骤如下:

  1. 创建 Intent:定义点击事件触发后要执行的操作,例如启动一个 Activity、发送一个广播或启动一个 Service。
Intent intent = new Intent(this, TargetActivity.class);

这里TargetActivity.class是要启动的目标 Activity 。

  1. 创建 PendingIntent:通过 PendingIntent 的静态方法getActivity、getBroadcast或getService来创建 PendingIntent 对象,根据不同的需求选择相应的方法。
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

getBroadcast方法用于创建与广播相关的 PendingIntent,getService方法用于创建与服务相关的 PendingIntent 。

  1. 设置点击事件:使用 RemoteViews 的setOnClickPendingIntent方法,将 PendingIntent 与对应的 View 关联起来。
remoteViews.setOnClickPendingIntent(R.id.button_id, pendingIntent);

[R.id].button_id是要设置点击事件的按钮的 ID 。通过以上步骤,当用户点击关联了 PendingIntent 的 View 时,系统会在合适的时机执行 PendingIntent 中定义的操作,从而实现点击事件的处理。

3.4 应用 RemoteViews

在通知栏和桌面小部件中应用 RemoteViews 的步骤和使用的类有所不同,下面分别进行介绍:

  • 通知栏应用 RemoteViews
    1. 创建 RemoteViews 对象:如前文所述,创建并关联布局文件。
    1. 设置 RemoteViews 属性和点击事件:使用上述设置 View 属性和处理点击事件的方法进行相应设置。
    1. 创建 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 及以上版本需要设置通知渠道 。

  1. 发送通知:获取NotificationManager,并调用notify方法发送通知。
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(notificationId, builder.build());

notificationId是通知的唯一标识,用于区分不同的通知。

  • 桌面小部件应用 RemoteViews
    1. 定义小部件布局文件:在res/layout目录下创建布局文件,定义小部件的 UI 结构。
    1. 创建 AppWidgetProvider 类:继承自AppWidgetProvider,在onUpdate方法中处理小部件的更新逻辑。
public class MyAppWidgetProvider extends AppWidgetProvider {
    @Override
    public 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);
        }
    }
}
  1. 定义 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" />
  1. 在 AndroidManifest.xml 中注册小部件:声明小部件的AppWidgetProvider。
<receiver android:name=".MyAppWidgetProvider">
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>
    <meta-data
        android: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 应用。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深入探索C++17文件系统库:std::filesystem全面解析

前言 在C编程中&#xff0c;文件系统操作是许多应用程序的基础功能之一。无论是读写文件、创建目录&#xff0c;还是遍历文件系统&#xff0c;文件系统操作几乎无处不在。然而&#xff0c;在C17之前&#xff0c;标准库并没有提供一个统一、高效且易用的文件系统操作接口。开发…

C++学习之C++初识、C++对C语言增强、对C语言扩展

一.C初识 1.C简介 2.第一个C程序 //#include <iostream> //iostream 相当于 C语言下的 stdio.h i - input 输入 o -output 输出 //using namespace std; //using 使用 namespace 命名空间 std 标准 &#xff0c;理解为打开一个房间&#xff0c;房间里有我们所需…

transformer架构解析{掩码,(自)注意力机制,多头(自)注意力机制}(含代码)-3

目录 前言 掩码张量 什么是掩码张量 掩码张量的作用 生成掩码张量实现 注意力机制 学习目标 注意力计算规则 注意力和自注意力 注意力机制 注意力机制计算规则的代码实现 多头注意力机制 学习目标 什么是多头注意力机制 多头注意力计算机制的作用 多头注意力机…

【大模型基础_毛玉仁】1.3 基于Transformer 的语言模型

【大模型基础_毛玉仁】1.3 基于Transformer 的语言模型 1.3 基于Transformer 的语言模型1.3.1 Transformer1&#xff09;注意力层&#xff08;AttentionLayer&#xff09;2&#xff09;全连接前馈层&#xff08;Fully-connected Feedforwad Layer&#xff09;3&#xff09;层正…

Beeline的使用和Hive JDBC

目录 1. 引言1.1 Hadoop1.2 HBase1.3 Hive 2. Beeline2.1 使用Beeline访问Hive2.1.1 通过beeline直接连接Hive2.1.2 先进入beeline客户端再连接Hive2.1.3 先进入beeline客户端再连接MySQL 2.2 Beeline命令 3. Hive JDBC3.1 pom.xml中依赖配置3.2 Util工具类3.3 代码3.4 结果 参…

分布式多卡训练(DDP)踩坑

多卡训练最近在跑yolov10版本的RT-DETR&#xff0c;用来进行目标检测。 单卡训练语句&#xff08;正常运行&#xff09;&#xff1a; python main.py多卡训练语句&#xff1a; 需要通过torch.distributed.launch来启动&#xff0c;一般是单节点&#xff0c;其中CUDA_VISIBLE…

30秒从零搭建机器人管理系统(Trae)

1. 安装 [Trae官网】(https://www.trae.com.cn/) 2. 提示词 创建一个BS架构的机器人远程操控系统&#xff0c;具备机器人状态及位置实时更新&#xff0c;可以实现机器人远程遥控&#xff0c;可以对机器人工作日志进行统计分析&#xff0c;以及其它管理系统的常用功能3. 模型…

软考-数据库开发工程师-3.1-数据结构-线性结构

第3章内容比较多&#xff0c;内容考试分数占比较大&#xff0c;6分左右 线性表 1、线性表的定义 一个线性表是n个元素的有限序列(n≥0)&#xff0c;通常表示为(a1&#xff0c;a2, a3,…an). 2、线性表的顺序存储(顺序表) 是指用一组地址连续的存储单元依次存储线性表中的数据元…

解锁数据潜能,永洪科技以数据之力简化中粮可口可乐决策之路

企业数字化转型是指企业利用数字技术和信息通信技术来改变自身的商业模式、流程和增值服务&#xff0c;以提高企业的竞争力和创新能力。数字化转型已经成为企业发展的重要战略&#xff0c;尤其在当前信息技术高速发展的时代。数字化转型还涉及到企业与消费者之间的互动和沟通。…

Vue 3 整合 WangEditor 富文本编辑器:从基础到高级实践

本文将详细介绍如何在 Vue 3 项目中集成 WangEditor 富文本编辑器&#xff0c;实现图文混排、自定义扩展等高阶功能。 一、为什么选择 WangEditor&#xff1f; 作为国内流行的开源富文本编辑器&#xff0c;WangEditor 具有以下优势&#xff1a; 轻量高效&#xff1a;压缩后仅…

游戏引擎学习第137天

演示资产系统中的一个 bug 我们留下了个问题&#xff0c;你现在可以看到&#xff0c;移动时它没有选择正确的资产。我们知道问题的原因&#xff0c;就在之前我就预见到这个问题会出现。问题是我们的标签系统没有处理周期性边界的匹配问题。当处理像角度这种周期性的标签时&…

监听 RabbitMQ 延时交换机的消息数、OpenFeign 路径参数传入斜杠无法正确转义

背景 【MQ】一套为海量消息和高并发热点消息&#xff0c;提供高可用精准延时服务的解决方案 我现在有一个需求&#xff0c;就是监听 RabbitMQ 一个延时交换机的消息数&#xff0c;而 RabbitTemplate 是不存在对应的方法来获取的。 而我们在 RabbitMQ 的控制台却可以发现延时交…

大数据学习(56)-Impala

&&大数据学习&& &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 承认自己的无知&#xff0c;乃是开启智慧的大门 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4dd;支持一下博主哦&#x1f91…

开发环境搭建-01.前端环境搭建

一.整体结构 Nginx目录必须放在没有中文的目录中才能正常运行&#xff01;&#xff01;&#xff01;

Redis 常见数据类型

官方文档 RedisCommands 1&#xff09;Redis 的命令有上百个&#xff0c;如果纯靠死记硬背比较困难&#xff0c;但是如果理解 Redis 的一些机制&#xff0c;会发现这些命令有很强的通用性。 2&#xff09;Redis 不是万金油&#xff0c;有些数据结构和命令必须在特定场景下使用…

Redis7——进阶篇(三)

前言&#xff1a;此篇文章系本人学习过程中记录下来的笔记&#xff0c;里面难免会有不少欠缺的地方&#xff0c;诚心期待大家多多给予指教。 基础篇&#xff1a; Redis&#xff08;一&#xff09;Redis&#xff08;二&#xff09;Redis&#xff08;三&#xff09;Redis&#x…

云原生时代的技术桥梁

在数字化转型的大潮中&#xff0c;企业面临着数据孤岛、应用间集成复杂、高成本与低效率等问题。这些问题不仅阻碍了企业内部信息的流通和资源的共享&#xff0c;也影响了企业对外部市场变化的响应速度。当前&#xff0c;这一转型过程从IT角度来看&#xff0c;已然迈入云原生时…

ICLR 2025|香港浸会大学可信机器学习和推理课题组专场

点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入&#xff01; AITIME 01 ICLR 2025预讲会团队专场 AITIME 02 专场信息 01 Noisy Test-Time Adaptation in Vision-Language Models 讲者&#xff1a;曹晨涛&#xff0c;HKBU TMLR Group一年级博士生&#xff0c;目前关注基础…

ProfibusDP主站转ModbusTCP网关如何进行数据互换

ProfibusDP主站转ModbusTCP网关如何进行数据互换 在现代工业自动化领域&#xff0c;通信协议的多样性和复杂性不断增加。Profibus DP作为一种经典的现场总线标准&#xff0c;广泛应用于工业控制网络中&#xff1b;而Modbus TCP作为基于以太网的通信协议&#xff0c;因其简单易…

016.3月夏令营:数理类

016.3月夏令营&#xff1a;数理类&#xff1a; 中国人民大学统计学院&#xff1a; http://www.eeban.com/forum.php?modviewthread&tid386109 北京大学化学学院第一轮&#xff1a; http://www.eeban.com/forum.php?m ... 6026&extrapage%3D1 香港大学化学系夏令营&a…