0

I am following to plot following this example. Things work if I have a static JSON and it will plot the data like shown in the website. However, I am retrieving data from MySQL and they are being updated every hour (I had look into this; create a button and potential to call the URL every hour), but I am not too sure if that's the efficient approach.
My question is if I have a MySQL table/data that is being every hour, how do I retrieve them and plot (retain old values as well as plot the new ones)? I have the following

Api Client with URL:

public class ApiClient {

    private static Retrofit retrofit = null;

private static OkHttpClient buildClient() {
    return new OkHttpClient
            .Builder()
            .addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
            .build();
}

public static Retrofit getClient() {
    if (retrofit == null) {
        retrofit = new Retrofit.Builder()
                .client(buildClient())
                .addConverterFactory(GsonConverterFactory.create())

                /**
                 *
                 *  base url here for api
                 */

                .baseUrl("https://xxx")       //retrieve data from MySQL 
                .build();
    }
    return retrofit;
}
}

MainActivity:

public class BarchartRetrofit extends AppCompatActivity {
    
    
        public ApiInterface apiInterface;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        apiInterface = ApiClient.getClient().create(ApiInterface.class);

        /**
         *  api call to get some data from server
         *
         */
        getData();

    }


    private void getData() {
        Call<PiChart> piChartCall = apiInterface.init();
        piChartCall.enqueue(new Callback<PiChart>() {
            @Override
            public void onResponse(Call<PiChart> call, Response<PiChart> response) {
                Log.d("CHART_RESPONSE", "" + response.body().getBarMonths().toString());
                setData(response.body());
            }

            @Override
            public void onFailure(Call<PiChart> call, Throwable t) {

            }
        });
    }

   

     private void setData(PiChart piChart) {
    
            ArrayList<BarDataSet> dataSets = null;
    
            ArrayList<BarEntry> completed = new ArrayList<>();
    
            for (int i = 0; i < piChart.getBarCompleted().size(); i++) {
                BarEntry value = new BarEntry(piChart.getBarCompleted().get(i), i); // Jan
                completed.add(value);
            }
    
            BarDataSet completeData = new BarDataSet(completed, "Completed Issue");
            completeData.setColor(Color.rgb(0, 155, 0));
    
            ArrayList<BarEntry> pending = new ArrayList<>();
            for (int i = 0; i < piChart.getBarCompleted().size(); i++) {
                BarEntry value = new BarEntry(piChart.getBarPending().get(i), i); // Jan
                pending.add(value);
            }
    
            BarDataSet pendingdata = new BarDataSet(pending, "Pending Issue");
            pendingdata.setColor(Color.rgb(253, 129, 0));
    
            ArrayList<BarEntry> rejected = new ArrayList<>();
            for (int i = 0; i < piChart.getBarCompleted().size(); i++) {
                BarEntry value = new BarEntry(piChart.getBarRejected().get(i), i); // Jan
                rejected.add(value);
            }
    
    
            BarDataSet rejectedData = new BarDataSet(rejected, "Rejected Issue");
            pendingdata.setColor(Color.rgb(255, 0, 0));
    
            dataSets = new ArrayList<>();
            dataSets.add(completeData);
            dataSets.add(pendingdata);
            dataSets.add(rejectedData);
            
            ArrayList<String> xAxis = new ArrayList<>();
            for (String months : piChart.getBarMonths()) {
                Log.d("CHART_RESPONSE", "month: " + months.toString());
                xAxis.add(months);
            }
    
            com.github.mikephil.charting.charts.BarChart chart = (com.github.mikephil.charting.charts.BarChart) findViewById(R.id.barchart);
    
            
            BarData data = new BarData(xAxis, dataSets);
            
            chart.setData(data);
            chart.setDescription("Bar chart");
            chart.invalidate();
    
        }
    }

Create JSON POJO:

