微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 Firebase 数据更新 mpandroidchart 时出现问题

如何解决使用 Firebase 数据更新 mpandroidchart 时出现问题

我的问题总结是我正在从 Firebase 数据库中检索实时数据,并且我正在尝试将模拟数据输入到我的数据库中。每次我加载一个新值时,我的图表都不会反映我想要的方式。我的代码支持图片如下。提前感谢您的帮助!

图表基本上不会从 Firebase 中绘制我输入数据的新值并刷新图表,它只是绘制了一条奇怪的线,我不知道它来自哪里。

Homepage.java 包含我的图表

package com.example.myapplication;

import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;

import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.IMarker;
import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
import com.github.mikephil.charting.utils.Utils;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.Query;
import com.google.firebase.database.ValueEventListener;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.Month;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Date;

public class Homepage extends AppCompatActivity{

    private LineChart chart;
    private FirebaseUser user;
    private DatabaseReference reference;
    private String userID;
    private TextView tvTitle;
    long reference_timestamp;

    ArrayList<Long> acTime = new ArrayList<>();
    ArrayList<Long> newAcTime = new ArrayList<>();
    ArrayList<Long> acValues = new ArrayList<>();
    ArrayList<Entry> result = new ArrayList<>();


    @RequiresApi(api = Build.VERSION_CODES.O)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_homepage);

        tvTitle = findViewById(R.id.tvTitle);
        chart = findViewById(R.id.petChart);
        chart.setDragEnabled(true);
        chart.setScaleEnabled(true);

        LocalDateTime dt = LocalDateTime.of(2021,Month.FEBRUARY,20,0);
        LocalDateTime dt2 = LocalDateTime.of(2021,23,59,59);

        long startTime = dt.toEpochSecond(ZoneOffset.UTC);
        System.out.println("startTime:" + startTime + " " + dt);
        long endTime = dt2.toEpochSecond(ZoneOffset.UTC);
        System.out.println("endTime:" + endTime + " " + dt2);

        user = FirebaseAuth.getInstance().getCurrentUser();
        userID = user.getUid();
        reference = FirebaseDatabase.getInstance().getReference("Users/" + userID + "/Data");
        Query query = reference.orderByKey().startAt(String.valueOf(startTime)).endAt(String.valueOf(endTime));

        System.out.println("Printing query:" + query);

        System.out.println("Printing reference:" + reference);

        query.addValueEventListener(new ValueEventListener() {

            boolean wasCalled = false;

            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

                System.out.println("wasCalled: " + wasCalled);

                if (!wasCalled)
                {

                    System.out.println("getting accelerometer values");
                    for (DataSnapshot valueSnapshot : dataSnapshot.getChildren())
                    {
                        acValues.add(Long.parseLong((valueSnapshot.getValue(String.class))));
                        acTime.add(Long.parseLong((valueSnapshot.getKey())));
                    }

                    long temp_time;

                    System.out.println("acTimeRef:" + acTime.get(0));
                    for (int i = 0; i < acTime.size(); i++)
                    {
                        System.out.println(acValues.get(i));
                        reference_timestamp = acTime.get(0);
                        temp_time = acTime.get(i) - reference_timestamp;
                        newAcTime.add(temp_time);

                        result.add(new Entry(newAcTime.get(i),acValues.get(i)));
                    }


                    Date date = new Date(acTime.get(0)*1000);
                    DateFormat format = new SimpleDateFormat("MMMM d,yyyy");
                    String formatted = format.format(date);

                    tvTitle.setText("Accelerometer Data for " + formatted);

                    chart.setBackgroundColor(Color.WHITE);
                    chart.getDescription().setEnabled(false);
                    chart.setTouchEnabled(true);
                    chart.setDragEnabled(true);
                    chart.setScaleEnabled(true);
                    chart.setDrawGridBackground(false);
                    chart.setHighlightPerDragEnabled(true);

                    chart.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                        @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
                        @Override
                        public void onGlobalLayout() {
                            chart.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                            int offset = (chart.getHeight() - chart.getWidth()) / 100;

                            FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) chart.getLayoutParams();
                            layoutParams.width = chart.getHeight();
                            layoutParams.height = chart.getWidth();
                            chart.setLayoutParams(layoutParams);

                            chart.setTranslationX(offset);
                            chart.setTranslationY(offset);

                            IMarker marker = null;
                            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
                                marker = new YourMarkerView(getApplicationContext(),R.layout.marker,reference_timestamp);
                            }
                            chart.setMarker(marker);
                            chart.setExtraOffsets(10,10,10);


                            Legend l = chart.getLegend();

                            l.setForm(Legend.LegendForm.LINE);
                            l.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP);
                            l.setHorizontalAlignment(Legend.LegendHorizontalAlignment.RIGHT);
                            l.setorientation(Legend.LegendOrientation.HORIZONTAL);
                            l.setDrawInside(false);


                            XAxis xAxis = chart.getXAxis();
                            xAxis.setPosition(XAxis.XAxisPosition.BottOM);
                            xAxis.setTextSize(16f);
                            xAxis.setValueFormatter(new XAxisValueFormatter(reference_timestamp));
                            xAxis.setDrawGridLines(false);
                            xAxis.setCenteraxisLabels(true);
                            xAxis.setLabelCount(5);
                            xAxis.setCenteraxisLabels(true);

                            YAxis leftAxis = chart.getAxisLeft();
                            leftAxis.setPosition(YAxis.YAxisLabelPosition.OUTSIDE_CHART);
                            leftAxis.setDrawGridLines(false);
                            leftAxis.setGranularityEnabled(true);
                            leftAxis.setLabelCount(5);
                            leftAxis.setTextSize(16f);
                            leftAxis.setTextColor(Color.BLACK);

                            YAxis rightAxis = chart.getAxisRight();
                            rightAxis.setEnabled(false);

                        }

                    });
                }

                LineDataSet set1;

                if (chart.getData() != null &&
                        chart.getData().getDataSetCount() > 0) {

                    set1 = (LineDataSet) chart.getData().getDataSetByIndex(0);
                    set1.notifyDataSetChanged();
                    set1.setValues(result);

                    System.out.println("set1: " + set1);

                    chart.animateX(1000);


                    chart.getData().notifyDataChanged();
                    chart.notifyDataSetChanged();



                }

                else
                {
                    set1 = new LineDataSet(result,"Accelerometer Data");
                    set1.setDrawValues(false);
                    set1.setAxisDependency(YAxis.AxisDependency.LEFT);
                    set1.setColor(Color.rgb(57,57,57));
                    set1.setlinewidth(3f);
                    set1.setDrawCircles(true);
                    set1.setCircleRadius(3.5f);
                    set1.setCircleColor(Color.rgb(112,141,255));

                    if (Utils.getSDKInt() >= 18) {
                        // fill drawable only supported on api level 18 and above
                        Drawable drawable = ContextCompat.getDrawable(Homepage.this,R.drawable.blue_gradient);
                        set1.setFillDrawable(drawable);
                    } else {
                        set1.setFillColor(Color.BLACK);
                    }

                    set1.setDrawFilled(true);


                    ArrayList<ILineDataSet> dataSets = new ArrayList<>();

                    dataSets.add(set1);

                    LineData data2 = new LineData(dataSets);
                    
                    chart.setData(data2);
                    chart.notifyDataSetChanged();
                    chart.invalidate();
                }

            }


            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {
                throw databaseError.toException();
            }
        });

    }

}

