Android Jetpack的新功能

As a matter of fact, Android Jetpack was inspired by the Support Library, which is a set of components to take advantage of advanced Android features; whereas, it maintains backwards compatibility. Google mentioned that it is currently used by 99% of every app in the Play Store. There have been carried out a number of works and improvements in Android Jetpack during recent years by Google. Additionally, these new libraries and features will make it easier to implement better apps. This essay aims to introduce some major enhancements and feature to existing libraries in Android Jetpack to expand their scopes.

实际上,Android Jetpack的灵感来自于支持库,该库是利用高级Android功能的一组组件。 相反,它保持了向后兼容性。 Google提到,目前Play商店中每个应用程序中有99%使用它。 近年来,Google在Android Jetpack中进行了许多工作和改进。 此外,这些新的库和功能将使实现更好的应用程序变得更加容易。 本文旨在向Android Jetpack中的现有库介绍一些主要的增强功能和功能,以扩展其范围。

简介与概述 (Introduction and Overview)

Basically, Android Jetpack is set of libraries, tools, and guidance for modern Android development. Currently, there are four categories for using Jetpack, which includes: Architecture, UI, Behavior, and Foundation. Jetpack has seen incredible adoption and momentum. At the moment, 80% of the top 1,000 apps in the Play store are using Jetpack.

基本上,Android Jetpack是一套用于现代Android开发的库,工具和指南。 当前,有四种使用Jetpack的类别,包括:体系结构,UI,行为和基础。 Jetpack的采用率和发展势头令人难以置信。 目前,Play商店中排名前1000位的应用中有80%正在使用Jetpack。

Image for post
Google Documents Google Documents提供

There have been done a number of works and improvements in Android Jetpack during these years by Google. In addition, these new libraries and features will make it easier to implement better apps. So, this article will demonstrate some major additions and features to existing libraries to expand their scopes.

近年来,Google在Android Jetpack中进行了许多工作和改进。 此外,这些新的库和功能将使实现更好的应用程序变得更加容易。 因此,本文将演示现有库的一些主要增加和功能,以扩展其范围。

击中 (Hilt)

Fundamentally, Hilt is Jetpack’s recommended dependency injection library. Dependency injection is a technique widely used in programming and well-suited to Android developments. However, dependencies are provided to a class instead of the class straight in itself. This helps diminish coupling in your codes. By using dependency injection, you get better code re-usability because of the coupling between components, and testing become much more easier since your class dependencies are well-defined. Furthermore, in the latest Android Developer Benchmark Survey by Google, 49% of the developers asked Google to work on a dependency injection solutions. As a result, Google has teamed up with the Dagger Team to create Hilt. Dagger’s dependency injection library developed by Google, and is widely adopted in the top rated android apps. However, getting started with Dagger on Android has some challenges for developers due to complexity of this library.

从根本上讲, Hilt是Jetpack推荐的依赖项注入库。 依赖注入是一种广泛用于编程的技术,非常适合Android开发。 但是,将依赖项提供给类而不是直接提供给类。 这有助于减少代码中的耦合。 通过使用依赖项注入,由于组件之间的耦合,您可以获得更好的代码可重用性,并且由于对类的依赖项进行了良好定义,因此测试变得更加容易。 此外,在Google最新的Android开发人员基准调查中,有49%的开发人员要求Google开发依赖项注入解决方案。 结果,Google与Dagger团队合作创建了Hilt。 Dagger的依赖项注入库由Google开发,并在评分最高的android应用程序中被广泛采用。 但是,由于该库的复杂性,在Android上使用Dagger入门对开发人员来说有些挑战。

Hilt is a dependency injection library for Android that reduces the boilerplate of doing manual dependency injection in your project.

Hilt是Android的依赖项注入库,它减少了在项目中进行手动依赖项注入的样板。

Hilt is an opinionated dependency injection library specifically built for Android on top of Dagger. When using Hilt, you annotate your classes with the AndroidEntryPoint annotation, and Hilt will make them inject-able. So, you can be able to use the @Inject annotation to inject your dependencies. Additionally, you can use the AndroidEntryPoint annotation in other Android components.

