0

I'm currently working on my final project and I have stuck.

I have Firebase Realtime Database what is connected with my mobile app written in Android (Java). The database on which I am working has the following structure:

The idea of a solution is that I for the 7 days (with current date) take ukpromet from the database and save it to ArrayList which is making bar chart in the fragment.

The code that is for now:

public class TjednoIzvjesceFragment extends Fragment {

    final List<Float> tjednoIzvjesce = new ArrayList<>();
    public ArrayList<BarEntry> entries = new ArrayList<>();

    String korisnik, year, month, day;
    Float ukpromet;
    Integer dayx;
    Integer monthx;
    Integer yearx;
    // Baza
    FirebaseDatabase rootNode;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_tjedno_izvjesce, container, false);


        BarChart barChart = view.findViewById(R.id.barChart);
        
        // Testing ArrayList and Bar Chart 
        //entries.add(new BarEntry(0,2));
        
        korisnik = ((HomeActivity) requireActivity()).korisnickoIme;


        // Current date
        String sadasnjiDatum = new SimpleDateFormat("dd/MM/yyyy", Locale.getDefault()).format(new Date());

        //Current date in string
        String[] separated = sadasnjiDatum.split("/");
        dan = separated[0];
        month = separated[1];
        year = separated[2];

        //Current date in integer
        int danasdd = Integer.parseInt(dan);
        int monthdd = Integer.parseInt(month);
        int yeardd = Integer.parseInt(year);

        String korisnik = ((HomeActivity) requireActivity()).korisnickoIme;
        // Putanja do baze smjena vozaca
        rootNode = FirebaseDatabase.getInstance();
        DatabaseReference reference = rootNode.getReference("Vozaci");

        // Current date for work in integer
        dayx = todaydd;
        monthx = monthdd;
        yearx = yeardd;

        // 7 days
        int counter = 7;

        for(int i = 0; i < counter; i++){

            if (dayx <= 0) {
                ...
            }


            // DatabaseReference danPutanja = reference.child(korisnik).child("smjene").child(String.valueOf(yearx)).child("09").child(String.valueOf(dayx));
            DatabaseReference danPutanja = reference.child(korisnik).child("smjene").child("2021").child("09").child("13");

            readData(danPutanja,i, entries -> {
            });

            dayx--;
        }


        ArrayList<String> datumi = new ArrayList<>();

        datumi.add("13.09");
        datumi.add("14.09");
        datumi.add("15.09");
        datumi.add("16.09");
        datumi.add("17/09");
        datumi.add("18./09");
        datumi.add("19./09");

        // Chart Data
        BarDataSet bardataset = new BarDataSet(entries, "DateSet1");
        bardataset.setColors(ColorTemplate.COLORFUL_COLORS);

        BarData data = new BarData(bardataset);
        data.setBarWidth(0.9f);

        // Chart layout
        barChart.setDrawBarShadow(false);
        barChart.setDrawValueAboveBar(true);
        barChart.setPinchZoom(false);
        barChart.setDrawGridBackground(true);
        barChart.setData(data); // set the data and list of labels into chart
        barChart.animateY(2000);
        barChart.invalidate();
        barChart.getDescription().setEnabled(false);


        // Legend
        Legend legend = barChart.getLegend();
        legend.setEnabled(false);

        // X axis
        XAxis xAxis = barChart.getXAxis();
        //xAxis.setCenterAxisLabels(true);
        xAxis.setEnabled(true);
        //xAxis.setDrawGridLines(false);
        xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
        xAxis.setValueFormatter(new com.github.mikephil.charting.formatter.IndexAxisValueFormatter(datumi));

        return view;
    }


    private void readData(DatabaseReference danPutanja, float counter, FirebaseCallback firebaseCallback){
        danPutanja.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                String getUkpromet;
                if (dataSnapshot.exists()) {
                    getUkpromet = dataSnapshot.child("ukPromet").getValue(String.class);
                } else {
                    getUkpromet = "0";
                }
                ukpromet = Float.parseFloat(getUkpromet);
                System.out.println(ukpromet);
                tjednoIzvjesce.add(ukpromet);
                entries.add(new BarEntry(counter,ukpromet));
                Log.e("!__@::>", counter + " " + ukpromet);

                firebaseCallback.onCallBack(entries);
            }

            @Override
            public void onCancelled(@NonNull DatabaseError error) {
                Log.d("Error: ", error.getMessage());
            }
        });
    }

    private interface FirebaseCallback{
        void onCallBack(ArrayList<BarEntry> entries);
    }
}

