简体   繁体   中英

ArrayList Error, App Crashes

I have the following problem. I have a two fragment application with a static arraylist which is used in both fragments .

The occurance of the error can be described like this:

  1. Add entries to arraylist ( FragmentA )
  2. Hit button, display arraylist in chart ( Fragment B )
  3. Go back to Fragment A , add another entrie to arraylist -> error occurs, app crashes

The code of the fragments is this:

  • Fragment A

     button.setOnClickListener(new View.OnClickListener() { public void onClick (View view) { if (editText3.getText().toString().matches("")) { Toast.makeText(getActivity(), "You did not enter a Valid Item ID", Toast.LENGTH_LONG).show(); return; } else if (editText2.getText().toString().matches("")) { Toast.makeText(getActivity(), "You did not enter a Valid Quantitiy", Toast.LENGTH_LONG).show(); return; } else { String nomen = (editText3.getText().toString()); float number = Float.parseFloat(editText2.getText().toString()); entries.add(new PieEntry(number, nomen)); editText3.setText(""); editText2.setText(""); editText3.requestFocus(); } } }); 
  • Fragment B

      button2.setOnClickListener(new View.OnClickListener() { public void onClick (View view) { getResources().getColor(R.color.violp); getResources().getColor(R.color.bluep); getResources().getColor(R.color.redp); getResources().getColor(R.color.greenp); getResources().getColor(R.color.yellowp); getResources().getColor(R.color.orangep); getResources().getColor(R.color.lightbluep); getResources().getColor(R.color.purplep); getResources().getColor(R.color.darkredp); PieDataSet set = new PieDataSet(entries, ""); set.setColors(new int[]{R.color.bluep, R.color.greenp, R.color.violp, R.color.redp, R.color.yellowp, R.color.orangep, R.color.lightbluep, R.color.purplep, R.color.darkredp}, getActivity()); PieData datax = new PieData(set); piechart.setData(datax); Toast.makeText(getActivity(), (R.string.loading), Toast.LENGTH_SHORT).show(); piechart.setNoDataText(String.valueOf(R.string.nodata)); piechart.notifyDataSetChanged(); piechart.animateX(2000, Easing.EasingOption.EaseInExpo); piechart.animateY(2000, Easing.EasingOption.EaseInExpo); } }); 

THE ERROR IM GETTING IS THIS:

java.lang.ArrayIndexOutOfBoundsException: length=1; index=1

If some expereienced experts could help me out I would be very grateful. Thanks.

UPDATE: ERROR STACK INCLUDED

E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: com.example.nextpietwo, PID: 2528
                  java.lang.ArrayIndexOutOfBoundsException: length=1; index=1
                      at com.github.mikephil.charting.renderer.PieChartRenderer.drawDataSet(PieChartRenderer.java:244)
                      at com.github.mikephil.charting.renderer.PieChartRenderer.drawData(PieChartRenderer.java:147)
                      at com.github.mikephil.charting.charts.PieChart.onDraw(PieChart.java:126)
                      at android.view.View.draw(View.java:17185)
                      at android.view.View.updateDisplayListIfDirty(View.java:16167)
                      at android.view.View.draw(View.java:16951)
                      at android.view.ViewGroup.drawChild(ViewGroup.java:3727)
                      at android.view.ViewGroup.dispatchDraw(ViewGroup.java:3513)
                      at android.view.View.updateDisplayListIfDirty(View.java:16162)
                      at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3711)
                      at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3691)
                      at android.view.View.updateDisplayListIfDirty(View.java:16130)
                      at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3711)
                      at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3691)
                      at android.view.View.updateDisplayListIfDirty(View.java:16130)
                      at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3711)
                      at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3691)
                      at android.view.View.updateDisplayListIfDirty(View.java:16130)
                      at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3711)
                      at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3691)
                      at android.view.View.updateDisplayListIfDirty(View.java:16130)
                      at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3711)
                      at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3691)
                      at android.view.View.updateDisplayListIfDirty(View.java:16130)
                      at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3711)
                      at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3691)
                      at android.view.View.updateDisplayListIfDirty(View.java:16130)
                      at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3711)
                      at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3691)
                      at android.view.View.updateDisplayListIfDirty(View.java:16130)
                      at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:648)
                      at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:654)
                      at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:762)
                      at android.view.ViewRootImpl.draw(ViewRootImpl.java:2800)
                      at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2608)
                      at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2215)
                      at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1254)
                      at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6337)
                      at android.view.Choreographer$CallbackRecord.run(Choreographer.java:874)
                      at android.view.Choreographer.doCallbacks(Choreographer.java:686)
                      at android.view.Choreographer.doFrame(Choreographer.java:621)
                      at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:860)
                      at android.os.Handler.handleCallback(Handler.java:751)
                      at android.os.Handler.dispatchMessage(Handler.java:95)
                      at android.os.Looper.loop(Looper.java:154)
                      at android.app.ActivityThread.main(ActivityThread.java:6119)
                      at java.lang.reflect.Method.invoke(Native Method)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

MPAndroidChart cannot shield you from the effects of not separating model and view layers and from issues with the managing the lifecycles of Fragments and Activities. Please note that "communicating" between Fragments (such as one Fragment manipulating the data of another) is not recommended by Google :

Two Fragments should never communicate directly

Although Entry may look like a member of the model layer, it is actually designed to be tightly coupled with PieChart which is part of the view layer. It definitely should not outlive the View with which it is associated and if you want to avoid errors such as the ArrayIndexOutOfBoundsException , the backing List lifecycle should coincide with that of the Fragment in which it is used. This does not mean that you can never add/remove from a List<Entry> once this is part of a PieChart - MPAndroidChart will allow you to do this within the above constraints.

To fix the above error, I would suggest a different approach than sharing a static object which is almost never a good idea in Android. You could share, instead, a separate model layer which contains the data you will use to construct the List<Entry> . When Fragment A updates the model, you can use an event to trigger rebuilding of the chart from the data inside Fragment B.

You have stated in the comments that you are using a ViewPager . The ViewPager uses fragmentTransaction.show() and .hide() and generally keeps the Fragments in a resumed state. Perhaps the easiest solution is to override onHiddenChanged as this is always called when the ViewPager switches to a new page. I think (not 100% sure) that you will also need a call in onActivityCreated(View v) .

So, you would have something like this:

@Override
onActivityCreated(View v) {
    //get updated model from Activity
    //rebuild chart from updated model
}

@Override 
onHiddenChanged(boolean hidden) {
    if (hidden == false) {
        //get updated model from Activity
        //rebuild chart from updated model
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM