作者: 林子木

博客地址:http://blog.csdn.net/wolinxuebin

文章总结:

什么是硬件加速:简单来说是一种采用GPU进行渲染,并且在计算需要重新绘制View上做了相应的优化。
相比原先的绘制模式,硬件加速具有什么优点:
  • 原先绘制模式是在一个view的内容改变的时候,调用invalidate()函数,立即将消息上传将生成一个dirty 区域(Rect 类型),之后将于dirty相交的view都进行重绘(即使内容没发生变化)。
  • 硬件加速模式,是采用dispaly list模式,有内容改变的view ,仍旧调用invalidate()函数,但是不会立马进行重绘,而是将调用了invalidate() 函数的view加入到 list 中,在下一次进行统一的绘制。
优点:

  • 一个优点很明显,就是不会将内容没有改变的view进行重新的绘制。
  • 另一个优点是,在开启了硬件加速,并且view的type设置成了 View.LAYER_TYPE_HARDWAR 模式,那么View的一些属性,如alpha、translateX,Y、rotateX,Y、scaleX,Y以及pivotX,Y将不再调用view的onDraw函数,而是直接在图层上进行操作,会有很高的效率。
以下是GOOGLE官方文档及个人的翻译:

前言:

Beginning in Android 3.0 (API level 11), the Android 2D rendering pipeline supports hardware acceleration, meaning that all drawing operations that are performed on a View's canvas use the GPU. Because of the increased resources required to enable hardware acceleration, your app will consume more RAM.
硬件加速是在 Anroid3.0(API Level 11)开始引入,主要用于Android2D的渲染。这话有点不是很好理解,简单的说就是View的在canvas上的操作,将由GPU进行执行。为什么要采用GPU呢?这是由于启用硬件加速,将消耗更多的RAM,所以由GPU接管了原先CPU的渲染工作。什么是渲染?简单理解就是将数据转化为图形,呈现在你面前。

Hardware acceleration is enabled by default if your Target API level is >=14, but can also be explicitly enabled. If your application uses only standard views and Drawables, turning it on globally should not cause any adverse drawing effects. However, because hardware acceleration is not supported for all of the 2D drawing operations, turning it on might affect some of your custom views or drawing calls. Problems usually manifest themselves as invisible elements, exceptions, or wrongly rendered pixels. To remedy this, Android gives you the option to enable or disable hardware acceleration at multiple levels. See Controlling Hardware Acceleration.

硬件加速在API大于14的系统版本中默认是开启的,如果不需要,也可以进行关闭。如果你的应用都使用了标准的view和Drawable,关闭硬件加速不会有任何的影响(这里的影响是指显示错误,而不是指性能方面的)。然而当前硬件加速并不支持所有的2D操作,因此可能会影响你的自定义的view或者部分的drawing的操作。会造成元素不可见、异常或者渲染了错误的像素等问题。为了补救该问题,Android在多个层级上给出了开关硬件加速的接口。

If your application performs custom drawing, test your application on actual hardware devices with hardware acceleration turned on to find any problems. The Unsupported drawing operations section describes known issues with hardware acceleration and how to work around them.

Controlling Hardware Acceleration

控制硬件加速


You can control hardware acceleration at the following levels:

控制硬件加速有如下几个级别:

  • Application
  • Activity
  • Window
  • View

Application level

In your Android manifest file, add the following attribute to the <application> tag to enable hardware acceleration for your entire application:

<application android:hardwareAccelerated="true" ...>

Activity level

If your application does not behave properly with hardware acceleration turned on globally, you can control it for individual activities as well. To enable or disable hardware acceleration at the activity level, you can use the android:hardwareAccelerated attribute for the <activity> element. The following example enables hardware acceleration for the entire application but disables it for one activity:

<application android:hardwareAccelerated="true"><activity ... /><activity android:hardwareAccelerated="false" />
</application>

Window level