The problem is that nothing is added to the array.

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: hr.vsite.map.taxivodstvo, PID: 1314
    java.lang.ArrayIndexOutOfBoundsException: length=0; index=0
        at com.github.mikephil.charting.buffer.BarBuffer.addBar(BarBuffer.java:37)
        at com.github.mikephil.charting.buffer.BarBuffer.feed(BarBuffer.java:80)
        at com.github.mikephil.charting.renderer.BarChartRenderer.drawDataSet(BarChartRenderer.java:144)
        at com.github.mikephil.charting.renderer.BarChartRenderer.drawData(BarChartRenderer.java:82)
        at com.github.mikephil.charting.charts.BarLineChartBase.onDraw(BarLineChartBase.java:237)
        at android.view.View.draw(View.java:21421)
        at android.view.View.updateDisplayListIfDirty(View.java:20298)
        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4372)
        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4345)
        at android.view.View.updateDisplayListIfDirty(View.java:20258)
        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4372)
        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4345)
        at android.view.View.updateDisplayListIfDirty(View.java:20258)
        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4372)
        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4345)
        at android.view.View.updateDisplayListIfDirty(View.java:20258)
        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4372)
        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4345)
        at android.view.View.updateDisplayListIfDirty(View.java:20258)
        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4372)
        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4345)
        at android.view.View.updateDisplayListIfDirty(View.java:20258)
        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4372)
        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4345)
        at android.view.View.updateDisplayListIfDirty(View.java:20258)
        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4372)
        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4345)
        at android.view.View.updateDisplayListIfDirty(View.java:20258)
        at android.view.View.draw(View.java:21153)
        at android.view.ViewGroup.drawChild(ViewGroup.java:4388)
        at androidx.drawerlayout.widget.DrawerLayout.drawChild(DrawerLayout.java:1426)
        at android.view.ViewGroup.dispatchDraw(ViewGroup.java:4149)
        at android.view.View.draw(View.java:21424)
        at android.view.View.updateDisplayListIfDirty(View.java:20298)
        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4372)
        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4345)
        at android.view.View.updateDisplayListIfDirty(View.java:20258)
        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4372)
        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4345)
        at android.view.View.updateDisplayListIfDirty(View.java:20258)
        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4372)
        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4345)
        at android.view.View.updateDisplayListIfDirty(View.java:20258)
        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4372)
        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4345)
        at android.view.View.updateDisplayListIfDirty(View.java:20258)
        at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4372)
        at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4345)
        at android.view.View.updateDisplayListIfDirty(View.java:20258)
        at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:575)
        at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:581)
        at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:654)
        at android.view.ViewRootImpl.draw(ViewRootImpl.java:3610)
        at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:3418)
        at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2755)
        at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1721)
E/AndroidRuntime:     at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:7598)
        at android.view.Choreographer$CallbackRecord.run(Choreographer.java:966)
        at android.view.Choreographer.doCallbacks(Choreographer.java:790)
        at android.view.Choreographer.doFrame(Choreographer.java:725)
        at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:951)
        at android.os.Handler.handleCallback(Handler.java:883)
        at android.os.Handler.dispatchMessage(Handler.java:100)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

How I understand, the problem appears because of the asynchronous behavior of Firebase API.

I have checked Mr. Alex Mamo tutorial and few articles about the problem. I'm not sure anymore what it could be Anyone has any idea how I can make it work?

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
iputak
  • 1
  • 2
  • Is your onDataChange() even triggered? What is the location of the database, Europe? – Alex Mamo Sep 29 '21 at 10:17
  • Yes, it is triggered. I can see it in logs: ` E/!__@::>: 0.0 705.0 I/System.out: 705.0 E/!__@::>: 1.0 705.0 I/System.out: 705.0 E/!__@::>: 2.0 705.0 I/System.out: 705.0 E/!__@::>: 3.0 705.0 I/System.out: 705.0 E/!__@::>: 4.0 705.0 I/System.out: 705.0 E/!__@::>: 5.0 705.0 I/System.out: 705.0 E/!__@::>: 6.0 705.0 D/AndroidRuntime: Shutting down VM E/AndroidRuntime: FATAL EXCEPTION: main Process: hr.vsite.map.taxivodstvo, PID: 1314 java.lang.ArrayIndexOutOfBoundsException: length=0; index=0 ` **Database location**: United States (us-central1). – iputak Sep 29 '21 at 10:51
  • At which particular line of code are you getting that error? – Alex Mamo Sep 29 '21 at 11:37

1 Answers1

0
java.lang.ArrayIndexOutOfBoundsException: length=0; index=0
        at com.github.mikephil.charting.buffer.BarBuffer.addBar(BarBuffer.java:37)
        at com.github.mikephil.charting.buffer.BarBuffer.feed(BarBuffer.java:80)
        at com.github.mikephil.charting.renderer.BarChartRenderer.drawDataSet(BarChartRenderer.java:144)
        at com.github.mikephil.charting.renderer.BarChartRenderer.drawData(BarChartRenderer.java:82)
        at com.github.mikephil.charting.charts.BarLineChartBase.onDraw(BarLineChartBase.java:237)
        at android.view.View.draw(View.java:21421)

Read the stack from the bottom up.

Android is trying to draw your custom view. When it tries to draw, it's looking for some data.

This is likely happening before the Firebase database has replied with the data it is expecting. (The code you have in your onCreate method calls out to firebase, firebase uses an async method to retrieve the data, therefore the Android UI carries on attempting to draw the screen whilst this is happening in the background).

You haven't shared BarBuffer or BarLineChartBase so can't recommend a fix, other than to say, your onDraw method should check if it actually has data to draw (i.e. if the array is empty, then skip drawing (or draw an empty view)).

This might be of interest: Do we need to use background thread for retrieving data using firebase?

Blundell
  • 75,855
  • 30
  • 208
  • 233