Hilt是一个专心致志的依赖项注入库,专门在Dagger之上为Android构建。 使用Hilt时,您可以使用AndroidEntryPoint注释对类进行注释,Hilt将使它们可注入。 因此,您可以使用@Inject批注来注入依赖项。 此外,您可以在其他Android组件中使用AndroidEntryPoint批注。

@AndroidEntryPoint
class SampleActivity : AppCompatActivity() { ... }

Hilt currently provides the following Android classes:

Hilt当前提供以下Android类:

  • Application (by using @HiltAndroidApp)

    Application (通过使用@HiltAndroidApp )

  • Activity

    Activity

  • Fragment

    Fragment

  • View

    View

  • Service

    Service

  • BroadcastReceiver

    BroadcastReceiver

Eventually, you require to annotate your Application class with the HiltAndroidApp annotation. All apps that use Hilt must include an Application class that is annotated with @HiltAndroidApp.

最终,您需要使用HiltAndroidApp注释对Application类进行注释。 所有使用Hilt的Application必须包含一个@HiltAndroidApp注释的Application类。

@HiltAndroidApp triggers Hilt's code generation, including a base class for your app, which serves as the application-level dependency container.

@HiltAndroidApp触发Hilt的代码生成,包括应用程序的基类,该类用作应用程序级依赖项容器。

@HiltAndroidApp
class SampleApplication : Application() { ... }

This generated Hilt component is attached to the Application object's lifecycle, and supports dependencies to it. Besides, it is the parent component of the app, which means that other components can be able to access the dependencies that it provides. Thus, Hilt can create the dependency graph for your Android app. The tight integration between Jetpack libraries and Hilt can help you that remodel can also be injected automatically. All you need to do is to annotate your ViewModel constructor with the ViewModelInject annotation we should ask Hilt to inject it.

此生成的Hilt组件已附加到Application对象的生命周期,并支持对其的依赖关系。 此外,它是应用程序的父组件,这意味着其他组件可以访问其提供的依赖项。 因此,Hilt可以为您的Android应用程序创建依赖关系图。 Jetpack库和Hilt之间的紧密集成可以帮助您重新建模,也可以自动注入。 您需要做的就是用ViewModelInject批注对ViewModel构造函数进行批注,我们应该让Hilt注入它。

If a dependency you want to provide needs more menu setup, you can create a Dagger module with the InstallIn annotation, and Hilt will discover it automatically. With InstallIn, you can specify the scope of dependencies provided by your module. Hilt comes with predefined scopes for Android, so you do not require to define your own for the common cases. Hilt not only decreases the code unit right, but also diminishes the mental load to get started. It also scales very well with your application as is already used by major Google apps like YouTube.

如果要提供的依赖项需要更多菜单设置,则可以创建带有InstallIn批注的Dagger模块 Hilt会自动发现它。 使用InstallIn ,可以指定模块提供的依赖项范围。 Hilt随附了适用于Android的预定义范围,因此您无需为常见情况定义自己的范围。 击键不仅减少了代码单元的权限,而且减轻了入门的精神负担。 与主要的Google应用程序(例如YouTube)已经使用的应用程序一样,它也可以很好地扩展您的应用程序。

Some benefits of using Hilt in Android apps:

在Android应用中使用Hilt的一些好处:

  1. Hilt supports a standard method to use Dependency Injection(DI) in your app by providing containers for every Android class in your project and managing their lifecycles automatically.

    通过为项目中的每个Android类提供容器并自动管理其生命周期,Hilt支持在应用程序中使用依赖注入(DI)的标准方法。

2. Hilt Contains extensions for providing classes from other Jetpack libraries. Now, Hilt supports the following Jetpack components: ViewModel and WorkManager.

2. Hilt包含用于提供其他Jetpack库中的类的扩展。 现在,Hilt支持以下Jetpack组件:ViewModel和WorkManager。

3. It has an Android Studio Integration for a more delightful developer experience.

3.它具有Android Studio集成功能,可为开发人员带来更愉悦的体验。

4. It has a well-defined scopes for android, and it also has out of the box testing APIs. Therefore, you can replace your dependencies per test with support for both Integration and Robolectric tests.

4.它具有适用于android的明确定义的作用域,并且还具有开箱即用的测试API。 因此,您可以通过支持IntegrationRobolectric来替换每个测试的依赖 测试。