If you need even more fine-grained control, you can enable hardware acceleration for a given window with the following code:

getWindow().setFlags(WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);

Note: You currently cannot disable hardware acceleration at the window level.

注意,当前不能在window 级别禁止硬件加速

View level

You can disable hardware acceleration for an individual view at runtime with the following code:

myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);

Note: You currently cannot enable hardware acceleration at the view level. View layers have other functions besides disabling hardware acceleration. See View layers for more information about their uses.

注意,当前不能在view级别开启硬件加速

Determining if a View is Hardware Accelerated

以下的一些操作可以查看一个view是否开启了硬件加速


It is sometimes useful for an application to know whether it is currently hardware accelerated, especially for things such as custom views. This is particularly useful if your application does a lot of custom drawing and not all operations are properly supported by the new rendering pipeline.

There are two different ways to check whether the application is hardware accelerated:

  • View.isHardwareAccelerated() returns true if the View is attached to a hardware accelerated window.
  • Canvas.isHardwareAccelerated() returns true if the Canvas is hardware accelerated

If you must do this check in your drawing code, use Canvas.isHardwareAccelerated() instead of View.isHardwareAccelerated() when possible. When a view is attached to a hardware accelerated window, it can still be drawn using a non-hardware accelerated Canvas. This happens, for instance, when drawing a view into a bitmap for caching purposes.

Android Drawing Models

Android的绘制模型


When hardware acceleration is enabled, the Android framework utilizes a new drawing model that utilizes display lists to render your application to the screen. To fully understand display lists and how they might affect your application, it is useful to understand how Android draws views without hardware acceleration as well. The following sections describe the software-based and hardware-accelerated drawing models.

如果开启了硬件加速,Android将采用一种新的绘制模型,该模型采用display lists的方式来渲染你的应用。为了更好的理解的工作原理,我们首先来理解Android最原始的绘制模型。接下来的章节,我们将分别介绍基于软件和开启硬件加速的绘制模型。

Software-based drawing model

基于软件的绘制模型

In the software drawing model, views are drawn with the following two steps:

在软件绘制模型中,一个view将进行下面两个步骤:

  1. Invalidate the hierarchy
  2. Draw the hierarchy

Whenever an application needs to update a part of its UI, it invokes invalidate() (or one of its variants) on any view that has changed content. The invalidation messages are propagated all the way up the view hierarchy to compute the regions of the screen that need to be redrawn (the dirty region). The Android system then draws any view in the hierarchy that intersects with the dirty region. Unfortunately, there are two drawbacks to this drawing model:

当我们的应用需要更新部分UI时,有内容变动的view将会执行invalidate()函数。这时候将会将这个message不断的向上传递,最后由rootView计算出一个 dirty 区域。之后根据这个dirty 区域,找出与之相交的所有的view,并执行重绘操作。这将带来以下几个缺点:

  • First, this model requires execution of a lot of code on every draw pass. For example, if your application calls invalidate() on a button and that button sits on top of another view, the Android system redraws the view even though it hasn't changed.
       首先,将会执行很多不必要的代码。比如一个button位于另一个view之上,一旦这个button内容发生了改变,调用了invalidate()这个函数,那么即使位于之下的那个view没有发生变化,进了重绘操作。
  • The second issue is that the drawing model can hide bugs in your application. Since the Android system redraws views when they intersect the dirty region, a view whose content you changed might be redrawn even though invalidate() was not called on it. When this happens, you are relying on another view being invalidated to obtain the proper behavior. This behavior can change every time you modify your application. Because of this, you should always call invalidate() on your custom views whenever you modify data or state that affects the view’s drawing code.
     其次,这里有一个隐藏的问题。当系统对之前和ditry区域相交的view进行重绘处理的时候,一个有内容变化的view即使没有调用invalidate()函数,也将被重绘。那么这将造成一个不同步的问题,比如View1的内容改变了并且被重绘了,而view2内容改变了,但是没有被重绘。

