草庐IT

android - 优化 Androidplot

coder 2023-12-02 原文

Androidplot (androidplot.com) 网站/论坛似乎已关闭,所以我会尝试在这里提出这个问题。

我有多点触控缩放和滚动。与 http://mlepicki.com/2012/03/androidplot-multitouch-zoom-scroll/ 类似的代码除了我有一个条形图。然而,对于 100 个数据点,它有明显的滞后。即使有 10 个柱线也只是显示。听起来像是它的绘图/计算/等等所有的酒吧。

关于如何优化它的任何想法?

我无法使用硬件渲染,因为我想支持 Android 2.1,但库不支持它(它中断了)。

最佳答案

我制作了一个自定义渲染器来解决我的滞后问题。似乎顺畅了许多。此代码基于版本 0.5。不知道它是否适用于 v0.51。

import android.graphics.*;
import com.androidplot.exception.PlotRenderException;
import com.androidplot.series.XYSeries;
import com.androidplot.util.ValPixConverter;
import com.androidplot.xy.BarFormatter;
import com.androidplot.xy.XYPlot;
import com.androidplot.xy.XYSeriesRenderer;

import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
 * Renders a point as a Bar
 */
public class OptimisedBarRenderer extends XYSeriesRenderer<BarFormatter> {

    private BarWidthStyle style = BarWidthStyle.FIXED_WIDTH;
    private float barWidth = 5;

    public OptimisedBarRenderer(XYPlot plot) {
        super(plot);
    }

    /**
     * Sets the width of the bars draw.
     * @param barWidth
     */
    public void setBarWidth(float barWidth) {
        this.barWidth = barWidth;
    }

    private final TreeMap<Number, XYSeries> tempSeriesMap = new TreeMap<Number, XYSeries>();

    @Override
    public void onRender(Canvas canvas, RectF plotArea) throws PlotRenderException {
        int longest = getLongestSeries();
        if(longest == 0) {
            return;  // no data, nothing to do.
        }
        tempSeriesMap.clear();

        for(int i = 0; i < longest; i++) {
            tempSeriesMap.clear();
            List<XYSeries> seriesList = getPlot().getSeriesListForRenderer(this.getClass());
            for(XYSeries series : seriesList) {
                if(i < series.size()) {
                    tempSeriesMap.put(series.getY(i), series);
                }
            }
            drawBars(canvas, plotArea, tempSeriesMap, i);
        }
    }

    @Override
    public void doDrawLegendIcon(Canvas canvas, RectF rect, BarFormatter formatter) {
        canvas.drawRect(rect, formatter.getFillPaint());
        canvas.drawRect(rect, formatter.getBorderPaint());
    }

    private int getLongestSeries() {
        int longest = 0;
        List<XYSeries> seriesList = getPlot().getSeriesListForRenderer(this.getClass());

        if(seriesList == null)
            return 0;

        for(XYSeries series :seriesList) {
            int seriesSize = series.size();
            if(seriesSize > longest) {
                longest = seriesSize;
            }
        }
        return longest;
    }