public class Example {

@SerializedName("success")
@Expose
private boolean success;
@SerializedName("bar_months")
@Expose
private List<String> barMonths = null;
@SerializedName("bar_pending")
@Expose
private List<Integer> barPending = null;
@SerializedName("bar_rejected")
@Expose
private List<Integer> barRejected = null;
@SerializedName("bar_completed")
@Expose
private List<Integer> barCompleted = null;

public boolean isSuccess() {
return success;
}

public void setSuccess(boolean success) {
this.success = success;
}

public List<String> getBarMonths() {
return barMonths;
}

public void setBarMonths(List<String> barMonths) {
this.barMonths = barMonths;
}

public List<Integer> getBarPending() {
return barPending;
}

public void setBarPending(List<Integer> barPending) {
this.barPending = barPending;
}

public List<Integer> getBarRejected() {
return barRejected;
}

public void setBarRejected(List<Integer> barRejected) {
this.barRejected = barRejected;
}

public List<Integer> getBarCompleted() {
return barCompleted;
}

public void setBarCompleted(List<Integer> barCompleted) {
this.barCompleted = barCompleted;
}

}

The JSON is:

{
 
  "success": true,
  
  
  "bar_months":[
  "jan",
  "feb",
  "mar"
],
  
  "bar_pending":[
    100,
    200,
    300
  ],
  
   "bar_rejected":[
    140,
    220,
    340
  ],
  
  
   "bar_completed":[
    170,
    290,
    310
  ]
  
}

So basically, my data in bar_months,bar_pending, bar_rejected and bar_completed will changed instead of a static value, wondering what suggestions/ examples that I can try to retrain the dynamic data every hour. Thanks in advance for reading and helping!

Ichigo Kurosaki
  • 3,765
  • 8
  • 41
  • 56
swiftlearneer
  • 324
  • 4
  • 17
  • 1
    what is the issue you are facing exactly? – Rajan Kali Jan 27 '21 at 07:35
  • Thanks for the response Rajan! Just not too sure how to retrieve data from MySQL every hour as the database being updated. I can do when the data is static... – swiftlearneer Jan 27 '21 at 15:23
  • 1
    use [workmanager](https://developer.android.com/reference/androidx/work/WorkManager) to schedule a periodic work and if you wish to display old data as well then just store all the data retrieved using room – Sekiro Jan 27 '21 at 16:06
  • @Sekiro Just wondering if I am using room then do I still use retrofit and do I need to completely write the different code based on what I have? I am just a bit new for both workmanager and room.. – swiftlearneer Jan 27 '21 at 18:44
  • 1
    retrofit and room has nothing to do with each other, room is an abstract layer over SQLite databases used to persist the data, any kind of data, locally whereas retrofit is the library used to make HTTP request over a server from your device – Sekiro Jan 28 '21 at 04:53
  • 1
    so back to your question, `if I am using room then do I still use retrofit and do I need to completely write the different code`, so you just need to add few more lines of code, not an altogether different code – Sekiro Jan 28 '21 at 04:56
  • I am still trying to implement WorkManager first to periodically retrieve MySQL data first (as a text).. but have no luck... – swiftlearneer Jan 28 '21 at 05:04
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/227936/discussion-between-swiftlearneer-and-sekiro). – swiftlearneer Jan 28 '21 at 05:07

1 Answers1

1

In order to schedule your getData() task as recurring (even when your app is not in the foreground) you can use a workmanager. In this specific case, you'll need a PeriodicWorkRequestBuilder (link). The first step is defining the work you want to run periodically, extend the Worker class to do so:

class ExampleWorker(
    appContext: Context,
    workerParams: WorkerParameters
) :
    Worker(appContext, workerParams) {
    override fun doWork(): Result {
        getData()
        // Indicate whether the work finished successfully with the Result
        return Result.success()
    }

    private fun getData() {
        val piChartCall: Call<PiChart> = apiInterface.init()
        piChartCall.enqueue(object : Callback<PiChart?>() {
            fun onResponse(call: Call<PiChart?>?, response: Response<PiChart?>) {
                Log.d("CHART_RESPONSE", "" + response.body().getBarMonths().toString())
                setData(response.body())
            }

            fun onFailure(call: Call<PiChart?>?, t: Throwable?) {}
        })
    }
}

The second step will be to schedule this work in a recurring way, PeriodicWorkRequestBuilder function can help you:

private fun schedulePeriodicWork(context: Context) {
    val request =
        PeriodicWorkRequestBuilder<ExampleWorker>(1, TimeUnit.HOURS).build()
    WorkManager.getInstance(context).enqueueUniquePeriodicWork(
        "charSync",
        ExistingPeriodicWorkPolicy.REPLACE, request
    )
}

Probably it would be a wise choice to put the scheduling function call in the onCreate() method of your Application class

Nicola Gallazzi
  • 7,897
  • 6
  • 45
  • 64