Note: Android views automatically call invalidate() when their properties change, such as the background color or the text in a TextView.

Hardware accelerated drawing model

硬件加速绘制模型

The Android system still uses invalidate() and draw() to request screen updates and to render views, but handles the actual drawing differently. Instead of executing the drawing commands immediately, the Android system records them inside display lists, which contain the output of the view hierarchy’s drawing code. Another optimization is that the Android system only needs to record and update display lists for views marked dirty by an invalidate() call. Views that have not been invalidated can be redrawn simply by re-issuing the previously recorded display list. The new drawing model contains three stages:

在硬件加速绘制模型中,Android系统仍旧使用invalidate() 和 draw()这两个函数来请求屏幕更新及渲染视图的操作,当时与基于软件的绘制模型相比,有很大的却别。与之前在调用函数就里面进行绘制不同,Android系统将把请求的view记录到一个display list中。另一个优化是,系统对invalidate()函数的处理,仅仅只用更新display list就可以。最终只要重绘list中的view,而不用全部重绘。具体的重绘将会包含下面三个阶段:

  1. Invalidate the hierarchy
  2. Record and update display lists
  3. Draw the display lists

With this model, you cannot rely on a view intersecting the dirty region to have its draw() method executed. To ensure that the Android system records a view’s display list, you must call invalidate(). Forgetting to do so causes a view to look the same even after it has been changed.

在这个模型中,将不会重绘那些没有改变的view,仅仅重绘被标记在display list中的view。

Using display lists also benefits animation performance because setting specific properties, such as alpha or rotation, does not require invalidating the targeted view (it is done automatically). This optimization also applies to views with display lists (any view when your application is hardware accelerated.) For example, assume there is a LinearLayout that contains a ListView above a Button. The display list for the LinearLayout looks like this:

采用display list 对动画的流畅性具有很大的帮助,比如动画改变alpha、旋转等,不需要将View进行invalidate标记,因为这些属性不需要对view进行处理,仅仅只要对图层做下相应的处理就可以。举一个例子,在LinearLayout中有一个lisiView,在lisiView之上又放了一个button,那么展现LinearLayout将如下几步:

  • DrawDisplayList(ListView)
  • DrawDisplayList(Button)

Assume now that you want to change the ListView's opacity. After invoking setAlpha(0.5f) on the ListView, the display list now contains this:

假设此时对listview进行了更新alpha的处理,那将如下操作:

  • SaveLayerAlpha(0.5)
  • DrawDisplayList(ListView)
  • Restore
  • DrawDisplayList(Button)

The complex drawing code of ListView was not executed. Instead, the system only updated the display list of the much simpler LinearLayout. In an application without hardware acceleration enabled, the drawing code of both the list and its parent are executed again.

由于ListView内容没有改变,所以不会重绘,仅仅是将图层的alpha进行改变就可以。如果不采用硬件加速,那么不仅listview要进行重绘,Button及LinearLayout都要进行重绘操作。

Unsupported Drawing Operations

下面是一些为未支持硬件加速的操作


When hardware accelerated, the 2D rendering pipeline supports the most commonly used Canvas drawing operations as well as many less-used operations. All of the drawing operations that are used to render applications that ship with Android, default widgets and layouts, and common advanced visual effects such as reflections and tiled textures are supported.

当前硬件加速支持大部分的Canvas的操作。此外还支持widgets和 layouts的一些常见的视觉效果,如反射和铺砖文理。

The following table describes the support level of various operations across API levels:

下面的表格将描述各种操作的支持的API级别:

   
  First supported API level
