【问题标题】:Passing current time in milliseconds to MPChart breaks it以毫秒为单位将当前时间传递给 MPChart 会破坏它
【发布时间】:2017-09-14 08:26:51
【问题描述】:

我已经尝试解决这个问题,但它没有加起来。数据未按应有的方式显示。

首先我生成虚拟数据。这是异步完成的,因为我需要在调用System.currentTimeMillis 之间留出一些时间间隔。 (看看这里的烂代码,这只是调试数据,不会在发布中。考虑到 ANR,在主线程上使用 Thread.sleep 是个坏主意)

public class AsyncGeneration extends AsyncTask<String, String, String>{
    public AsyncGeneration() {
        super();
    }
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }
    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
    }
    @Override
    protected void onProgressUpdate(String... values) {
        super.onProgressUpdate(values);
    }
    @Override
    protected void onCancelled(String s) {
        super.onCancelled(s);
    }
    @Override
    protected void onCancelled() {
        super.onCancelled();
    }
    @Override
    protected String doInBackground(String... strings) {
        while(root == null) {
            try {
                Thread.sleep(200);
            }catch(InterruptedException e){}
        }
        List<Entry> rdata = new ArrayList<>();
        for(int i = 1; i < 30; i++){
            try{
                Thread.sleep(200);
            }catch(Exception e){
                //IGNORE
            }

            float time = System.currentTimeMillis();
            Log.e("GChart", "Timex: " + time);
            Session s = new Session(r.nextInt(5000), time);//Replace time with the index in the for-loop and it works for some reason
            rdata.add(new Entry(s.getXValue(), s.getYValue()));
            Log.e("GChart", "Timey: " + s.getXValue());
        }

        final List<Entry> entries = rdata;
        OverviewFragment.this.getActivity().runOnUiThread(() ->{

            LineDataSet data = new LineDataSet(entries, "Distance");
            data.setCircleColor(Color.parseColor("#FF0000"));
            LineData lineData = new LineData(data);
            tab1chart.setData(lineData);

            tab1chart.invalidate(); // refresh

            tab1chart.getXAxis().setValueFormatter(new DateFormatter());
            tab1chart.getXAxis().setPosition(XAxis.XAxisPosition.BOTTOM);
            tab1chart.getXAxis().setTextSize(10f);
            tab1chart.getXAxis().setTextColor(Color.RED);
            tab1chart.getXAxis().setDrawAxisLine(true);
            tab1chart.getXAxis().setDrawGridLines(true);
            tab1chart.getAxisLeft().setValueFormatter(new DistanceValueFormatter());
            tab1chart.getAxisLeft().setDrawGridLines(true);
            Log.v("Chart", "Chart data loaded and invalidated");//This prints

        });
        return null;
    }
}

到目前为止,一切看起来都很好。数据被放入图表中,没有异常,没有崩溃。

当图表呈现时,一个数据点会显示在图表的最左侧。我生成了 30 个数据点,其中一个出现了。

这是问题 #1:只显示一个数据点。

第 2 题稍微难一些。底部的整个 X 轴消失。 X 轴消失了,缩放时,Y 轴及其文本也消失了。这很难解释,所以这里是截图:

值得一提的是,如果我在 for 循环中传递 i 作为时间,它会按预期显示:所有轴都到位,缩放不会破坏任何东西。

(浮点值可以采用与 Long 相同的值,除了它们还有小数。)

另外,我格式化数据:

public class DateFormatter implements IAxisValueFormatter {
    SimpleDateFormat formatter;

    public DateFormatter(){
        formatter = new SimpleDateFormat("dd/MM/yy, HH:mm");
    }

    @Override
    public String getFormattedValue(float value, AxisBase axis) {
        //This method is never called. Nothing is returned
        if(axis instanceof XAxis) {
            String formatted = formatter.format(new Date((long) value));
            Log.d("Formatter", "Formatted \"" + value + "\" to \"" + formatted + "\".");
            return formatted;
        }
        return "Not supported";
    }
}

