0

I am asking this question because, this is quiet no clear to me why my graph does not get update each time the user select to parse data for 1day or 1week or 1month basis. A similar How to update/remove/insert new series/data in Shinobi Line Chart in android?

I attempted the answer provided by a member called Kai, apparently he works for shinobicontrols.

You may also also note that I have implemented the shinobichart library inside a GraphFragment that seats in a view pager, which imports android.android.support.v4.app.Fragment;

ViewPagerAdapter class imports import android.support.v4.app.FragmentPagerAdapter; and the fragment transaction that calls the GraphFragment class budles an array of graph data from another activity that parses the JSON graphdata. I am trying to make this question clear so that when you read my code atleast you get an idea that the problem is not the JSON data because is pulled accordingly based on 1week, 1day or 1month. The issues is that Shinobichart does remove the series and its data but does not plot new parsed data. I read shinobichart user-guide how to handle chart-life cycle but was unable to find the solution I want. I also read ChartFragment handle onPause and onResume for the developer and I wonder If the same applies to SupportChartFragment.

Here is my GraphFragment that integrates shinobichart.Hope someone can help. Thank you in advance.

public class GraphFragment extends Fragment implements OnClickListener, 
        ShinobiChart.OnCrosshairActivationStateChangedListener{

private static final int CROSSHAIR_INACTIVE_COLOR = Color.argb(255, 240, 240, 240);
private static final int CROSSHAIR_ACTIVE_COLOR = Color.argb(150, 0, 0, 0);
Context context;
String label_x[];
ArrayList<DataAssetGraph> alAssetGraph = new ArrayList<DataAssetGraph>();
Button btnOneDayG, btnOneWeekG, btnOneMonthG;
String endDate;
String assetId;
ProgressDialog dialog;
ShinobiChart shinobiChart;
LineSeries series;
SupportChartFragment chartFragment;
String startDate;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    super.onCreateView(inflater, container, savedInstanceState);
    View view = null;
    view = inflater.inflate(R.layout.fragment_chart, null);
    initView(view);
    if (getArguments() != null) {
        alAssetGraph = (ArrayList<DataAssetGraph>) getArguments()
                .getSerializable(WebElement.RECORDS);
        if (alAssetGraph != null && alAssetGraph.size() > 0) {
            // DrawGraph(alAssetGraph);
             // Only setup the chart the first time the activity is created
            if (savedInstanceState == null) {
                // Log.d("Init Graph", "Retrieve"+ alAssetGraph);
                chartFragment =
                      (SupportChartFragment) getActivity().getSupportFragmentManager().findFragmentById(R.id.chart);
                    shinobiChart = chartFragment.getShinobiChart();
                    // TODO: replace <license_key_here> with you trial license key
                    shinobiChart.setLicenseKey("sCVfKPnWajLtffqMjAxNTA0MThzdGVybmx5QHJpZ2h0Y2xpY2t" +
                            "tZWRpYS5jby56YQ==rveipQf9y4819/K4wLwWKR86Q1RIViUBTLEhBXAwh6q5zW53TgYi" +
                            "JcIUvc3S7DhTfH4KzUNeol9Rc5rXrzLOBnzP0TStc8n+eytCBhUFEgR21Cv7gq1dLEvOu" +
                            "tLENUwUtZ6Crk+Z8syIKEuyfZ8/1gtPvHIc=BQxSUisl3BaWf/7myRmmlIjRnMU2cA7q+" +
                            "/03ZX9wdj30RzapYANf51ee3Pi8m2rVW6aD7t6Hi4Qy5vv9xpaQYXF5T7XzsafhzS3hbBo" +
                            "kp36BoJZg8IrceBj742nQajYyV7trx5GIw9jy/V6r0bvctKYwTim7Kzq+YPWGMtqtQoU=" +
                            "PFJTQUtleVZhbHVlPjxNb2R1bHVzPnh6YlRrc2dYWWJvQUh5VGR6dkNzQXUrUVAxQnM5b2" +
                            "VrZUxxZVdacnRFbUx3OHZlWStBK3pteXg4NGpJbFkzT2hGdlNYbHZDSjlKVGZQTTF4S2Zwe" +
                            "WZBVXBGeXgxRnVBMThOcDNETUxXR1JJbTJ6WXA3a1YyMEdYZGU3RnJyTHZjdGhIbW1BZ21PTT" +
                            "dwMFBsNWlSKzNVMDg5M1N4b2hCZlJ5RHdEeE9vdDNlMD08L01vZHVsdXM+PEV4cG9uZW50Pk" +
                            "FRQUI8L0V4cG9uZW50PjwvUlNBS2V5VmFsdWU+");
                    // Create the series
                    createLineSeries(alAssetGraph);

                   // Add this Activity as a listener for any crosshair changes
                   shinobiChart.setOnCrosshairActivationStateChangedListener(this);

            }

        } else {

        }
    }

    return view;
}
private void initView(View view)
{
    btnOneDayG=(Button)view.findViewById(R.id.btnOneDayG);
    btnOneWeekG=(Button)view.findViewById(R.id.btnOneWeekG);
    btnOneMonthG=(Button)view.findViewById(R.id.btnOneMonthG);
    btnOneDayG.setSelected(true);
    btnOneDayG.setOnClickListener(this);
    btnOneMonthG.setOnClickListener(this);
    btnOneWeekG.setOnClickListener(this);
}
@Override
public void onClick(View v) {
    switch (v.getId()) {
    case R.id.btnOneDayG:
        btnOneWeekG.setSelected(false);
        btnOneMonthG.setSelected(false);
        if(!btnOneDayG.isSelected())
        {
            btnOneDayG.setSelected(true);
            startDate=GlobalData.getDateBeforeOneDay();
            getGraphHistory(startDate);
            System.out.println("Btn Date 1 day: %tc"+startDate);
        }
        break;

    case R.id.btnOneWeekG:
        btnOneDayG.setSelected(false);
        btnOneMonthG.setSelected(false);
        if(!btnOneWeekG.isSelected())
        {
            btnOneWeekG.setSelected(true);
            startDate=GlobalData.getDateBeforeOneWeek();
            getGraphHistory(startDate);
            System.out.println("Btn Date 1 week: %tc"+startDate);

        }
        break;
    case R.id.btnOneMonthG:
        btnOneWeekG.setSelected(false);
        btnOneDayG.setSelected(false);
        if(!btnOneMonthG.isSelected())
        {
            btnOneMonthG.setSelected(true);
            startDate=GlobalData.getDateBeforeOneMonth();
            getGraphHistory(startDate);
            System.out.println("Btn Date 1 Month: %tc"+startDate);
        }
        break;

    default:
        break;
    }       
}