5. Hilt is built on top of the popular DI library Dagger to benefit from the compile-time correctness, runtime performance, and scalability that Dagger provides.

5. Hilt建立在流行的DI库Dagger之上,以受益于Dagger提供的编译时正确性,运行时性能和可伸缩性。

应用启动 (App Startup)

As we know, Application startup time is a vital metric for any app. Users expect apps to be responsive and fast to load. When an application does not meet this expectation, it can be disappointing to users. Thus, this inappropriate experience may cause a user to rate your app badly on the Play store, or even abandon your app.

众所周知,应用程序启动时间对于任何应用程序都是至关重要的指标。 用户期望应用程序能够快速响应并快速加载。 当应用程序不符合此期望时,它会使用户感到失望。 因此,这种不适当的体验可能会导致用户在Play商店中对您的应用进行不良评价,甚至放弃您的应用。

Most of these libraries use Content Provides to initialize automatically, including some Jetpack libraries like WorkManager and Lifecycle. The cost of creating Content Providers has been investigated by Google. They noticed each of them adds at least two milliseconds on a pixel to a device running Android 10. This is just only the cost of Content Providers not the work library does. Jetpack App Startup is a library that provides a straightforward, performant way to initialize components at application startup. So, both library developers and app developers can be able to use App Startup to streamline startup sequences and explicitly set the order of initialization.

这些库中的大多数都使用Content Provides来自动初始化,包括一些Jetpack库,如WorkManager和Lifecycle。 Google已调查了创建内容提供商的费用。 他们注意到,每个像素向运行Android 10的设备增加至少2毫秒的像素。这只是内容提供者的成本,而工作库则不然。 Jetpack App Startup是一个库,提供了一种简单,高效的方法来在应用程序启动时初始化组件。 因此,库开发人员和应用程序开发人员都可以使用App Startup简化启动顺序并显式设置初始化顺序。

Here is an example of an initializer component that configures WorkManager. It extends the initializer API specifying its type, and when crate is called, it simply initialize WorkManager and returns the instance.

这是配置WorkManager的初始化程序组件的示例。 它扩展了初始化程序API并指定了它的类型,当调用crate时,它只是初始化WorkManager并返回实例。

class WorkManagerInitializer : Initializer<WorkManager> {
override fun create(context: Context): WorkManager {
val configuration = Configuration.Builder()
.setMinimumLoggingLevel(Log.DEBUG)
.build()
WorkManager.initialize(context, configuration)
return WorkManager.getInstance(context)
}

// This component does not have any dependencies
override fun dependencies() = emptyList<Class<out Initializer<*>>>()
}

Alternatively, the initializer component can also define its dependencies. So that the Startup library will initialize dependencies before initializing our component. Under the hood, the Startup library uses a single Content Provider shared between all these initializers reducing the application startup time. As a result, the App Startup library can be used by both application and developer to streamline startup. It provides lazy initialization to further improve Application Startup Performance by completing avoiding the Content Provider. In addition, it automatically adds traces points for every initializer. This way of components being initialized at application launch using tools like Systrace and Perfetto.

或者,初始化器组件也可以定义其依赖项。 这样,启动库将在初始化组件之前初始化依赖项。 在后台,启动库使用所有这些初始化程序之间共享的单个Content Provider,从而减少了应用程序的启动时间。 结果,应用程序和开发人员都可以使用App Startup库来简化启动过程。 它提供了惰性初始化,可以通过避免使用内容提供程序来进一步提高应用程序启动性能。 此外,它会自动为每个初始化程序添加跟踪点。 组件的这种方式被使用像Systrace普菲工具在应用程序启动初始化。

Android游戏SDK (Android Game SDK)

To make game development easier, Google launched the Android Game SDK earlier this year. This includes a set of libraries that are designed to help you enhance your game performance across various devices. It has been available on the Android website, and is considered as a part of the Jetpack family now. Also, it is available on Google’s Maven repository. The SDK currently contains two important features. The Android Frame Pacing library allows games to keep a steady frame rate and can lower a game’s input latency. The library detects the expected frame rate and auto adjusts frame presentation times accordingly. Android Performance Tuner enables you to measure and optimize your frame rate at scale across the whole Android ecosystem. You also get new performance insights in Android vitals, designed specifically for game developers, by integrating Android Performance Tuner into your game. Currently, this feature is available as Alpha on the Google Play Maven Repository.