Canvas
drawBitmapMesh() (colors array) 18
drawPicture() 23
drawPosText() 16
drawTextOnPath() 16
drawVertices()
setDrawFilter() 16
clipPath() 18
clipRegion() 18
clipRect(Region.Op.XOR) 18
clipRect(Region.Op.Difference) 18
clipRect(Region.Op.ReverseDifference) 18
clipRect() with rotation/perspective 18
Paint
setAntiAlias() (for text) 18
setAntiAlias() (for lines) 16
setFilterBitmap() 17
setLinearText()
setMaskFilter()
setPathEffect() (for lines)
setRasterizer()
setShadowLayer() (other than text)
setStrokeCap() (for lines) 18
setStrokeCap() (for points) 19
setSubpixelText()
Xfermode
PorterDuff.Mode.DARKEN (framebuffer)
PorterDuff.Mode.LIGHTEN (framebuffer)
PorterDuff.Mode.OVERLAY (framebuffer)
Shader
ComposeShader inside ComposeShader
Same type shaders inside ComposeShader
Local matrix on ComposeShader 18

Canvas Scaling

画布的缩放操作

The hardware accelerated 2D rendering pipeline was built first to support unscaled drawing, with some drawing operations degrading quality significantly at higher scale values. These operations are implemented as textures drawn at scale 1.0, transformed by the GPU. In API level <17, using these operations will result in scaling artifacts increasing with scale.

硬件加速最开始并没有支持缩放绘制,一些操作在大的放大情况下,显得很低的显示质量。这些操作都是基于不缩放的情况下进行使用的。如果在API < 17的情况下使用这些操作将会带来不利的影响。

The following table shows when implementation was changed to correctly handle large scales:

   
Drawing operation to be scaled First supported API level
drawText() 18
drawPosText()
drawTextOnPath()
Simple Shapes* 17
Complex Shapes*
drawPath()
Shadow layer

Note: 'Simple' shapes are drawRect(), drawCircle(), drawOval(), drawRoundRect(), and drawArc() (with useCenter=false) commands issued with a Paint that doesn't have a PathEffect, and doesn't contain non-default joins (via setStrokeJoin() / setStrokeMiter()). Other instances of those draw commands fall under 'Complex,' in the above chart.

注意:’Simple’ 形状是指drawRect(), drawCircle(), drawOval(), drawRoundRect(), and drawArc() ( useCenter这参数设为false时),这些事不存在路径影响的函数。其他的都是‘Complex’现在还暂时不支持。

If your application is affected by any of these missing features or limitations, you can turn off hardware acceleration for just the affected portion of your application by calling setLayerType(View.LAYER_TYPE_SOFTWARE, null). This way, you can still take advantage of hardware acceleration everywhere else. See Controlling Hardware Acceleration for more information on how to enable and disable hardware acceleration at different levels in your application.

如果你的应用存在这种问题,只要采用setLayerType(View.LAYER_TYPE_SOFTWARE, null)进行关闭,在其他地方依旧可以使用硬件加速带来的好处。

View Layers

View 图层


In all versions of Android, views have had the ability to render into off-screen buffers, either by using a view's drawing cache, or by using Canvas.saveLayer(). Off-screen buffers, or layers, have several uses. You can use them to get better performance when animating complex views or to apply composition effects. For instance, you can implement fade effects using Canvas.saveLayer() to temporarily render a view into a layer and then composite it back on screen with an opacity factor.

在所有的版本的Android中,所有的View都具备采用drawing cache或采用Canvas.saveLayer()来实现离屏缓存(简单的理解,在不同的图层绘制,不会影响其他图层)。

Beginning in Android 3.0 (API level 11), you have more control on how and when to use layers with the View.setLayerType() method. This API takes two parameters: the type of layer you want to use and an optional Paint object that describes how the layer should be composited. You can use the Paint parameter to apply color filters, special blending modes, or opacity to a layer. A view can use one of three layer types:

在Android 3.0开始,就可以使用View.setLayerType()函数来实现离屏缓存功能。这个函数具有两个参数:第一个是图层的type,另一个是paint对象。你可以同时patin对象实现颜色滤镜、特殊的混合模式以及图层的透明度操作等功能。一个View可以采用如下3个类型:

  • LAYER_TYPE_NONE: The view is rendered normally and is not backed by an off-screen buffer. This is the default behavior.
      这个是默认操作,采用普通个渲染模式,没有采用离屏缓冲。
  • LAYER_TYPE_HARDWARE: The view is rendered in hardware into a hardware texture if the application is hardware accelerated. If the application is not hardware accelerated, this layer type behaves the same as LAYER_TYPE_SOFTWARE.
      如果设置了这个模式,在应用没有开启硬件加速的时候,会默认采用LAYER_TYPE_SOFTWARE,否则采用LAYER_TYPE_HARDWARE模式。
  • LAYER_TYPE_SOFTWARE: The view is rendered in software into a bitmap.
     这个模式将view渲染成一个bitmap。

The type of layer you use depends on your goal:

  • Performance: Use a hardware layer type to render a view into a hardware texture. Once a view is rendered into a layer, its drawing code does not have to be executed until the view calls invalidate(). Some animations, such as alpha animations, can then be applied directly onto the layer, which is very efficient for the GPU to do.
      性能方面:如果采用硬件层,那么将把view采用硬件文理渲染。一旦视图加入该层,只有当view调用了invalidate()函数之后,才会调用绘制相关的代码。一些动画,比如透明度动画,就可以直接在图层上进行变换,这些操作对GPU来说,是很高效的。
  • Visual effects: Use a hardware or software layer type and a Paint to apply special visual treatments to a view. For instance, you can draw a view in black and white using a ColorMatrixColorFilter.
     视觉影响: 可以使用硬件或软件层以及配合Paint的功能,实现黑白画面等。
  • Compatibility: Use a software layer type to force a view to be rendered in software. If a view that is hardware accelerated (for instance, if your whole application is hardware acclerated), is having rendering problems, this is an easy way to work around limitations of the hardware rendering pipeline.
      兼容性:采用软件图层将强制将view采用软件渲染模式。如果一个view采用了硬件加速,但是却遇到了渲染方面的问题,将自动转化为软件图层的模式。     

View layers and animations

视图图层和动画

Hardware layers can deliver faster and smoother animations when your application is hardware accelerated. Running an animation at 60 frames per second is not always possible when animating complex views that issue a lot of drawing operations. This can be alleviated by using hardware layers to render the view to a hardware texture. The hardware texture can then be used to animate the view, eliminating the need for the view to constantly redraw itself when it is being animated. The view is not redrawn unless you change the view's properties, which calls invalidate(), or if you call invalidate() manually. If you are running an animation in your application and do not obtain the smooth results you want, consider enabling hardware layers on your animated views.

When a view is backed by a hardware layer, some of its properties are handled by the way the layer is composited on screen. Setting these properties will be efficient because they do not require the view to be invalidated and redrawn. The following list of properties affect the way the layer is composited. Calling the setter for any of these properties results in optimal invalidation and no redrawing of the targeted view:

在开启了硬件加速的情况下,以下几个属性的改变,将不会引起view的重绘。

  • alpha: Changes the layer's opacity
  • x, y, translationX, translationY: Changes the layer's position
  • scaleX, scaleY: Changes the layer's size
  • rotation, rotationX, rotationY: Changes the layer's orientation in 3D space
  • pivotX, pivotY: Changes the layer's transformations origin

These properties are the names used when animating a view with an ObjectAnimator. If you want to access these properties, call the appropriate setter or getter. For instance, to modify the alpha property, call setAlpha(). The following code snippet shows the most efficient way to rotate a viewiew in 3D around the Y-axis:

view.setLayerType(View.LAYER_TYPE_HARDWARE, null);
ObjectAnimator.ofFloat(view, "rotationY", 180).start();

Because hardware layers consume video memory, it is highly recommended that you enable them only for the duration of the animation and then disable them after the animation is done. You can accomplish this using animation listeners:

View.setLayerType(View.LAYER_TYPE_HARDWARE, null);
ObjectAnimator animator = ObjectAnimator.ofFloat(view, "rotationY", 180);
animator.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {view.setLayerType(View.LAYER_TYPE_NONE, null);}
});
animator.start();

For more information on property animation, see Property Animation.

Tips and Tricks

建议等


Switching to hardware accelerated 2D graphics can instantly increase performance, but you should still design your application to use the GPU effectively by following these recommendations:

以下是关于一些提高应用性能的操作:

Reduce the number of views in your application
The more views the system has to draw, the slower it will be. This applies to the software rendering pipeline as well. Reducing views is one of the easiest ways to optimize your UI.
减少View的个数,是最简单的优化你的UI的方法。
Avoid overdraw
Do not draw too many layers on top of each other. Remove any views that are completely obscured by other opaque views on top of it. If you need to draw several layers blended on top of each other, consider merging them into a single layer. A good rule of thumb with current hardware is to not draw more than 2.5 times the number of pixels on screen per frame (transparent pixels in a bitmap count!).
避免过度重绘。
Don't create render objects in draw methods
A common mistake is to create a new Paint or a new Path every time a rendering method is invoked. This forces the garbage collector to run more often and also bypasses caches and optimizations in the hardware pipeline.
不要在onDraw函数中进行new Paint 与 new Path等操作,这样会产生大量的垃圾。
Don't modify shapes too often
Complex shapes, paths, and circles for instance, are rendered using texture masks. Every time you create or modify a path, the hardware pipeline creates a new mask, which can be expensive.
复杂的形状、路径、圆等,是采用纹理面具渲染。每次修改路径都会引起硬件加速重新创建新的面具(mask),很消耗资源。
Don't modify bitmaps too often
Every time you change the content of a bitmap, it is uploaded again as a GPU texture the next time you draw it.
避免多次修改bitmap,因为每次进行修改,都会让CPU重新进行纹理处理。
Use alpha with care
When you make a view translucent using setAlpha(), AlphaAnimation, or ObjectAnimator, it is rendered in an off-screen buffer which doubles the required fill-rate. When applying alpha on very large views, consider setting the view's layer type to LAYER_TYPE_HARDWARE.
小心使用alpha,因为这在离屏缓冲中使用双倍的填充速率。当如果要修改一个大的view的alpha时,可以设置LAYER_TYPE_HARDWARE来提升效率。

