3

My main Thread extends from Activity, it starts two asynchronous tasks that gather data from different UDP sources. One of this tasks should append the data to this graph drawing library. I am making updates on the UI from the onPostExecute section of AsynTask:

@Override
protected void onPostExecute(Integer result) {
    super.onPostExecute(result);
    edt2.setText(Integer.toString(result));
    // Graph Update
    if (graphActive) {
        exampleSeries1.appendData(ATList.get(ATList.size()-1), true);
    } else {
        //do nothing
    }
}

The data is passed to the graph and if I click with my finger on the display it is displayed correctly, but I want the software to update the graph automatically. The edt2 textfield is updated automatically.

I tried the following:

layout.postInvalidate(); //and invalidate

I have no idea how to make Android to update the GraphView.

This is the respective part of the XML:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/graph1"
    android:layout_width="match_parent"
    android:layout_height="305dp" >

</LinearLayout>

Thank you very much for your help!

lcnicolau
  • 3,252
  • 4
  • 36
  • 53
Hauke S.
  • 43
  • 5
  • the LinearLayout is where your draw the graph? – weakwire Sep 16 '12 at 12:42
  • consider making it a View or just add a dummy view to the LinearLayout to see if it works. ViewGroup with no drawable and no children tend not to invalidate. Please post your results – weakwire Sep 16 '12 at 15:16
  • The Graph is added into a linearlayout, by: layout = (LinearLayout) findViewById(R.id.graph1); layout.addView(graphView); Is that what you mean? – Hauke S. Sep 16 '12 at 16:03
  • so why you invalidate the layout and dont invalidate the graphView? – weakwire Sep 16 '12 at 16:54
  • was not successful, but I got it working with a Timer that updates removes and adds the graphview, so new data is written: ll.removeAllViews(); ll.addView(graphView); – Hauke S. Sep 16 '12 at 19:19
  • that implementation isn't good. try one last thing. set a background color at the graphview and then check again with graphview.invalidate – weakwire Sep 16 '12 at 19:23

3 Answers3

3

The answer by @Rishabh is not correct. Both onPostExecture and onProgressUpdate are called on the UI thread. The accepted solution is more kludgy than the original track you were on, that is to update in onPostExecute. Doing it there is absolutely the elegant way to do. You do NOT want to call runOnUiThread here.

As @weakwire said: invalidating the graph is the right way, not invalidating the layout. Anyways, the accepted answer is not the Android way to perform a task in the background and then update the UI with the results.

lcnicolau
  • 3,252
  • 4
  • 36
  • 53
vkinra
  • 943
  • 1
  • 9
  • 16
  • This is the solution. Although you shouldn't call the `GraphView#invalidate()` by yourself. Instead, you should call the `GraphView#onDataChanged(boolean, boolean)` and it will properly invalidate not only the `GraphView` but also the `GridLabelRenderer`. Take a look at this [answer](https://stackoverflow.com/a/53237088/4071001) for details. – lcnicolau Nov 10 '18 at 08:06
0

AsyncTask is not a Ui Thread use runOnUiThread(..) instead Asynctask.

1 rl-: parent view. 2 myView -: Child View

//Use This Method //

    runOnUiThread(new Runnable() {

        //@Override
        public void run() {
            // TODO Auto-generated method stub
            rl.addView(new myView(getApplicationContext()));
        }
    });
Rishabh Agrawal
  • 861
  • 2
  • 15
  • 25
  • But it should run in Background, not in the UI Thread or didn´t i get your point? – Hauke S. Sep 16 '12 at 12:36
  • your can only update data using AsyncTask not ui because asynctask is not a ui thread.so keep update data only in background & then pass in to ui thread using ruOnUiThread() for update your graph – Rishabh Agrawal Sep 16 '12 at 14:42
0

For changes to take effect, you need to call:

graphView.onDataChanged(false, false);

This will invalidate the GraphView and the GridLabelRenderer as @weakwire and @vkinra suggest, but this is the recommended way to go, as you can see in GridLabelRenderer#invalidate(boolean, boolean)'s javadoc:

/**
 * Clears the internal cache and forces to redraw the grid and labels.
 *
 * Normally you should always call {@link GraphView#onDataChanged(boolean, boolean)}
 * which will call this method.
 *
 * @param keepLabelsSize true if you don't want to recalculate the size of the labels. 
 *                       It is recommended to use "true" because this will improve 
 *                       performance and prevent a flickering.
 * @param keepViewport true if you don't want that the viewport will be recalculated.
 *                     It is recommended to use "true" for performance.
 */
public void invalidate(boolean keepLabelsSize, boolean keepViewport) { /*...*/ }

And these are the same parameters of GraphView#onDataChanged(boolean, boolean), so you should play with them to ensure the best performance. Also, you can take a look at this answer to see the GraphView#onDataChanged(boolean, boolean)'s javadoc.

lcnicolau
  • 3,252
  • 4
  • 36
  • 53