/   今日科技快讯   /

近日,电动汽车制造商特斯拉公布了2021年第三季度财报。财报显示,特斯拉第三季度营收137.6亿美元,同比增长57%;净利润16.2亿美元,同比增长389%;每股收益1.86美元,与去年同期相比增长145%。

/   作者简介   /

明天就是开心的周末了,祝大家周五愉快,我们下周再见。

本篇文章转载自TechMerger的博客,文章主要分享了Android 12上AppWidget的变化,相信会对大家有所帮助!

原文地址:

https://juejin.cn/post/6968851189190377480

/   前言   /

Google IO 2021上重磅介绍的Android 12,号称历代设计变化最大的版本。其全新的Material You设计语言、流畅的动画特效再到焕然一新的小组件,都令人印象深刻。本文将聚焦小组件环节,谈谈它在重新设计之后的各种新特性和适配方法。

小组件在Android平台上命名为AppWidget,有的时候还被翻译成小部件、小插件和微件。说的都是一个东西:显示在Launcher上,能在Logo以外提供更多信息的特别设计。它方便用户免于打开App即可直接查看信息和进行简单的交互,在PC上、早前的Symbian上都有类似的设计。

简要回顾下移动平台在小组件设计上的持续探索:

  • 早期的Android版本缺乏美观,小组件更是常年未改。似乎除了天气、时钟等常用小组件以外鲜少使用,逐渐被人遗忘

  • Windows Phone的动态磁贴在自由尺寸的Logo上灵活展示信息的设计非常超前,奈何生态构建困难,早已退场

  • Apple向来稳重(保守),直到iOS 10才引入小组件,但负一屏限制着它的发展。直到iOS 14的全面支持才大获成功,大有后来居上的态势

  • VIVO紧随其后重磅推出的OriginOS则将Logo和小组件完美融合,试图一统磁贴和小组件的概念,非常值得称赞

也许是受到了友商们的持续刺激,Google终于开始重新审视小组件这个元老级功能,并在Android 12里进行了重新设计、重新出发。

下面将结合代码实战,带领大家逐步感受Android 12里小组件的各项新特性和对应的适配方法。

/   选择和展示   /

事实上即使未做任何适配,在12上直接运行的小组件与11就有明显不同,主要表现在选择器和展示的效果。

以Chrome和Youtube Music的小组件为例:

可以看到12上的一些变化:

  • 选择器

  • 顶部悬浮搜索框,可以更加快速地找到目标小组件

  • 小组件按照App自动折叠,避免无关的小组件占用屏幕空间

  • App标题还对包含的小组件数目进行了提示

  • 拖拽到桌面上之后小组件默认拥有圆角设计

11上的小组件选择器不支持搜索而且无法折叠,拖拽到桌面上也是初始的直角效果。

/   圆角设计   /

健康信息越发重要,手撸一个展示今日步数的小组件,搭配androidplot框架展示详细的步数图表。

override fun onUpdate(...) {for (appWidgetId in appWidgetIds) {showBarChartToWidget(context, appWidgetManager, appWidgetId)}
}private fun showBarChartToWidget(...) {// Create plot view.val plot = XYPlot(context, "Pedometers chart")...// Set graph shapeplot.setBorderStyle(Plot.BorderStyle.ROUNDED, 12f, 12f)plot.isDrawingCacheEnabled = true// Reflect chart's bitmap to widget.val bmp = plot.drawingCacheval remoteViews = RemoteViews(context.packageName, R.layout.widget_pedometer)remoteViews.setBitmap(R.id.bar_chart, "setImageBitmap", bmp)appWidgetManager.updateAppWidget(appWidgetId, remoteViews)
}

不用特别适配,直接运行到12上,就能有圆角效果。

但布局需要遵从如下两点建议:

  • 四周的边角不要放置内容,防止被切掉

  • 背景不要采用透明的、空的视图或布局,避免系统无法探测边界去进行裁切

事实上,系统预设了如下dimension以设置默认的圆角表现。

  • system_app_widget_background_radius: 小组件背景的圆角尺寸,默认16dp,上限28dp

  • system_app_widget_inner_radius: 小组件内部视图的圆角尺寸 ,默认8dp,上限20dp

  • system_app_widget_internal_padding:内部视图的padding值,默认16dp

看下官方的对于内外圆角尺寸的示意图。