为了简化游戏开发,Google在今年初推出了Android Game SDK 。 其中包括一组旨在帮助您在各种设备上增强游戏性能的库。 它已在Android网站上提供,并且现在被视为Jetpack系列的一部分。 另外,它在Google的Maven存储库中可用。 该SDK当前包含两个重要功能。 Android Frame Pacing库可让游戏保持稳定的帧频并降低游戏的输入延迟。 磁带库检测到预期的帧速率并相应地自动调整帧显示时间。 Android Performance Tuner使您能够在整个Android生态系统中大规模测量和优化帧速率。 通过将Android Performance Tuner集成到您的游戏中,您还将获得专为游戏开发人员设计的Android vitals中的新性能见解。 目前,此功能可以在Google Play Maven存储库中以Alpha形式使用。

基准1.1 (Benchmark 1.1)

The Jetpack Benchmark library allows you to quickly benchmark your Kotlin-based or Java-based code from within Android Studio. The library handles warm-up, measures your code performance and allocation counts, and outputs benchmarking results to both the Android Studio console and a JSON file with more detail. The new release for the Benchmarking library has been done by Google recently. It integrates with the CPU Profiler. Thus, you can profile your benchmarks, and then weave the method, or sample trace it right in Android Studio. We have also added support for memory allocation tracking. So. You can optimize the time spent for allocations and reduce a lot on garbage collection.

通过Jetpack Benchmark库,您可以在Android Studio中快速对基于Kotlin或Java的代码进行基准测试。 该库处理预热,测量代码性能和分配计数,并将基准测试结果输出到Android Studio控制台和更详细的JSON文件 。 基准测试库的新版本最近由Google完成。 它与CPU Profiler集成在一起。 因此,您可以剖析基准测试,然后编织该方法,或者直接在Android Studio中进行示例跟踪。 我们还增加了对内存分配跟踪的支持。 所以。 您可以优化分配时间,并减少大量垃圾回收。

分页3 (Paging 3)

Initially, Paging is a library that helps you load and displays small amounts of data incrementally. Paging 3 completely right off the library using Kotlin Coroutines, and adds highly requested features like Separators. This is the center of the Paging where we connect at our back-end.

最初,分页是一个可帮助您加载和增量显示少量数据的库。 使用Kotlin Coroutines在库中完全分页3 ,并增加了诸如Separators之类的功能。 这是我们在后端连接的分页中心。

The Paging library helps you load and display pages of data from a larger dateset from local storage or over network. This approach allows your app to use both network bandwidth and system resources more efficiently.

分页库可帮助您从本地存储或通过网络加载和显示较大日期集的数据页面。 这种方法使您的应用可以更有效地使用网络带宽和系统资源。

We extend this PagingSource class, which is a single method that we need implemented. Here we call our API to get the result and return the page. If something goes wrong, we return an error result to notify Paging that an expected error has happened. Once you have the PagingSource, you can create a Pager, provided with the configuration of our page size, and get the flow out of it. Finally, UI layer, we collect from this flow and pass the values into our paging adapter. That adapter will take care of displaying the data for us.

我们扩展了PagingSource类,这是我们需要实现的单个方法。 在这里,我们调用API以获取结果并返回页面。 如果出现问题,我们将返回错误结果,以通知Paging发生了预期的错误。 一旦有了PagingSource,就可以创建一个分页器,提供我们页面大小的配置,并从中获取流程。 最后,在UI层,我们从该流中收集并将这些值传递到我们的分页适配器中。 该适配器将负责为我们显示数据。

class DoggosRemotePagingSource(
val backend: GoodDoggosService
) : PagingSource<Int, Dog>() {
override suspend fun load(
params: LoadParams<Int>
): LoadResult<Int, Dog> {
try {
// Load page 1 if undefined.
val nextPageNumber = params.key ?: 1
val response = backend.getDoggos(nextPageNumber)
return LoadResult.Page(
data = response.doggos,
prevKey = null, // Only paging forward.
nextKey = response.nextPageNumber + 1
)
} catch (e: Exception) {
// Handle errors in this block
return LoadResult.Error(exception)
}
}
}

