jjzjj

android - 避免在 onDraw() (StaticLayout) 中分配对象?

coder 2023-12-03 原文

我有一个自定义 View ,我很快学会了不在其中进行对象分配,并将我所有的 Paint 分配移动到一个不同的方法中,很好。

但是我需要使用 StaticLayout 来处理一些应用了一些可跨越的“内容”的文本。

    layoutBpm = new StaticLayout(bpmValue,
            textPaintBPM, arcRadius, Layout.Alignment.ALIGN_NORMAL, 0, 1,
            false);

    layoutBpm.draw(canvas);

这对我来说在 onDraw 中似乎很有意义,但我当然会被警告避免这种情况。对我来说重要的是我会尽我所能避免任何性能问题,所以我正在努力正确地做到这一点。

我似乎找不到任何我能理解的文档来解释 StaticLayout 的一些参数实际上做了什么(float spacingmult?float spacingadd?),但我认为第三个是 StaticLayout 文本的最大宽度我只能从 onMeasure 获取,因为它与我的 Canvas 大小有关。这让我想将作业放在 onMeasure 或 onDraw 中,这两者似乎都不是我想要做的。将 StaticLayout 赋值放在 onDraw 中是否可以,或者有更好的方法吗?

希望这是有道理的,我对此很陌生。感谢您的任何帮助。

(编辑:我假设将这个赋值放在一个方法中并从 onDraw/onMeasure 调用是愚蠢的,会停止 Eclipse 警告我但实际上不会帮助?)

最佳答案

出现警告的原因是,通常情况下,您不需要在绘制操作中多次重新创建对象。与 View 中的其他方法相比,onDraw() 可以被调用数百次。大多数时候,正在重新创建的对象是使用准确的参数重新创建的。其他时候,与创建新对象相比,更改对象状态的开销要小得多。

StaticLayout 的情况下,您只需要在文本更改或调整 padding、spacing 或 maxwidth 时创建一个新布局。如果文本经常更改,那么您可能需要考虑 DynamicLayout,它每次都会重新测量自己。与创建新对象相比,重新测量成本更高,但它发生的频率没有比 onDraw() 调用更频繁的了。

如果文本不经常更改并且您绝对必须使用 StaticLayout,那么您可以使用类似这种结构的东西。

StaticLayout myLayout;
String textSource = defaultSource;
Paint textPaint = defaultPaint;
int textWidth = defaultWidth; 

public CustomView(Context ctx) {
    super(ctx);
    createLayout();
}

public void setText(String text) {
   textSource = text;
   createLayout();
}

public void setWidth(int width) {
   textWidth = width;
   createLayout();
}

@Override
public void onDraw(Canvas canvas) {
   myLayout.draw(canvas);
}

private void createLayout() {
   myLayout = new StaticLayout(textSource, textPaint, textWidth, Layout.Alignment.ALIGN_NORMAL, 0, 1, false);
}

基本上,只有在发生变化时才创建新布局。否则,您只需重用您创建的最后一个对象。

编辑:

跳过测量过程的一种方法是在新调整大小的 View 本身上调用 View#measure。所以你的 createLayout() 方法应该是这样的。

   private void createLayout() {
       myLayout = new StaticLayout(textSource, textPaint, textWidth, Layout.Alignment.ALIGN_NORMAL, 0, 1, false);
       int textWidthSpec = MeasureSpec.makeMeasureSpec(maxLayoutWidth, MeasureSpec.AT_MOST);
       int textHeightSpec = MeasureSpec.makeMeasureSpec(maxLayoutHeight, MeasureSpec.AT_MOST);
       myLayout.measure(textWidthSpec, textHeightSpec);
       forceLayout();
    }

基本上,它所做的是告诉布局 View 可以达到的最大值。它会测量自己和它的 child 。 forceLayout() 将在父级(您的自定义 View )上调用,父级将根据新测量值重新布局其他内容。

我应该指出,我从来没有用 StaticLayout 做过这件事,所以我不知道会发生什么。似乎在创建 View 时可能已经处理了这种类型的测量,但也可能没有。

希望对您有所帮助。

关于android - 避免在 onDraw() (StaticLayout) 中分配对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17092887/