注意:

  1. 这些dimension可以被ROM厂商或3rd Launcher修改,不一定能保证一致性的尺寸

  2. 官方没有说明小组件的内部视图如何才能应用上内部圆角尺寸,DEMO确实也没有适配上,不知道是ROM的问题还是App的问题,有待后续的进一步研究

当然12以前的系统想要支持圆角设计也很简单:自定义radius的attribute,应用在shape drawable上,手动将drawable应用到background。具体可参考官方Sample:

https://github.com/android/user-interface-samples/tree/main/AppWidget

/   动态色彩效果   /

给小组件添加暗黑主题支持即可自动适配动态色彩。

<!-- values/themes.xml -->
<resources xmlns:tools="http://schemas.android.com/tools"><style name="Theme.AppWidget" parent="Theme.MaterialComponents.DayNight.DarkActionBar"><item name="colorPrimary">@color/purple_500</item><item name="colorPrimaryVariant">@color/purple_700</item><item name="colorOnPrimary">@color/white</item>...</style>
</resources><!-- values-night/themes.xml -->
<resources xmlns:tools="http://schemas.android.com/tools"><style name="Theme.AppWidget" parent="Theme.MaterialComponents.DayNight.DarkActionBar"><item name="colorPrimary">@color/purple_200</item><item name="colorPrimaryVariant">@color/purple_700</item><item name="colorOnPrimary">@color/black</item>...</style>
</resources>

/   预览改进   /

12针对小组件选择时的预览界面进行了改进,方便展示更加精准的预览效果。

动态预览

之前只能使用previewImage属性展示一张预览图,功能迭代的过程中忘记更新它的话,可能导致预览和实际效果发生偏差。

12新引入了previewLayout属性用以配置小组件的实际布局,使得用户能够在小组件的选择器里看到更加接近实际效果的视图,而不再是一层不变的静态图片。

这样一来在保证效果一致的同时免去了额外维护预览图的麻烦。

<appwidget-provider<!-- 既存的图片属性指定UI提供的设计图 -->android:previewImage="@drawable/app_widget_pedometer_preview_2"<!-- 新的预览API里指定实际的布局 -->android:previewLayout="@layout/widget_pedometer"
</appwidget-provider>

左边是步数小组件一开始的设计图,右边是最后的实际效果。

如果忘记说服UI重新作图的话,在11上的预览图会和实际效果有较大偏差。而12上不用在乎设计图是否更新,借助新的API即可直接预览实际效果,所见即所得。

一般来说previewLayout属性最好指定小组件的实际布局。但如果预览的测试数据和实际的默认值有冲突的话,可以指定专用的预览布局,只需要确保布局的一致。

添加预览说明

description属性则可以在小组件预览的下方展示额外的说明,便于用户更好地了解其功能定位。

<appwidget-providerandroid:description="@string/app_widget_pedometer_description">
</appwidget-provider>

需要提醒的是description属性并非12新增,但12之前的选择器不支持展示这个说明。

/   新的交互控件   /

之前的小组件不支持CheckBox等控件,从12开始全面支持CheckBox、Switch和RadioButton三种状态控件。

下面是采用这三种控件的简单效果。

再做个简单的待办事项以更好地说明状态小组件的使用。

// 小组件件布局里指定CheckBox控件即可
<LinearLayout ...android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:theme="@style/Theme.AppWidget.AppWidgetContainer"><include layout="@layout/widget_todo_list_title_region" /><CheckBoxandroid:id="@+id/checkbox_first"style="@style/Widget.AppWidget.Checkbox"android:layout_width="match_parent"android:layout_height="wrap_content"android:text="@string/todo_list_sample_1"Tools:text="@string/todo_list_tool" />...
</LinearLayout>

如果将同样的代码运行到11上,则会显示加载失败。日志:

AppWidgetHostView: Error inflating AppWidget AppWidgetProviderInfo(UserHandle{0}/ComponentInfo{com.example.splash/com.example.splash.widget.TodoListAppWidget}): android.view.InflateException: Binary XML file line #13 in com.example.splash:layout/widget_todo_list: Binary XML file line #13 in com.example.splash:layout/widget_todo_list: Error inflating class android.widget.CheckBox

文本内容不确定的话,可以通过代码动态地控制文本,同时还可以监听用户的选择事件。

比如我们要展示Android开发者如今要学习的三座大山,选中的时候弹出Toast。

