title: Android invalidate(Rect) invalidates entire region
body: <p>I don't understand why invalidate(Rect) is invalidating the entire region.
  The region is divided up into 5 sections and a line graph is being drawn in each one. Each section contains 100 points. As the data arrives for times tn to tn+100 I call invalidate(new Rect(left, top, right bottom)) where top is the top of the screen in height (but a lower numerical value than bottom). This invokes a call to the onDraw() method. The region from tn to tn+100 is drawn, but the previously drawn segment in region tn-100 to tn is erased. It continues that way forever. Each invalidate draws in only that region (since that is the only data I have) which IS correct, but all the previously drawn data is erased. So I get a marching segment!</p>
  
  <p>In other words, I get identical behavior if I call invalidate() or invalidate(Rect).</p>
  
  <p>I am assuming that the parameters of the Rect() are pixels and are getting the values based upon the height and width of the AlertDialog window in which this is being drawn.</p>
  
  <p>The hope is eventually to reduce the region of 'Rect()' so I can simulate real time drawing and only invalidate time step t to t+1 instead of a region.</p>
  
  <p>I must be doing something stupid.</p>
  
  <p>I hope that the fact it is being done in an AlertDialog is not the issue.</p>
  
  <p>This part is for trying to help 'android developer' help a noob like me get this right.
  First the sequence of events:<br>
  1. Data is received via Bluetooth in a callback<br>
  2. If it is the right type of data, a BroadcastReceiver in the main activity (UI thread) is  signaled and from there a routine is called that sets the parameters of a WaveFormView extends View class and then ShowDialog(id) is called which calls the onCreateDialog(id) callback in the main activity.<br>
  3. Then I call invalidate().<br>
  4. The dialog pops up and then the graph is drawn.<br>
  5. All subsequent calls to ShowDialog(id) bypass the onCreateDialog(id)</p>
  
  <p>That works but the entire region is always invalidated regardless of the parameters. There are also no user events here. From your example the best I could come up with is the following where I place invalidate in the onShow() instead of calling myself after the showDialog(id)</p>
  
  <pre><code>@Override
  protected Dialog onCreateDialog(int id)
  {
      Log.d(TAG, "Alert Dialog 'onCreateDialog' method has been called with id " + id);
      Builder bldr = new AlertDialog.Builder(this);
      AlertDialog alert = bldr.setView(waveForm).setNegativeButton("Dismiss " + id, 
              new DialogInterface.OnClickListener()
              {
                  public void onClick(DialogInterface dialog, int id)
                  {
                      dialog.cancel();
                  } 
              }).create();
      // I tried adding this and invalidating here worked only first pass
      alert.setOnShowListener(
                      new DialogInterface.OnShowListener()
                      {
                          @Override
                          public void onShow(DialogInterface dialog)
                          {
                              // call to invalidate
                              waveForm.drawArea();
                          }
                      });
  
      //alert.getWindow().setLayout(alert.getWindow().getAttributes().width, alert.getWindow().getAttributes().height / 2);
      alert.getWindow().setLayout(waveForm.getCurrentWidth(), waveForm.getCurrentHeight());
  
      return alert;
  }
  </code></pre>
  
  <p>However the onShow() does not get called.</p>
  
  <p>The method in the main activity that calls the showDialog is</p>
  
  <pre><code>private void displayRtsa(int[] rtsaReceived)
  {
      // rtsaReceived[0] has the agentsink hash code
      int agent = rtsaReceived[0];
      // rtsaReceived[1] has the index of the RtsaData object updated
      int index = rtsaReceived[1];
      TreeMap&lt;Integer, RtsaData[]&gt; agentRtsa = BluetoothPanService.getAgentRtsaMap();
      RtsaData[] rtsaDataValues = agentRtsa.get(agent);
  
      int dialogId = 0;
      synchronized(dialogIds)
      {
          int i = 0;
          if(dialogIds.containsKey(agent + index) == false)
          {
              for(i = 0; i &lt; dialogIds.size(); i++)
              {
                  if(dialogIds.containsValue(i) == false)
                  {
                      break;
                  }
              }
              dialogIds.put(agent + index, i);
          }
          dialogId = dialogIds.get(agent + index);
      }
      final int id = dialogId;
      Log.d(TAG, "Dialog id being shown = " + dialogId);
      waveForm.setPeriod(rtsaDataValues[index].getPeriod());
      waveForm.setMaxMin(rtsaDataValues[index].getMinValue(), rtsaDataValues[index].getMaxValue());
      waveForm.setColor(Color.argb(255, 255, 200, 0));
      waveForm.setData(rtsaDataValues[index].getData());
      waveForm.setTitle(rtsaDataValues[index].getType());
      showDialog(id);
      // invalidate
      // waveForm.drawArea(); (try to do in onCreateDialog callback)
  }
  </code></pre>
  
  <p>This is probably a completely wrong approach. Probably openGl is the only way.</p>
  
  <p>By the way, thanks for putting up with me!</p>