理解Andriod 硬件加速相关推荐

  1. Android硬件加速(二)-RenderThread与OpenGL GPU渲染

    Android4.0之后,系统默认开启硬件加速来渲染视图,之前,理解Android硬件加速的小白文简单的讲述了硬件加速的简单模型,不过主要针对前半阶段,并没怎么说是如何使用OpenGL.GPU处理数据 ...

  2. Android基础 硬件加速和软件绘制 invalidate和RequestLayout流程

    前言 本文介绍了硬件加速和软件绘制的区别: 并梳理了最简单的情况,在子View(非ViewGroup)调用invalidate的流程,且忽略绘图缓存,即mLayerType == LAYER_TYPE ...

  3. [css] 说说你对GPU的理解,举例说明哪些元素能触发GPU硬件加速?

    [css] 说说你对GPU的理解,举例说明哪些元素能触发GPU硬件加速? GPU: 图形处理器,用于处理图形有关的任务,用于渲染页面在css中使用 transform: translateZ(0),可 ...

  4. CUDA硬件加速的理解

    李国帅 从网络收集的内容并整理 2012/7/31 9:05:27 概念 CUDA是一种由NVIDIA推出的通用并行计算架构,该架构使GPU能够解决复杂的计算问题. 它包含了CUDA指令集架构(ISA ...

  5. Android 4.0的图形硬件加速及绘制技巧

    [51CTO独家特稿]从Android 3.0开始,Android 2D的绘制流程就设计为能够更好地支持硬件加速.使用GPU的View在Canvas上进行画的操作时都会使用硬件加速.在最新的Andro ...

  6. FFmpeg在Intel GPU上的硬件加速与优化

    英特尔提供了一套基于VA-API/Media SDK的硬件加速方案,通过在FFmpeg中集成Intel GPU的媒体硬件加速能力,为用户提供更多的收益.本文来自英特尔资深软件开发工程师赵军在LiveV ...

  7. FFmpeg Maintainer赵军:FFmpeg关键组件与硬件加速

    本文来自FFmpeg Maintainer赵军在LiveVideoStackCon 2018热身分享,并由LiveVideoStack整理而成.在分享中,赵军介绍了FFmpeg的历史.关键组件,并介绍 ...

  8. 硬件加速下webview切换闪屏_网页渲染性能优化 —— 性能优化下

    博客 有更多精品文章哟. Composite 的优化 终于,我们到了像素管道的末尾.对于这一部分的优化策略,我们可以从为什么需要 Composited Layer(Graphics Layer)来入手 ...

  9. Android 系统(175)---Android硬件加速原理与实现简介

    Android硬件加速原理与实现简介 在手机客户端尤其是Android应用的开发过程中,我们经常会接触到"硬件加速"这个词.由于操作系统对底层软硬件封装非常完善,上层软件开发者往往 ...

  10. 《深入浅出DPDK》读书笔记(十):硬件加速与功能卸载(VLAN、IEEE1588、IP TCP/UDP/SCTP checksum、Tunnel)

    Table of Contents 109.硬件卸载简介 110.网卡硬件卸载功能 111.DPDK软件接口 接收侧: 发送侧: 112.硬件与软件功能实现 113.VLAN硬件卸载 1. 收包时VL ...

最新文章

  1. 第十六 django进一步了解
  2. 如何挑选适合的前端框架(去哪儿网前端架构师司徒正美)
  3. JavaScript之图片的无缝滚动
  4. Python 中多线程共享全局变量的问题
  5. OpenCV Java开发简介
  6. 奥特曼系列ol光元在哪个服务器,奥特曼系列ol光元怎么合理使用
  7. linux系统多大分区,linux系统中fdisk最大能认到多大分区
  8. wxparse使用(富文本插件)
  9. 河南省第二届“金盾信安杯”网络安全大赛 WriteUp Crypto+Misc
  10. ACM International Collegiate Programming Contest, Egyptian Collegiate Programming Contest (ECPC 2015
  11. 了解一下 Technorati 的后台数据库架构
  12. UE4_虚幻引擎4多人联机基础知识和客户端服务器通信机制详解
  13. Microsoft Teams管理(一)
  14. 修改谷歌和火狐浏览器滚动条的样式
  15. 常见博客Blog托管提供商评测
  16. 数据分析 第一讲 Python语言及工作环境准备、本地数据的采集与操作
  17. spring 自定义消息转换器
  18. XCP实战系列介绍02-A2L文件详尽解析
  19. [zz]《2012武汉IT求职指南》IT行业、程序员求职专用
  20. 中国大学生计算机设计大赛三等奖什么水平,我校获得2016年(第九届)中国大学生计算机设计大赛总决赛二等奖1项、三等奖1项...

热门文章

  1. 鸡兔同笼php编程,C语言鸡兔同笼问题
  2. keytool 使用
  3. stm32中typedef的用法
  4. Java学习从入门到放弃
  5. 计算机辅助机械设计a卷,二维CAD工程师(机械设计)考试A卷
  6. CurvySplines基础
  7. linux下用impdp导入dmp文件
  8. Win系统 - 重装系统(微PE、MSDN镜像)【绝对纯净】
  9. 图像处理-RGB24转YUV420遇到的坑以及执行效率对比
  10. Netty学习之读netty权威指南(一)