private fun updateAppWidget(...) {val viewId1 = R.id.checkbox_firstval pendingIntent = PendingIntent.getBroadcast(...)val rv = RemoteViews(context.packageName, R.layout.widget_todo_list)rv.apply {// 设置文本setTextViewText(viewId1, context.resources.getString(R.string.todo_list_android))...// 设置CheckBox的默认选中状态setCompoundButtonChecked(viewId1, true)// 监听相应的CheckBox的选中事件setOnCheckedChangeResponse(viewId1,RemoteViews.RemoteResponse.fromPendingIntent(pendingIntent))}appWidgetManager.updateAppWidget(appWidgetId, remoteViews)
}override fun onReceive(context: Context?, intent: Intent?) {...val checked = intent.extras?.getBoolean(RemoteViews.EXTRA_CHECKED, false) ?: falseval viewId = intent.extras?.getInt(EXTRA_VIEW_ID) ?: -1Toast.makeText(context,"ViewId : $viewId's checked status is now : $checked",Toast.LENGTH_SHORT).show()
}

/   便捷配置尺寸   /

12针对小组件的尺寸配置环节也进行了改进,更加便捷。

精确的尺寸

在已有的minWidth、minResizeWidth等属性以外,新增了几个属性以更便捷地配置小组件的尺寸。

  • targetCellWidth和targetCellHeight:占据Launcher上Cell的宽高格数,用以替代minWidth和minHeight。事实上Launcher是以Cell的单位来展示小组件的,所以直接指定Cell数显然更合理

  • maxResizeWidth和maxResizeHeight: 配置Launcher上允许配置的最大尺寸,弥补minResizeWidth和minResizeHeight的不足

<appwidget-provider...android:targetCellWidth="3"android:targetCellHeight="2"android:maxResizeWidth="250dp"android:maxResizeHeight="110dp">
</appwidget-provider>

灵活调节尺寸

iOS上添加小组件后尺寸就固定了,不支持调节。而Android 12上小组件在长按后即可灵活调节。

想要支持这个特性只需要给widgetFeatures属性指定reconfigurable值即可。

<appwidget-providerandroid:widgetFeatures="reconfigurable">
</appwidget-provider>

The reconfigurable flag was introduced in Android 9 (API level 28), but it was not widely supported in launchers until Android 12.

事实上这个属性早在Android 9的时候就引入了,但官方说从S开始才全面支持。我在11版本的Pixel Launcher上发现已经可以直接调节尺寸了,不知道官方的意思是不是别的Launcher并不支持。

采用默认配置

configure属性可以在小组件展示之前启动一个配置画面,供用户选择小组件所需的内容、主题和风格等。

如果想让用户快速看到效果,即不想展示这个画面的话,只要在widgetFeatures里指定新的configuration_optional值即可。

<appwidget-provider...android:configure="com.example.appwidget.activity.WidgetConfigureActivity"android:widgetFeatures="reconfigurable|configuration_optional">
</appwidget-provider>

后面改主意了又想替换配置的话,可以长按小组件找到配置的入口。

一是小组件右下方的编辑按钮,二是上方出现的Setup菜单,这在以前的版本上是没有的。

/   高效控制布局   /

小组件内容较多的时候,为了展示的完整往往会给它限定Size,这意味着只有Launcher空间足够大小组件才能成功放置。当Launcher空间捉急的时候就尴尬了,用户只能在移除别的小组件和放弃你的小组件之间做个抉择。

免除这种困扰的最佳做法是在不同的Size下采用不同的布局,对展示的内容做出取舍。即Size充足的情况下提供更多丰富的内容,反之只呈现最基本、最常用的信息。

响应式布局

之前是如何做到这一需求呢?除了预设各种尺寸的小组件的一般思路以外,通过onAppWidgetOptionsChanged回调也可以控制布局的变化,但往往非常繁琐。

而12上借助新增的RemoteViews(Map<SizeF, RemoteViews> map)API可以大大简化实现过程。在小组件放置的时候就将Size和布局的映射关系告知系统,当Size变化了AppWidgetManager将自动响应更新对应的布局。

比如待办事项小组件在Size为3x2的时候额外展示添加按钮,2x2的时候只展示事项列表的相应式布局。

代码的实现也简单清晰:

private fun updateAppWidgetWithResponsiveLayouts(...) {...// 尺寸够宽的情况下Button才显示val wideView = RemoteViews(rv)wideView.setViewVisibility(button, View.VISIBLE)val viewMapping: Map<SizeF, RemoteViews> = mapOf(SizeF(100f, 100f) to rv,SizeF(200f, 100f) to wideView)// 将Size和RemoteViews布局的映射关系告知AppWidgetManagerval remoteViews = RemoteViews(viewMapping)appWidgetManager.updateAppWidget(appWidgetId, remoteViews)
}

好处:

  • 免于同一功能提供一堆尺寸小组件的繁琐,减轻选择器的负担

  • 实现简单,自动响应

精确布局

如今移动设备的尺寸、形态丰富多样,尤其是折叠屏愈加成熟。如果响应式布局仍不能满足更精细的需求,可以在Size变化的回调里,获取目标Size对布局进一步的精确把控。

利用AppWidgetManager新增的OPTION_APPWIDGET_SIZES KEY可以从AppWidgetManager里拿到目标Size。

// 监听目标尺寸
override fun onAppWidgetOptionsChanged(...) {...// Get the new sizes.val sizes = newOptions?.getParcelableArrayList<SizeF>(AppWidgetManager.OPTION_APPWIDGET_SIZES)// Do nothing if sizes is not provided by the launcher.if (sizes.isNullOrEmpty()) {return}Log.d("Widget", "PedometerAppWidget#onAppWidgetOptionsChanged() size:${sizes}")// Get exact layoutif (BuildCompat.isAtLeastS()) {val remoteViews = RemoteViews(sizes.associateWith(::createRemoteViews))appWidgetManager?.updateAppWidget(appWidgetId, remoteViews)}
}

如下的日志显示Size变化的时候会将目标Size回传。

Widget  : PedometerAppWidget#onAppWidgetOptionsChanged() size:[377.42856x132.0, 214.57143x216.57143]

之后从预设的精细布局里匹配相应的视图。

private fun createRemoteViews(size: SizeF): RemoteViews {val smallView: RemoteViews = ...val tallView: RemoteViews = ...val wideView: RemoteViews = ......return when (size) {SizeF(100f, 100f) -> smallViewSizeF(100f, 200f) -> tallViewSizeF(200f, 100f) -> wideView...}
}

注意:实际上Size列表由Launcher提供,如果3rd Launcher没有适配这一特性的话,回传的Size可能为空

/   自由更新视图   /

RemoteViews作为小组件视图的重要管理类,本次OSV也添加了诸多API,以便更加自由地控制视图的展示。

  • 更改颜色的setColorStateList()

更改边距的setViewLayoutMargin()

更改宽高的setViewLayoutWidth()等

这些新API可以助力我们实很多方便的功能,比如CheckBox选中之后更新文本颜色,思路很简单:

  1. 监听小组件的点击事件并传递目标视图

  2. 根据CheckBox的状态获得预设的文本颜色

  3. 使用setColorStateList()更新

override fun onReceive(context: Context?, intent: Intent?) {...// Get target widget.val appWidgetManager = AppWidgetManager.getInstance(context)val thisAppWidget = ComponentName(context!!.packageName, TodoListAppWidget::class.java.name)val appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidget)// Update widget color parameters dynamically.for (appWidgetId in appWidgetIds) {val remoteViews = RemoteViews(context.packageName, R.layout.widget_todo_list)remoteViews.setColorStateList(viewId,"setTextColor",getColorStateList(context, checked))appWidgetManager.updateAppWidget(appWidgetId, remoteViews)}
}private fun getColorStateList(context: Context, checkStatus: Boolean): ColorStateList =if (checkStatus) ColorStateList.valueOf(context.getColor(R.color.widget_checked_text_color))else ColorStateList.valueOf(context.getColor(R.color.widget_unchecked_text_color))

再比如Chart线图太小,看不清楚。可以让它在点击之后放大,再点击之后恢复原样。

// 根据记录的缩放状态获得预设的宽高
// 通过setViewLayoutWidth和setViewLayoutHeight更新宽高
override fun onReceive(context: Context?, intent: Intent?) {...val widthScaleSize = if (scaleOutStatus) 200f else 260fval heightScaleSize = if (scaleOutStatus) 130f else 160f// Update widget layout parameters dynamically.for (appWidgetId in appWidgetIds) {val remoteViews = RemoteViews(context.packageName, R.layout.widget_pedometer)remoteViews.setViewLayoutWidth(viewId, widthScaleSize, TypedValue.COMPLEX_UNIT_DIP)remoteViews.setViewLayoutHeight(viewId, heightScaleSize, TypedValue.COMPLEX_UNIT_DIP)appWidgetManager.updateAppWidget(appWidgetId, remoteViews)}
}

/   流畅启动效果   /

12版本上点击Widget启动App的时候可以呈现更流畅的过渡效果,适配也很简单。官方指示只需给小组件的根布局指定android的 backgoround id即可。

<LinearLayout...android:id="@android:id/background">
</LinearLayout>

实际的动作显示添加这个ID后App启动没有什么变化,个中原因需要继续研究。

12开始对从Broadcast Receiver或Serivce启动Activity做了更严格的限制,但不包括Widget发起的场合。但为了避免视觉上的突兀,这种后台启动的情况下不展示迁移动画。

/   简化数据绑定   /

小组件里展示ListView的需求也很常见,提供数据的话需要声明一个 RemoteViewsService 以返回RemoteViewsFactory,比较绕。

而12里新增的 setRemoteAdapter(int , RemoteCollectionItems) API则可以大大简化这个绑定过程。

比如制作一个即将到来的事件列表小组件,通过这个API便可以高效注入数据。

private fun updateCountDownList(...) {...// 创建用于构建Remote集合数据的Builderval builder = RemoteViews.RemoteCollectionItems.Builder()val menuResources = context.resources.obtainTypedArray(R.array.count_down_list_titles)// 往Builder里添加各Item对应的RemoteViewsfor (index in 0 until menuResources.length()) {...builder.addItem(index.toLong(), constructRemoteViews(context, resId))}// 构建Remote集合数据// 并通过setRemoteAdapter直接放入到ListView里val collectionItems = builder.setHasStableIds(true).build()remoteViews.setRemoteAdapter(R.id.count_down_list, collectionItems)...
}// 创建ListView各Item对应的RemoteViews
private fun constructRemoteViews(...): RemoteViews {val remoteViews = RemoteViews(context.packageName, R.layout.item_count_down)val itemData = context.resources.getStringArray(stringArrayId)// 遍历Item数据行设置对应的文本itemData.forEachIndexed { index, value ->val viewId = when (index) {0 -> R.id.item_title1 -> R.id.item_time...}remoteViews.setTextViewText(viewId, value)}return remoteViews
}

如果Item的布局不固定不止一种,可以使用setViewTypeCount指定布局类型的数目,告知ListView需要提供的ViewHolder种类。如果不指定也可以,系统将自动识别布局的种类,需要系统额外处理而已。

但要注意:如果指定的数目和实际的不一致会引发异常。

IllegalArgumentException: View type count is set to 2, but the collection contains 3 different layout ids

另外,需要补充一下,支持该API的View必须是AdapterView的子类,比如常见的ListView、GridView等。RecyclerView是不支持的,毕竟小组件里数据量不多,不能使用也没关系。

/   新增API总结   /

简要罗列一下12针对小组件新增的API,方便大家查阅。

/   结语   /

通过上面的解读,大家可以感受到Google在小组件的重新设计上耗费了诸多努力,它给这个老旧的功能注入很多新玩法和新花样。

简要回顾一下Android 12里小组件的新特性:

  • 更便捷的小组件选择器

  • 更美观的圆角边框设计

  • 更灵活的小组件预览

  • 更完整的控件支持

  • 更方便的尺寸调节

  • 更精准的布局控制

  • 更自由的视图更新

  • 更简便的列表数据绑定

如此之多的新特性,在助力小组件高效开发的同时,还能给用户呈现更加优秀的使用体验。

跟随Android 12的脚步,快快尝试起来,让现有的小组件重新绽放光彩。

未决事项

1. 小组件内部视图的圆角尺寸如何适配?

2. 小组件启动App的流畅过渡效果如何实现,是什么效果?

Demo地址:

https://github.com/ellisonchan/NewAppWidget

推荐阅读:

Button的“进化之旅”

PermissionX 1.6发布,支持Android12

Android 12 正式发布 | 开发者们的全新舞台

欢迎关注我的公众号

学习技术或投稿

长按上图,识别图中二维码即可关注

Android 12上焕然一新的小组件相关推荐

  1. Android 12上焕然一新的小组件:美观、便捷和实用

    Google IO 2021上重磅介绍的Android 12,号称历代设计变化最大的版本.其全新的Material You设计语言.流畅的动画特效再到焕然一新的小组件,都令人印象深刻.本文将聚焦小组件 ...

  2. Probe:Android线上OOM问题定位组件

    配送骑手端App是骑手用于完成配送履约的应用,帮助骑手完成接单.到店.取货及送达,提供各种不同的运力服务,也是整个外卖闭环中的重要节点.由于配送业务的特性,骑手App对于应用稳定性的要求非常高,体现A ...

  3. Android 12上无法调用setDisplaySurface

    app_process在使用反射的方法调用setDisplaySurface方法时,对于新的手机会出问题. 使用的时候,机型是小米12,当时以为是miui13的问题,因为其余的华为.蓝厂和绿厂都运行的 ...

  4. android ge模拟器,在Android模拟器上的一些小陷阱

    从Android SDK R17开始,模拟器就支持OpenGL ES 2.如果能让KlayGE在模拟器上跑起来,开发和测试就能方便许多.于是我装了最新的R21和Android 2.1的ARM v7a的 ...

  5. Android平台 Target API level 升级到 31,在Android 12上启动黑屏卡死

    项目的SDK要升级,要把Target API level调整31.项目使用的是Unity2017.4.x,接完SDK后打完APP包装到手机上,启动直接黑屏.看Log,也没定位到具体的原因.然后网上搜索 ...

  6. 从 iOS 14 到 Android 12,桌面小组件是怎么「文艺复兴」的

    本文转载自 极客公园 时尚界一直以来有一个著名的理论:在某一时代流行的时尚元素,在经过一段时间的沉寂之后,会被人们再次拿出来利用. 这便是「弗莱定律」,它解释了为什么在长期的历史中,为什么很多曾经时尚 ...

  7. Android 12 小部件详解

    来龙去脉 小部件兴起 2020年九月苹果的 iOS 14 正式版本发布,其中的一项重大更新就是苹果也支持小部件了!不容易啊,安卓好多年前拥有的功能现如今苹果终于用上了,先来看看苹果中的小部件样式吧! ...

  8. android 仿苹果 小组件,安卓玩烂的小组件 iOS怎么又给捡起来了?

    在所有用户的认知中,新系统区别于旧系统的第一印象永远是外观上的变化,例如iOS7的扁平化设计.iOS 10的控制中心.iOS 13的深色模式. 而在即将推出的iOS 14中,最直观的变化莫过于重新设计 ...

  9. Android 12 变更与新特性

    Date:2021.7 文章目录 Android 12新特性总结 一.设置 二.通知 1. 媒体控制界面 2. 媒体控制 3. 休眠功能 4. 通知界面更新 5. trampoline 三.消息框To ...

最新文章

  1. python3默认编码格式_python3 中文乱码与默认编码格式设定方法
  2. Fragment详解之四——管理Fragment(2)
  3. 光流 | 基于Matlab实现Lucas-Kanade方法:方法1(附源代码)
  4. assembly 输出ab中所有数_.NET Core中批量注入Grpc服务
  5. JS实现透明度渐变动画
  6. 将CMD内的显示内容输出到txt文件
  7. pku3670 Eating Together
  8. vue视频教程大全下载
  9. 【CAD技巧】120个常见CAD问题解决办法
  10. 非线性发展方程定解问题
  11. 微信小程序——1、搭建自己的Https服务器
  12. 计算机主板cpu的电源接口类型,给力:主板CPU电源的4pin和8pin有什么区别?
  13. sqlserver获取周数
  14. vue中父传子,父传孙说明
  15. 简易php代码防止恶意刷新网站
  16. 自动投注c语言,yy七周年自动挂机
  17. 学习LDPC码的一些入门笔记
  18. 无约束优化和有约束优化原理
  19. springboot 2.X jdbc 实现session共享mysql
  20. halcon的长度和角度测量

热门文章

  1. 计算机三级网络技术大题详解,教你快速拿到60分,附三级题库绿色免安装
  2. No.005<日常><工具表>《数学符号与希腊字母表》
  3. java排查full gc_一次频繁Full GC问题排查过程分享
  4. 云计算平台项目团队组织架构与缘起
  5. 浅谈网页设计的形式美法则
  6. 李沐的深度学习笔记来了!
  7. 应届生为什么觉得女生更适合银行工作?(上)
  8. 怎么网络同步计算机的本地时间,VBA实现本地计算机时间与网服务器时间的同步...
  9. Flink之IntervalJoin介绍
  10. 二硬脂酰磷脂酰乙醇胺-聚乙二醇-巯基吡啶 DSPE-PEG-OPSS;常用于脂质体的合成