Paging is rewritten from the ground up with Kotlin Coroutines and Flow. It has built-in API at headers, footers or separators. Besides, you can even do other transformations like mapping items filtering. Finally, Paging 3 is fully backwards compatible with Paging 2 to help you migrate easily. At the moment, it is available as Alpha version.

使用Kotlin Coroutines和Flow从头开始重新编写分页。 它在页眉,页脚或分隔符处具有内置的API。 此外,您甚至可以进行其他转换,例如映射项过滤。 最后,分页3与分页2完全向后兼容,以帮助您轻松迁移。 目前,它可以作为Alpha版本使用。

相机X (CameraX)

As you know, creating real time filters was a difficult task some years ago. Basically, CameraX is a Jetpack library that makes integrating camera into your application very easy and reliable. It reached Beta last February, and Google has focused on reliability and documentation before reaching the stable version. CameraX runs on 90% of Android devices, which means there is a number of variety in terms of performance and feature. PreviewView is a widget that displays the camera preview in your application. Currently, it manages interactions with your app lifecycle via pages reliably. Besides, it optimized transparently your surface view under the hood on devices, which will benefit from its performance enhancements. This provides less buffering and better power efficiency. Google has also focused on providing more guidelines to make it easier to use CameraX. They added the sample for YUV to RGB conversion to do image analysis in more familiar formats. As a result, you can easily integrate it with libraries like in AppKit. Other samples are created including OpenGL and rotation handling.

如您所知,几年前创建实时过滤器是一项艰巨的任务。 基本上,CameraX是一个Jetpack库,可以使相机轻松,可靠地集成到您的应用程序中。 它于去年2月达到Beta版,在稳定版发布之前,Google一直专注于可靠性和文档编制。 CameraX可在90%的Android设备上运行,这意味着在性能和功能上有多种选择。 PreviewView是一个小部件,可在您的应用程序中显示相机预览。 当前,它通过页面可靠地管理与您的应用程序生命周期的交互。 此外,它透明地优化了设备引擎盖下的表面视图,这将受益于其性能增强。 这样可以减少缓冲,提高电源效率。 Google还致力于提供更多指南,以简化CameraX的使用。 他们添加了用于YUV到RGB转换的样本,以更熟悉的格式进行图像分析。 因此,您可以轻松地将其与AppKit中的库集成。 创建的其他示例包括OpenGL和旋转处理。

工作经理 (WorkManager)

In fact, WorkManager is the Jetpack library that allows you to run deferrable background jobs like sending your very important email when the user is connected to the Internet. WorkManager does not only rely on JobScheduler to execute your jobs, it also has in-process scheduler trying your workers, and Google has dramatically improved it during this year. Now, It provides delayed workers and periodic work requests. The scheduler also no longer imposes scheduling limits, which enhances the throughput of your work requests. WorkManager supports long-running or significant work that should be kept alive by the Operating System.

实际上, WorkManager是Jetpack库,它允许您运行可延迟的后台作业,例如在用户连接到Internet时发送非常重要的电子邮件。 WorkManager不仅依靠JobScheduler来执行您的工作,而且还具有进程内调度程序来尝试您的工作人员,并且Google在今年大大改进了它。 现在,它提供了延迟的工人和定期的工作要求。 调度程序也不再施加调度限制,这可以提高工作请求的吞吐量。 WorkManager支持应由操作系统保留的长期运行或重要工作。

WorkManager is an API that makes it easy to schedule deferrable, asynchronous tasks that are expected to run even if the app exits or the device restarts.

WorkManager是一种API,即使应用程序退出或设备重新启动,也可以轻松地计划运行的异步任务

Sometimes it would be difficult to know why a worker did not run when you expected it to run. For these cases, Google has represent the new feature called Diagnostics API that you can invoke with adb to peek into the internal state of WorkManager. When invoked, WorkManager will dump its current state into Logcat, which we can simply view via an adb Logcat command. Additionally, to identify some mistakes, Google has added lead rules to catch these mistakes by using Lint checks as some warnings. Therefore, the Android Studio can immediately inform you if that occurs in your codebase.