private void createLineSeries(ArrayList<DataAssetGraph> alGraph) {
    // TODO Auto-generated method stub
    shinobiChart.getSeries();

    // remove Series
    while (shinobiChart.getSeries().size() > 0) {
        shinobiChart.removeSeries(shinobiChart.getSeries().get(0));
    }

    // remove Axis
    while (shinobiChart.getAllXAxes().size() > 0) {
        shinobiChart.removeXAxis(shinobiChart.getAllXAxes().get(0));
    }
    while (shinobiChart.getAllYAxes().size() > 0) {
        shinobiChart.removeYAxis(shinobiChart.getAllYAxes().get(0));
    }
    // Create the X-axis, showing ticks daily with a custom format and
    // clipping the tick at the far right
    DateTimeAxis xAxis = new DateTimeAxis();
    // xAxis.setTitle("Date/Time");
    xAxis.enableGesturePanning(true);
    xAxis.enableGestureZooming(true);
    xAxis.getDoubleTapBehavior();
     // Create the Y-axis, clipping the tick at the top
    NumberAxis yAxis = new NumberAxis();
    // yAxis.setTitle("Temperature");
    yAxis.enableGesturePanning(true);
    yAxis.enableGestureZooming(true);

    // Declare length of graph array
    int length=alGraph.size();

    LineSeries series = new LineSeries();

    series.getStyle().getPointStyle().setPointsShown(false);

    DataAdapter<Date, Double> data = new SimpleDataAdapter<Date, Double>();

    for(int i=0;i<length;i++)
    {
        String dateString=alGraph.get(i).x_cord;
        double y_cord=  alGraph.get(i).y_cord;
        Date x_cord=convertToDate(dateString);
        data.add(new DataPoint<Date, Double>(x_cord, y_cord));
    }
    // reload and redraw the graph
     series.setDataAdapter(data);
     series.setCrosshairEnabled(true);
     shinobiChart.addSeries(series, xAxis, yAxis);
     series.getStyle().setLineColor(Color.WHITE);
     System.out.println("Add Series");
     // Style the chart and the crosshair
     shinobiChart.getStyle().setPlotAreaBackgroundColor(
              GraphFragment.CROSSHAIR_ACTIVE_COLOR);
     shinobiChart.getCrosshair().getStyle().setLineColor(Color.BLUE);
     shinobiChart.getStyle().setBackgroundColor(Color.WHITE);
     // shinobiChart.getStyle().setPlotAreaBackgroundColor(Color.BLACK);
     shinobiChart.getStyle().getBackgroundColor();
     shinobiChart.getXAxis().getStyle().getGridlineStyle().setGridlinesShown(true);
     shinobiChart.getYAxis().getStyle().getGridlineStyle().setGridlinesShown(true);
     // Remember to redraw the chart to make the changes visible
     shinobiChart.redrawChart();
}