删除格式化程序不会改变任何东西,轴仍然消失了。缩放仍然会破坏 Y 轴。

所以我的问题是:我该如何解决这个问题?当我以毫秒为单位传递当前时间时,我不明白为什么图表不起作用(我用调试输出检查了值,浮点数可以处理它)。我早些时候得到了一些调试输出,最终完全停止显示传递给格式化程序的值是

图表本身似乎没有损坏,但从触摸事件看来,每个点都被推入相同的 X 坐标,但只有一个点呈现。当我触摸图表时,会出现橙色线条,指示数据点的位置。它会在不可见的点上弹出。

当我将 for 循环索引作为 X 值传递时,它按预期工作,格式化程序工作正常(撇开它显示日期为 1970 年的事实不谈,但它被计为 1 毫秒进入纪元,所以这是预期的)

我查看了this 以及格式化日期。当我尝试通过自纪元以来的毫秒数时,图表停止工作。

我正在使用 MPChart v 3.0.2,针对 Android 26 进行编译,使用 Java 8,并运行 Android Studio 3.0 beta 2

至于布局,它只是一个LinearLayout,里面有一个LineChart。


这应该可以,但是由于某种原因,当我以毫秒为单位传递当前时间时它会中断。传递任何其他数据(只要数字不是那么大)都可以正常工作。

这两个图像不是图表应有的外观。 X 轴应该是可见的,但由于某种原因,它并没有与大量数据一起显示。

【问题讨论】:

    标签: android mpandroidchart


    【解决方案1】:

    这是Android MPChart (have a read this thread) 的已知问题。 MPChart 中支持的时间序列图 - 您可以将时间(在 millis 中)设置为小时图的 X 值。

    但是过多的连续数据(点)无法正确绘制在折线图中。因为由于某些性能限制,Entry 对象将只接受浮点值。

    所以,保留第一个值作为参考,并从参考值中减去每个即将到来的值,然后除以一些常数(比如1000)。所以,你的X value 设置就像10,20,30....等等。

    在您的 Axis Value formatter 中执行反向逻辑以正确呈现 X Axis 标签(参见代码 sn-p)。

    lineChart.getXAxis().setValueFormatter(new IAxisValueFormatter() {
                @Override
                public String getFormattedValue(float value, AxisBase axis) {
    
                    SimpleDateFormat format2 = new SimpleDateFormat("HH:mm:ss");
                    return format2.format(new Date(firstTimeStamp + ((long) value) * 1000L));
    
                }
    
            });
    

    【讨论】:

    • 我已经除以十亿来得到数千,现在小数有问题。我无法获得足够的小数来支持它。分割时丢失了太多细节。 1000 没有效果,100 万没有效果,10 亿也没有效果。如果足够准确,最后一个可能会有
    • @LunarWatcher 在除法之前,您必须从参考/偏移值中减去每个值。您尝试过吗?
    • 现在就这样做。但我不能除,第一个数字是 0,除以 0 会引发 ArithmeticException。我不划分,但跟踪初始值并从中减去是可行的。图表现在按预期呈现,没有 X 轴消失或值停留在一个位置。谢谢! (不能再奖励 22 小时的赏金,但这是可行的。一旦 Stack Overflow 允许,我将奖励它)
    • @LunarWatcher 很高兴为您提供帮助。在这里您正在处理一些虚拟数据。因此它从 0 开始。在实际情况下,您将拥有一个时间戳,因此是一个非零值。:)
    • 我仍然会得到 0,当你有一个初始时间戳时,你也必须减去它。当time == initialTimetime -= initialTime time = 0 时。虚拟数据使用当前时间(以毫秒为单位),就像一个实时时间戳
    猜你喜欢
    • 2010-10-02
    • 1970-01-01
    • 1970-01-01
    • 2011-10-25
    • 2017-02-20
    • 1970-01-01
    • 1970-01-01
    • 2017-04-25
    相关资源
    最近更新 更多