当前位置: 首页 > news >正文

关于做网站常见的问题企业网站建设多少家

关于做网站常见的问题,企业网站建设多少家,黄页网站推广下载免费,网站建设 呢咕云如何使用好 ArkUI 的 Image 组件#xff1f; 开发者经常需要在应用中显示一些图片#xff0c;例如#xff1a;按钮中的logo、网络图片、本地图片等。在应用中显示图片需要使用 Image 组件实现#xff0c;Image支持多种图片格式#xff0c;包括png、jpg、bmp、svg和gif 开发者经常需要在应用中显示一些图片例如按钮中的logo、网络图片、本地图片等。在应用中显示图片需要使用 Image 组件实现Image支持多种图片格式包括png、jpg、bmp、svg和gif具体用法请参考Image组件。 ArkUI 的 Image组件类比SwiftUI中的Image也就是UIKit中的UIImageView。 本文主要对 Image 如何展示图像做一些解读然后对 Image组件一些特殊属性做分析进而帮助开发者理解设置前后的效果以及我们会尝试寻找何时使用这个属性最佳进而给开发者提出参考方案。 一、整理潜在的优化点 Image组件将图片显示到屏幕上分为三步加载、解码、渲染 一般情况下我们直接调用组件操作的是加载这个步骤。因此从渲染过程分析考虑以下几个方面可能可以提升性能。 · 异步下载图片。 一般情况下图片加载流程会异步进行以避免阻塞主线程影响UI交互。但是特定情况下图片刷新时会出现闪烁这时可以使用syncLoad属性使图片同步加载从而避免出现闪烁。 · 将image解码放到子线程。 以Image组件为例。当其显示在屏幕上时需要Image作为数据源。 Image持有的数据是没有解码的压缩数据能节省较多的内存和加快存储。 当image被赋值给Image时图像数据会被解码变成RGB的颜色数据。 解码是一个计算量较大的任务且需要CPU来执行。 解码出来的图片体积与图片的宽高有关与图片原来的体积无关。 图片解码是耗时操作如果图片非常大建议放到子线程解码。 图片解码可能会产生什么问题 在上下滑动展示图片的过程中我们会在lazyforeach的方法加载Image图片相当于在主线程同时进行IO操作、解码等操作。这会造成内存迅速增长和CPU负载瞬间提升。 并且内存的迅速增加会触发系统的内存回收机制尝试回收其他后台进程的内存增加CPU的工作量。 如果系统无法提供足够的内存则会先结束后台app进程同时造成UI卡顿。 · 使用合适尺寸的图片减少为了适配屏幕产生的bitmap计算。 使用图片资源管理工具存储不同分辨率的图片在不同分辨率的设备使用最适合的尺寸。如果图片是网络获取可以通过传参的类型告诉服务端服务端根据设备类型返回最合适尺寸的图片。 · 使用缓存 内存缓存和磁盘缓存 详细分析见下文《图片缓存》章节。 · 直接存储压缩后的图片避免下次从使用缓存的时候再次解压缩。 · 减少内存级别的拷贝。采用字节对齐 在图像渲染时是通过一块一块渲染因此数据是一块块地取如果一块连续的内存数据里结尾的数据不是图像的内容是内存里其他的数据会影响读取效率。 块的大小和CPU cache有关64位系统按64byte作为一块数据去读取和渲染让图像数据对齐64byte就可以避免图形管理器再拷贝一份数据进行修补。 · 图片预下载。 提前将需要的图片下载到本地并在CPU空闲的时候解压缩。 二、对 syncLoad 加载原理分析 我们发现聊天列表头像图片很小加载很快根据官方文档指示在加载图片的耗时比较短的时候通过异步加载的效果会大打折扣建议配置 Image的 .syncLoad属性。 Image($r(app.media.icon)).syncLoad(true)这个修改虽然很简单按字面意思就是设置 同步/异步 加载但我们想弄清楚的是什么时候使用这个特性才是合理的 为了彻底搞明白我们尝试阅读实现代码从代码上看设置了这个值对组件有什么影响。 分析结果 结论先行通过下面的分析我们可以得知设置.syncLoad(true)这个值产生的影响是创建图片时是否创建一个异步任务是否使用互斥锁。 而我们知道创建异步任务和使用互斥锁也是有开销的进而会影响内存和性能。 分析过程 · 由于我们使用的是Image组件Image组件属于ArkUI所以我们找到ArkUI的代码仓下载代码https://gitee.com/openharmony/arkui_ace_engine · 打开下载后的工程找到对应Image的目录 设置初始值 · 查看 image_pattern.h中属性的定义其中省略了无关的代码 namespace OHOS::Ace::NG {class ACE_EXPORT ImagePattern : public Pattern, public SelectionHost {DECLARE_ACE_TYPE(ImagePattern, Pattern, SelectionHost);public:...private:...bool syncLoad_ false;bool isShow_ true;ACE_DISALLOW_COPY_AND_MOVE(ImagePattern); };} // namespace OHOS::Ace::NG#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_IMAGE_IMAGE_PATTERN_H通过 bool syncLoad_ false; 我们知道了syncLoad的默认属性是false如果不设置图片加载就是异步的。 LoadImageDataIfNeed() · 查看 image_pattern.cpp中的实现其中省略了无关的代码 void ImagePattern::ToJsonValue(std::unique_ptrJsonValue json) const {...json-Put(syncLoad, syncLoad_ ? true : false);... }ToJsonValue这个方法通过将sync属性转换成json值和我们目的无关不需要细看。 找到另一个实现方法 LoadImageDataIfNeed 和图片加载强相关我们粗略看一下整段代码 void ImagePattern::LoadImageDataIfNeed() {// 获得图片布局属性auto imageLayoutProperty GetLayoutPropertyImageLayoutProperty();CHECK_NULL_VOID(imageLayoutProperty);// 获得图片绘制属性auto imageRenderProperty GetPaintPropertyImageRenderProperty();CHECK_NULL_VOID(imageRenderProperty);auto src imageLayoutProperty-GetImageSourceInfo().value_or(ImageSourceInfo());UpdateInternalResource(src);if (!loadingCtx_ || loadingCtx_-GetSourceInfo() ! src) {LoadNotifier loadNotifier(CreateDataReadyCallback(), CreateLoadSuccessCallback(), CreateLoadFailCallback());loadingCtx_ AceType::MakeRefPtrImageLoadingContext(src, std::move(loadNotifier), syncLoad_);LOGI(start loading image %{public}s, src.ToString().c_str());loadingCtx_-LoadImageData();}if (loadingCtx_-NeedAlt() imageLayoutProperty-GetAlt()) {auto altImageSourceInfo imageLayoutProperty-GetAlt().value_or(ImageSourceInfo());LoadNotifier altLoadNotifier(CreateDataReadyCallbackForAlt(), CreateLoadSuccessCallbackForAlt(), nullptr);if (!altLoadingCtx_ || altLoadingCtx_-GetSourceInfo() ! altImageSourceInfo ||(altLoadingCtx_ altImageSourceInfo.IsSvg())) {altLoadingCtx_ AceType::MakeRefPtrImageLoadingContext(altImageSourceInfo, std::move(altLoadNotifier));altLoadingCtx_-LoadImageData();}} } 其中重点部分如果 loadingCtx_ 不存在 或者 loadingCtx_ 的图片地址和当前不一致时就会创建一个 RefPtr // 判断条件如果 loadingCtx_ 不存在 或者 loadingCtx_ 的图片地址和当前不一致时if (!loadingCtx_ || loadingCtx_-GetSourceInfo() ! src) {// 创建一个 loadingCtx_ syncLoad_ 是其中一个属性loadingCtx_ AceType::MakeRefPtrImageLoadingContext(src, std::move(loadNotifier), syncLoad_);loadingCtx_-LoadImageData();}RefPtr 那么 loadingCtx_ 是一个什么东西呢通过查看定义文件 image_pattern.h发现 RefPtrImageLoadingContext loadingCtx_;loadingCtx_ 是一个 RefPtr 类型的指针。 我们也可以在源码memery 下的 referenced.h 中找到 RefPtr 的定义由于对我们分析图片加载影响不大简单看一下可以得知 RefPtr 使用引用计数管理实例由于在一些场景需要隐式转换所以在构造函数中移除了 explicitexplicit指定构造函数或转换函数 (C11起)为显式, 即它不能用于隐式转换和复制初始化 templateclass T class RefPtr final {public:...private:...explicit RefPtr(T* rawPtr, bool forceIncRef true) : rawPtr_(rawPtr){if (rawPtr_ ! nullptr forceIncRef) {// Increase strong reference count for holding instance.rawPtr_-IncRefCount();}}... }; AceType::MakeRefPtr 再回到之前的调用代码 loadingCtx_ AceType::MakeRefPtrImageLoadingContext(src, std::move(loadNotifier), syncLoad_);主要关注下使用到的 MakeRefPtr 函数可以得知 Referenced::MakeRefPtr 是用于创建新实例的而这个创建的新实例是继承于 Referenced的。使用 RefPtr 管理指针。 templateclass T, class... Args static RefPtrT MakeRefPtr(Args... args) {return Claim(new T(std::forwardArgs(args)...)); }我们发现 MakeRefPtr 这个函数核心是调用 Claim函数所以我们需要找到 Claim函数 templateclass T static RefPtrT Claim(T* rawPtr) {if (MemoryMonitor::IsEnable()) {MemoryMonitor::GetInstance().Update(rawPtr, static_castReferenced*(rawPtr));}return RefPtrT(rawPtr); }通过代码可以得知Claim通过内存监控管理器用 原始指针构建 RefPtr而 syncLoad_ 是作为一个 std::forwardArgs(args)...)的一个参数被管理起来。 ImageLoadingContext() · 知道了 syncLoad_ 是怎么被管理的之后我们再看 syncLoad_ 怎么用就更容易理解了。 通过之前的指针类型定义 RefPtrImageLoadingContext loadingCtx_;我们可以找到 ImageLoadingContext 这个类在cpp实现中找到了这个方法 OnDataLoading() void ImageLoadingContext::OnDataLoading() {if (auto obj ImageProvider::QueryImageObjectFromCache(src_); obj) {DataReadyCallback(obj);return;}ImageProvider::CreateImageObject(src_, WeakClaim(this), syncLoad_); }可以发现是CreateImageObject() 这个方法创建了图片对象并且使用了 syncLoad_ 这个参数作为创建时的初始值参数。所以我们再次在 image_provider.cpp这个文件中找到 CreateImageObject() 这个方法 这个方法是重点所以完整展示代码并添加一些注释 CreateImageObject() void ImageProvider::CreateImageObject(const ImageSourceInfo src, const WeakPtrImageLoadingContext ctx, bool sync) {if (!RegisterTask(src.GetKey(), ctx)) {// 如果任务已经在跑了直接返回return;}if (sync) {// 如果是同步的直接调用helper类创建CreateImageObjHelper(src, true);} else {// 如果是异步的使用了一个互斥锁std::scoped_lockstd::mutex lock(taskMtx_);// 创建一个可取消的任务CancelableCallbackvoid() task;// 以src作为唯一键值绑定任务task.Reset([src] { ImageProvider::CreateImageObjHelper(src); });tasks_[src.GetKey()].bgTask_ task;// 放到后台去执行任务ImageUtils::PostToBg(task);} }image_utils.cpp void ImageUtils::PostToBg(std::functionvoid() task) {CHECK_NULL_VOID(task);ImageUtils::PostTask(std::move(task), TaskExecutor::TaskType::BACKGROUND, BACKGROUND); }void ImageUtils::PostTask(std::functionvoid() task, TaskExecutor::TaskType taskType, const char* taskTypeName) {auto taskExecutor Container::CurrentTaskExecutor();if (!taskExecutor) {LOGE(taskExecutor is null when try post task to %{public}s, taskTypeName);return;}taskExecutor-PostTask([task, id Container::CurrentId()] {ContainerScope scope(id);CHECK_NULL_VOID(task);task();},taskType); }/*** Post a task to the specified thread.** param task Task which need execution.* param type FrontendType of task, used to specify the thread.* return Returns true whether task has been post successfully.*/ bool PostTask(Task task, TaskType type) const {return PostDelayedTask(std::move(task), type, 0); }mock_image_utils.cpp void ImageUtils::PostToBg(std::functionvoid() task) {// mock bg thread poolif (g_threads.size() MAX_THREADS) {return;}g_threads.emplace_back(std::thread(task)); }emplace_back() 函数在原理上比 push_back() 有了一定的改进包括在内存优化方面和运行效率方面。内存优化主要体现在使用了就地构造直接在容器内构造对象不用拷贝一个复制品再使用强制类型转换的方法来实现在运行效率方面由于省去了拷贝构造过程因此也有一定的提升。 ~ImageLoadingContext() 有创建就有销毁同样我们在析构函数中也找到响应证据如果是异步的就会在析构函数中调用CancelTask 取消任务 ImageLoadingContext::~ImageLoadingContext() {// 取消后台任务if (!syncLoad_) {auto state stateManager_-GetCurrentState();if (state ImageLoadingState::DATA_LOADING) {// 取消 CreateImgObj 任务ImageProvider::CancelTask(src_.GetKey(), WeakClaim(this));} else if (state ImageLoadingState::MAKE_CANVAS_IMAGE) {// 取消 MakeCanvasImage 任务if (InstanceOfStaticImageObject(imageObj_)) {ImageProvider::CancelTask(canvasKey_, WeakClaim(this));}}} }总结综上分析我们知道了设置了.syncLoad(true)这个值后创建图片时就不会创建一个异步任务而我们知道创建异步任务和互斥锁也是有开销的会影响内存和性能所以是否使用这个属性取决于 空间和时间 的取舍关键在于这个阈值是在哪里。为了找出多大的图片使用 syncLoad 更好我们做了如下测试 对比测试 todo。。。 三、objectFit、autoResize 属性对 Image 组件性能的影响 todo 四、图片缓存 ArkUI的图片缓存策略以及我们建议的图片缓存策略 todo
http://www.dnsts.com.cn/news/148577.html