    private void drawBars(Canvas canvas, RectF plotArea, TreeMap<Number, XYSeries> seriesMap, int x) {
//        Paint p = new Paint();
//        p.setColor(Color.RED);

        Object[] oa = seriesMap.entrySet().toArray();
        Map.Entry<Number, XYSeries> entry;
        Number yVal = null;
        Number xVal = null;

        float halfWidth = barWidth * 0.5f;

        for(int i = oa.length-1; i >= 0; i--) {
            entry = (Map.Entry<Number, XYSeries>) oa[i];
            XYSeries tempEntry = entry.getValue();

            if(tempEntry != null) {
                yVal = tempEntry.getY(x);
                xVal = tempEntry.getX(x);

                if (yVal != null && xVal != null) {  // make sure there's a real value to draw
                    switch (style) {
                        case FIXED_WIDTH:
                            float pixX = ValPixConverter.valToPix(xVal.doubleValue(), getPlot().getCalculatedMinX().doubleValue(), getPlot().getCalculatedMaxX().doubleValue(), plotArea.width(), false) + plotArea.left;

                            float left = pixX - halfWidth;
                            float right = pixX + halfWidth;

                            boolean offScreen = left > plotArea.right || right < plotArea.left;

                            if(!offScreen){
                                float pixY = ValPixConverter.valToPix(yVal.doubleValue(), getPlot().getCalculatedMinY().doubleValue(), getPlot().getCalculatedMaxY().doubleValue(), plotArea.height(), true) + plotArea.top;

                                BarFormatter formatter = getFormatter(tempEntry);
                                if(Math.abs (left - right) > 1f){//Don't draw as it will be hidden anyway.
                                    canvas.drawRect(left, pixY, right, plotArea.bottom, formatter.getFillPaint());
                                }
                                canvas.drawRect(left, pixY, right, plotArea.bottom, formatter.getBorderPaint());

                            }
                            break;
                        default:
                            throw new UnsupportedOperationException("Not yet implemented.");
                    }
                }
            }
        }
    }
}

关于android - 优化 Androidplot,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10132885/