有关android - 避免在 onDraw() (StaticLayout) 中分配对象?的更多相关文章

  1. ruby-on-rails - RSpec:避免使用允许接收的任何实例 - 2

    我正在处理旧代码的一部分。beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)endRubocop错误如下:Avoidstubbingusing'allow_any_instance_of'我读到了RuboCop::RSpec:AnyInstance我试着像下面那样改变它。由此beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)end对此:let(:sport_

  2. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  3. ruby-on-rails - 在 rails 中分配/替换参数哈希 - 2

    我在RailsController操作中有下面的代码序列。在IF之前,params包含请求参数,正如预期的那样。在它之后,params为零。谁能解释一下这里发生了什么?iffalseparams={:user=>{:name=>"user",:comment=>'comment'}}end谢谢。 最佳答案 params其中包含请求参数实际上是一个方法调用,它返回包含参数的散列。你的params=行正在分配给一个名为params的局部变量.iffalse之后block,Ruby已经看到了本地params变量,所以当你引用params时

  4. ruby - 在 Ruby 中为变量赋值时如何避免控制台输出 - 2

    赋值时是否可以避免这种影响:irb(main):584:0>a=true=>trueirb(main):584:0>我有一个代码有很多赋值,当我试图测试它时,由于所有这些返回值,我看不到结果:truefalsetruefalsetruetrue.. 最佳答案 您可以启动irb或附加--noecho选项的控制台。$irb--noecho2.0.0p353:001>true2.0.0p353:002>否则,如果控制台由另一个进程启动,只需设置conf.echo=false$irb2.0.0p353:001>true=>true2.0.0

  5. ruby-on-rails - Rails - 如何避免在 View 中使用 hidden_​​fields 将值传递给 Controller ​​? - 2

    有没有一种方法可以避免hidden_​​field方法将View中的值传递给Controller​​?出于安全原因,我更喜欢Controller方法。不幸的是,strong_parameters不支持值对@variables。EDIT6/181:00PMESTI'verenamedmygaragescontrollertoappointmentscars_controllernolongercreatesanewappointment(formallygarages).Anewappointmentiscreatedintheappointments_controller我目前的结构路

  6. ruby-on-rails - 在 Rails 中分配和重用变量 - 设计模式 - 2

    我一直在使用相同的模式来返回json代码(参见下面的示例)。我正在收集照片并将其存储在变量中。如果存在标记参数,我将获得一个更具体的集合并将其重新分配给同一个变量。然后将其作为json返回。什么是更好的设计模式来实现同样的事情?photos=collection_of_photosifparams[:tag]photos=photos.find_all{|photo|somecondition}endrenderjson:photos 最佳答案 如果照片是ActiveRecord对象,您应该使用scope为您需要的确切数据生成适当的

  7. ruby - 如何使用 ruby​​ fibers 避免阻塞 IO - 2

    我需要将目录中的一堆文件上传到S3。由于上传所需的90%以上的时间都花在了等待http请求完成上,所以我想以某种方式同时执行其中的几个。Fibers能帮我解决这个问题吗?它们被描述为解决此类问题的一种方法,但我想不出在http调用阻塞时我可以做任何工作的任何方法。有什么方法可以在没有线程的情况下解决这个问题? 最佳答案 我没有使用1.9中的纤程,但是1.8.6中的常规线程可以解决这个问题。尝试使用队列http://ruby-doc.org/stdlib/libdoc/thread/rdoc/classes/Queue.html查看文

  8. ruby - 无法在 Ruby 中分配内存(无 MemoryError)? - 2

    我写了一个简单的脚本,它应该读取整个目录,然后通过去除HTML标签将HTML数据解析为普通脚本,然后将其写入一个文件。我有8GB内存和大量可用虚拟内存。当我这样做时,我有超过5GB的RAM可用。目录中最大的文件为3.8GB。脚本是file_count=1File.open("allscraped.txt",'w')do|out1|forfile_nameinDir["allParts/*.dat"]doputs"#{file_name}#:#{file_count}"file_count+=1File.open(file_name,"r")do|file|source=""tmp_sr

  9. Ruby FTP 从文件夹中分离文件 - 2

    我正在尝试抓取FTP并以递归方式提取所有文件。到目前为止,我一直在尝试使用下拉目录ftp.list.eachdo|entry|ifentry.split(/\s+/)[0][0,1]=="d"out[:dirs]但事实证明,如果您将列表拆分到最后一个空格,则获取带有空格的文件名和目录是错误的。在此处的逻辑上需要一点帮助。 最佳答案 如果一次列出所有文件,则可以避免递归files=ftp.nlst('**/*.*')目录未包含在列表中,但名称中仍提供完整的ftp路径。编辑我假设每个文件名都包含一个点,而目录名则没有。感谢您提及@Nik

  10. ruby - 阅读用户输入时如何避免回显换行符? - 2

    我正在用Ruby编写类似curses的程序,我正在使用stty和ansi转义字符来实现我想要的。当我想获得用户输入时,我的问题就出现了。像许多基于控制台的程序一样,我想从终端底部获取用户输入。因此,我将光标放在屏幕底部并调用Readline.readline(或任何获取用户输入的方法)。像往常一样,它会读取所有内容,直到我按下回车键,并打印一个换行符。由于光标位于终端的最后一行,它会滚动一行,这会弄乱屏幕。我怎样才能避免这种情况?我试图使用stty来停止回显换行符,但我没有成功。也许可以使用stty来阻止终端滚动?当然,我可以编写自己的方法来通过一次读取一个字符(并捕获“返回”)来捕获

随机推荐