相关文章:

  • 软件开发和网站开发区别网页托管网站
  • 工控主机做网站服务器室内设计学校网站
  • dtcms网站开发wordpress 网站加载过慢6
  • php企业网站后台管理系统顺企网是什么网站
  • 陕西省建设造价协会网站常州网站推广招聘
  • 网站设计分析报告系统繁忙是什么原因
  • 怎样自己制作网站长沙有实力seo优化
  • iis默认网站路径汽车零件销售网站开发
  • 东莞公司想建网站网站开发如何压缩图片
  • 网上书店网站建设建筑人才网官网入口
  • 国内优秀的设计网站推荐wordpress博客页面无法显示
  • 学校建设网站费用申请怎么才能做电商
  • 网站域名在哪里查询潍坊做网站哪个公司好
  • 买域名送网站空间浙江网站建设推广公司
  • 苏州门户网站建设电话福建省建设工程质量安全网站
  • 二手车网站模版售价wordpress表单留言
  • 移动端网站开发流程seo网络排名优化技巧
  • 建设电视台微信网站必要性ui需要学哪些内容
  • 福州培训网站建设南宁黄页电话号码查询
  • html5 网站案例制作京东一样的网站
  • 那个企业网站是用vue做的版式设计1000例
  • 网站建设创建做网页设计需要学什么
  • 松山湖网站建设公司免费微信网站模板下载
  • 寿光哪里做网站wordpress 网站标题设置方法
  • 做网站送白酒南宁求介绍seo软件
  • 做网站侵权吗广州市网站建站
  • 网站页面设计风格wordpress访问权限插件
  • 购物网站需求分析网站提交地址
  • seo网站架构设计自适应产品网站模板
  • 乐清网站制作优化品牌建设的目标