private Date convertToDate(String dateString)
{
    Date convertedDate= new Date();

    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
    try 
    {
        convertedDate = dateFormat.parse(dateString);
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        return null;
    }

    return convertedDate;
}

private void getGraphHistory(String start_date)
{
        System.out.println("Get graph History: %tc"+ start_date);
        dialog= new ProgressDialog(getActivity());
        dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        dialog.setMessage("Retrieving graph...");
        dialog.setCanceledOnTouchOutside(false);
        dialog.show();
        endDate=GlobalData.getCurrentDate();
        assetId=ComponentActivity.assetId;
        new LoadAssetGraphTask(getActivity(),assetId, start_date,endDate)
        {
            @Override
            protected void onPostExecute(ArrayList<DataAssetGraph> result) 
            {
                super.onPostExecute(result);
                if(dialog.isShowing())
                    dialog.dismiss();
                if(result!=null && result.size()>0)
                {   
                    createLineSeries(result);
                    System.out.println("onPostExecute Called");
                }

            };
        }.execute();


    //}
}

@Override
public void onCrosshairActivationStateChanged(ShinobiChart chart) {
    // Set the plot area background color depending on the crosshair's
    // activation state
    if (chart.getCrosshair().isActive()) {
        chart.getStyle().setPlotAreaBackgroundColor(GraphFragment.CROSSHAIR_ACTIVE_COLOR);
        chart.getLegend().getStyle().setTextColor(Color.WHITE);
    }
    else {
        chart.getStyle().setPlotAreaBackgroundColor(GraphFragment.CROSSHAIR_INACTIVE_COLOR);
        chart.getLegend().getStyle().setTextColor(Color.BLACK);
    }

    // Remember to redraw the chart to make the color change visible
    chart.redrawChart();
}
Community
  • 1
  • 1
Cockpit Aliens
  • 411
  • 6
  • 18

1 Answers1

0

I appreciate that it is some time since you have asked this. As it is unanswered, I will try to provide an answer, also in case other people ask similar questions.

Can you please post the rest of your code as it is difficult to get the full picture of what your code is doing? For example your layout files, Activity file and your LoadAssetGraphTask file.

In the meantime, I have created a simple application which has one main activity which contains a ViewPager. I have extended SupportChartFragment and I hold 3 charts in the ViewPager. I have 3 buttons in my Activity, which load 3, 6 and 12 months of data to the chart.

I have kept my data quite simple for the purposes of this exercise, I simply hard code it. I was successful in being able to dynamically re-load my data upon clicking the buttons. You can see my app on GitHub here:

https://github.com/Kai2k/ViewPagerChartFragment

I can make several observations about your code:

To reload your chart you do not necessarily need to remove your axes and the Series. Having said that, every time you add a data point to your DataAdapter, a full draw of the chart is invoked which may hamper performance. As such you may like to detach your DataAdapter from your Series, update your data and then re-attach it.

I notice you have made your Fragment implement OnClickListener. I noticed using this approach the chart was not initially updated, but in fact another chart within the ViewPager (which was currently off-screen) was updated instead. I notice that as I paged though my pages within the ViewPager, all of the contained charts were updated. At this point in time I am no expert on how the ViewPager class internally handles the creation and destruction of fragments, but this may certainly be an area to investigate further.

When I set the click listener in the Activity and 'push' the command to reload to the current fragment, it works.

You may also have an issue with your LoadAssetGraphTask, which I believe is an AsyncTask. Obviously I cannot see this code at present so I do not know what this class will be doing. Have you tried a simpler approach first, with dummy data within your Fragment (as I have) to rule out any issue with the AsyncTask?

SupportChartFragment and ChartFragment do handle life cycle call backs for you, so you do not need to override onPause or onResume. You may have issues however if you try to nest your Fragment inside another Fragment, because ChartFragment/SupportChartFragment is retained across Activity re-creation and the Android framework does not allow retained Fragments within other Fragments. If your use-case dictates this you may find using a ChartView a more suitable approach. In this case you would need to handle life cycle call backs.

If you wish to use the ChartFragment or SupportChartFragment, another approach might be to extend the class directly, rather than extend Fragment. This is the approach which I have taken in my app. With this approach you are less likely to encounter inflation issues when inflating nested fragments.

I hope that this helps. Thanks, Kai.

Disclaimer - I work for Shinobicontrols.

Kai
  • 186
  • 2
  • 10