有关android - 优化 Androidplot的更多相关文章

  1. 安卓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,打开命令窗口,并将路

  2. Ruby 缺少常量表达式优化? - 2

    我希望Ruby的解析器会进行这种微不足道的优化,但似乎并没有(谈到YARV实现,Ruby1.9.x、2.0.0):require'benchmark'deffib1a,b=0,1whileb由于这两种方法除了在第二种方法中使用预定义常量而不是常量表达式外是相同的,因此Ruby解释器似乎在每个循环中一次又一次地计算幂常数。是否有一些Material说明为什么Ruby根本不进行这种基本优化或只在某些特定情况下进行? 最佳答案 很抱歉给出了另一个答案,但我不想删除或编辑我之前的答案,因为它下面有有趣的讨论。正如JörgWMittag所说,

  3. ruby-on-rails - 优化读取数据库和写入csv文件 - 2

    我正在尝试从数据库中读取大量单元格(超过100.000个)并将它们写入VPSUbuntu服务器上的csv文件。碰巧服务器没有足够的内存。我正在考虑一次读取5000行并将它们写入文件,然后再读取5000行,等等。我应该如何重构我当前的代码以使内存不会被完全消耗?这是我的代码:defwrite_rows(emails)File.open(file_path,"w+")do|f|f该函数由sidekiqworker调用:write_rows(user.emails)感谢您的帮助! 最佳答案 这里的问题是,当您调用emails.each时,

  4. 软约束、硬约束、Minimum Snap的轨迹优化方法 - 2

    文章目录前言约束硬约束的轨迹优化Corridor-BasedTrajectoryOptimizationBezierCurveOptimizationOtherOptions软约束的轨迹优化Distance-BasedTrajectoryOptimization优化方法前言可以看看我的这几篇Blog1,Blog2,Blog3。上次基于MinimumSnap的轨迹生成,有许多优点,比如:轨迹让机器人可以在某个时间点抵达某个航点。任何一个时刻,都能数学上求出期望的机器人的位置、速度、加速度、导数。MinimumSnap可以把问题转换为凸优化问题。缺点:MnimumSnap可以控制轨迹一定经过中间的

  5. ruby-on-rails - 负载测试期间 Unicorn CPU 使用率激增,优化方法 - 2

    我对为我的RubyonRails3.1.3应用优化我的Unicorn设置的方法很感兴趣。我目前正在高CPU超大实例上生成14个工作进程,因为我的应用程序在负载测试期间似乎受CPU限制。在模拟负载测试中,每秒大约20个请求重放请求,我的实例上的所有8个内核都达到峰值,盒子负载飙升至7-8个。每个unicorn实例使用大约56-60%的CPU。我很好奇可以通过哪些方式对其进行优化?我希望能够每秒将更多请求汇集到这种大小的实例上。内存和所有其他I/O一样完全正常。在我的测试过程中,CPU越来越低。 最佳答案 如果您受CPU限制,您希望使用

  6. 美团外卖搜索基于Elasticsearch的优化实践 - 2

    美团外卖搜索工程团队在Elasticsearch的优化实践中,基于Location-BasedService(LBS)业务场景对Elasticsearch的查询性能进行优化。该优化基于Run-LengthEncoding(RLE)设计了一款高效的倒排索引结构,使检索耗时(TP99)降低了84%。本文从问题分析、技术选型、优化方案等方面进行阐述,并给出最终灰度验证的结论。1.前言最近十年,Elasticsearch已经成为了最受欢迎的开源检索引擎,其作为离线数仓、近线检索、B端检索的经典基建,已沉淀了大量的实践案例及优化总结。然而在高并发、高可用、大数据量的C端场景,目前可参考的资料并不多。因此

  7. 基于RTS超低延时直播优化强互动场景体验 - 2

    RTS在阿里云视频直播的基础上进行底层技术优化,通过集成阿里云播放器SDK,支持在千万级并发场景下节点间毫秒级延时直播的能力,弥补了传统直播存在3~6秒延时的问题,确保了超低延时、低卡顿、秒开流畅的直播观看体验。本文介绍了基于RTS超低延迟直播优化强互动场景体验的最佳实践方案,并以阿里云播放器Aliplayer为例,详细介绍RTS超低延迟拉流接入、自动降级、排障信息获取等逻辑的实现,助力企业打造互动直播行业的产品竞争力。适用场景该方案适用于对超低延迟直播有诉求的客户,尤其是业务中存在强互动场景直播的场景。强互动场景直播主要是指对主播和观众存在互动,或观众存在更高实时性观看、画面互动需求的情况,

  8. ruby - 无法使用 CONSTANT 优化字符串 - 2

    我目前正在研究Ruby2.1.1的改进,但遇到了一些奇怪的事情。我正在尝试改进String类并定义一个名为FOO的常量。沙箱.rbmoduleFoobarrefineStringdoFOO="BAR"deffoobar"foobar"endendendusingFoobarputs"".class::FOO#=>uninitializedconstantString::FOO(NameError)puts"".foobar#=>"foobar"这给了我未初始化的常量String::FOO(NameError)。但是我可以调用"".foobar这让我相信我在正确的范围内。奇怪的是,如果我

  9. Android Studio开发之使用内容组件Content获取通讯信息讲解及实战(附源码 包括添加手机联系人和发短信) - 2

    运行有问题或需要源码请点赞关注收藏后评论区留言一、利用ContentResolver读写联系人在实际开发中,普通App很少会开放数据接口给其他应用访问。内容组件能够派上用场的情况往往是App想要访问系统应用的通讯数据,比如查看联系人,短信,通话记录等等,以及对这些通讯数据及逆行增删改查。首先要给AndroidMaifest.xml中添加响应的权限配置 下面是往手机通讯录添加联系人信息的例子效果如下分成三个步骤先查出联系人的基本信息,然后查询联系人号码,再查询联系人邮箱代码 ContactAddActivity类packagecom.example.chapter07;importandroid

  10. Android 10.0 设置默认launcher后安装另外launcher后默认Launcher失效的功能修复 - 2

    1.前言 在10.0的系统rom定制化开发中,在系统中有多个launcher的时候,会在开机进入launcher的时候弹窗launcher列表,让用户选择进入哪个launcher,这样显得特别的不方便所以产品开发中,要求用RoleManager的相关api来设置默认Launcher,但是在设置完默认Launcher以后,在安装一款Launcher的时候,默认Launcher就会失效,在系统设置的默认应用中Launcher选项就为空,点击home键的时候会弹出默认Launcher列表,让选择进入哪个默认Launcher.所以需要从安装Launcher的流程来分析相关的设置。来解决问题设置默认La

随机推荐