有时很难知道为什么工人在您期望的时候没有运行。 对于这些情况,Google代表了称为Diagnostics API的新功能,您可以使用adb调用它以窥探WorkManager的内部状态。 调用时,WorkManager会将其当前状态转储到Logcat中,我们可以通过adb Logcat命令简单地查看它。 此外,为了识别一些错误,Google添加了线索规则,以使用Lint检查作为一些警告来捕获这些错误。 因此,Android Studio可以立即通知您代码库中是否发生了这种情况。

导航 (Navigation)

As a matter of fact, the Navigation library allows you to navigate between various screens of your app with ease while also following Android UI principles.

事实上, 导航库使您可以轻松地在应用程序的各个屏幕之间导航,同时还遵循Android UI原则。

Navigation refers to the interactions that allow users to navigate across, into, and back out from the different pieces of content within your app. Android Jetpack’s Navigation component helps you implement navigation, from simple button clicks to more complex patterns, such as app bars and the navigation drawer.

导航是指允许用户在应用程序中的不同内容之间进行浏览,浏览和退出的交互。 Android Jetpack的Navigation组件可帮助您实现导航,从简单的按钮单击到更复杂的模式,例如应用程序栏和导航抽屉。

In Navigation 2.3, Google has added support for dynamic feature modules, which allows you to download pieces of your application as the user needs it. This significantly reduce the initial download size of your application. The integration with the Navigation component can provide you to navigate to these modules as if they are part of your base APK. All you need to do is to annotate your fragments with the module name. So, Navigation library will support the downloading if it is necessary before moving to that screen. In addition, a number improvements have been made to the Deep Linking feature in Navigation. Now, you can easily access query parameters, provide custom actions, and specify mime types. Finally, Returning a Result feature, In Navigation 2.3, now each screen in your application has a NavBackStackEntry, which gives you access to the same state of that entry as well. To ensure your results are kept over configuration changes or process that Navigation uses the savedStateHandle class to pass data between screens. Your fragments can access the previous fragment savedStateHandle by using the previous BackStackEntry. Once you obtain the savedStateHandle from the previous entry, you can set the result values on the SavedState. To observe the result, you can get the same value from the SavedState of the currentBackStackEntry and observe the value without LiveData. In this way, observation is considered as Lifecycle aware because we are using SavedState, it works even if your application’s restarted between these two screens.

在Navigation 2.3中,Google添加了对动态功能模块的支持,该功能使您可以根据用户需要下载应用程序的各个部分。 这样可以大大减少应用程序的初始下载大小。 与Navigation组件的集成可以为您提供导航到这些模块的机会,就像它们是您的基本APK的一部分一样。 您需要做的就是用模块名称注释片段。 因此,如果需要,导航库将支持下载,然后再移至该屏幕。 此外,对导航中的深层链接功能进行了许多改进。 现在,您可以轻松访问查询参数,提供自定义操作并指定mime类型。 最后,返回结果功能,在Navigation 2.3中,现在应用程序中的每个屏幕都有一个NavBackStackEntry ,它使您也可以访问该条目的相同状态。 为了确保在配置更改或导航过程中导航保持使用vededStateHandle类在屏幕之间传递数据,可以保留结果。 您的片段可以使用先前的BackStackEntry访问先前的片段savedStateHandle 。 一旦从上一个条目中获取了savedStateHandle,就可以在SavedState上设置结果值。 要观察结果,您可以从currentBackStackEntry的SavedState获取相同的值,并观察不带LiveData的值。 通过这种方式,观察被认为是生命周期感知的,因为我们正在使用SavedState ,即使您的应用程序在这两个屏幕之间重新启动,它也可以工作。

结论 (In conclusion)

In fact, Android Jetpack is set of libraries, tools, and guidance for advanced Android development. Currently, there are four categories for using Jetpack, which includes: Architecture, UI, Behavior, and Foundation. There have been carried out a number of works and enhancements in Android Jetpack during recent years by Google. This article considered some new features and improvements in recent months in Android Jetpack.

实际上,Android Jetpack是一套用于高级Android开发的库,工具和指南。 当前,有四种使用Jetpack的类别,包括:体系结构,UI,行为和基础。 近年来,Google在Android Jetpack中进行了许多工作和增强。 本文考虑了最近几个月Android Jetpack中的一些新功能和改进。

翻译自: https://medium.com/kayvan-kaseb/the-new-features-in-android-jetpack-39d709a1d035

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值