YourMarkerView.java(创建这个类是为了让用户点击标记以在图表上显示更详细的时间)

package com.example.myapplication;

import android.content.Context;
import android.graphics.Canvas;
import android.os.Build;
import android.widget.TextView;

import androidx.annotation.RequiresApi;

import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.MarkerView;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.highlight.Highlight;
import com.github.mikephil.charting.utils.MPPointF;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;

@RequiresApi(api = Build.VERSION_CODES.O)
public class YourMarkerView extends MarkerView {

    private TextView tvContent;
    long reference_timestamp;
    private LocalDateTime mDate;
    private DateTimeFormatter mDataFormat;
    private LineChart chart;
    private Context mContext;


    public YourMarkerView(Context context,int layoutResource,long reference_timestamp) {
        super(context,layoutResource);

        // find your layout components
        chart = findViewById(R.id.petChart);
        tvContent = (TextView) findViewById(R.id.tvContent);
        this.mContext = context;
        this.reference_timestamp = reference_timestamp;
        this.mDataFormat = DateTimeFormatter.ofPattern("h:mm:ss a");
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    @Override
    public void refreshContent(Entry e,Highlight highlight) {

        long currentTimestamp = (long)e.getX() + reference_timestamp;
        System.out.println("currentTimestamp:" + currentTimestamp);
        tvContent.setText(e.getY() + " m/s^2 at " + getTimedate(currentTimestamp)); // set the entry-value as the display text

        // this will perform necessary layouting
        super.refreshContent(e,highlight);
    }


    @Override
    public void draw(Canvas canvas,float posx,float posy)
    {
        // Check marker position and update offsets.
        System.out.println("Posx:" + posx);
        int w = getWidth();
        int h = getHeight();
        if((getResources().getdisplayMetrics().widthPixels-posx-w) < w) {
            posx -= w;
        }
        System.out.println("Posx:" + posx);


        if (getResources().getdisplayMetrics().heightPixels-posy-h < h)
        {
            posy-=h;
        }

        if (posx < 0)
        {
            posx+=w;
        }


        canvas.translate(posx,posy);
        draw(canvas);
        canvas.translate(-posx,-posy);
    }

    private MPPointF mOffset;

    @Override
    public MPPointF getoffset() {
        if (mOffset == null) {
            mOffset = new MPPointF(-(getWidth() / 2),-getHeight());
        }

        return mOffset;
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    private String getTimedate(long timestamp) {

        try {
            Instant instant = Instant.ofEpochSecond(timestamp);
            LocalDateTime dt =
                    instant.atZone(ZoneId.systemDefault()).toLocalDateTime();

//            System.out.println("Marker: " + dt);

            String formatted = mDataFormat.format(dt);
            return formatted;
        } catch (Exception ex) {
            return "xx";
        }
    }
}

XAxisValueFormatter.java(格式化x轴以使其易于理解)

package com.example.myapplication;

import android.os.Build;

import androidx.annotation.RequiresApi;

import com.github.mikephil.charting.components.AxisBase;
import com.github.mikephil.charting.formatter.ValueFormatter;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;

public class XAxisValueFormatter extends ValueFormatter {
    long reference_timestamp;

    public XAxisValueFormatter(long reference_timestamp)
    {
        this.reference_timestamp = reference_timestamp;

    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    @Override
    public String getFormattedValue(float value) {

        long epoch = (((long)value + reference_timestamp));

        // Show time in local version
        Instant instant = Instant.ofEpochSecond(epoch);
        LocalDateTime dt =
                instant.atZone(ZoneId.systemDefault()).toLocalDateTime();

        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("h:mm:ss a");
        String formatted = dtf.format(dt);

        return formatted;
    }

    @RequiresApi(api = Build.VERSION_CODES.O)
    public String getAxisLabel(float value,AxisBase axis) {
        return getFormattedValue(value);
    }
}

What I want the graph to look like when new values are being inputted

What the graph looks like instead

Screenshot of database

Screenshot of database

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。