Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Java Development

Reply
New Developer
VariousArtist
Posts: 22
Registered: ‎08-18-2010
Accepted Solution

How to update UI field with background thread

I am trying to update a screen (that extends MainScreen) with data that is changing based on a continuously running thread which calls a Web Service over http. 

 

I was trying to use the Observer/Observable pattern based off an example I found online, but this was in reference to a popup and I’m not exactly how to complete this for the screen I have.  Below is an edited down version of the code I am working with – I know I need to tie in the instanceOf the observable piece, but not sure how with this existing code that I have to maintain "as-is"...

 

public interface WebServiceStatusObserver
{
   public void update(String currentStatus);
}

public interface WebServiceStatusObservable
{
   public void setWebServiceStatusObserver(WebServiceStatusObserver observer);
}

public class MyScreen extends MainScreen, implements WebServiceStatusObserver
{
   LabelField latestWsStatus;        // label to be updated
   WebServiceThread wsThread = null; // background thread updates from web servece

   public MyScreen() 
   {
      latestWsStatus = new LabelField("");

      HorizontalFieldManager hfmTitle = new HorizontalFieldManager
         (Manager.USE_ALL_WIDTH | NO_HORIZONTAL_SCROLL) 
      {
         hfmTitle.add(latestWsStatus);
      }
   }

   public void update(String currentStatus)
   {   
      final String finalCurrentStatus = currentStatus;
      UiApplication.getUiApplication().invokeLater(new Runnable() 
      {
         public void run() 
         {
            latestWsStatus.setText(finalCurrentStatus);
         }
      });
    }

   class WebServiceThread extends Thread implements Runnable, WebServiceStatusObservable 
   {
      boolean quit = false;

      private WebServiceStatusObserver observer; 
      public void setWebServiceStatusObserver(WebServiceStatusObserver observer)
      {
         this.observer = observer;
      }        

      public void run() 
      {
         if ( observer != null ) { observer.update("Starting");  }

         while(true)
         {
            if ( observer != null ) { observer.update("Running”);  }
            // <some call to a web service over http goes here>
                  
            Thread.sleep(10000);    
        }
      }
   }
}

 

Please use plain text.
Developer
peter_strange
Posts: 19,526
Registered: ‎07-14-2008

Re: How to update UI field with background thread

The code that you have supplied looks OK as is and should work for your MainScreen.  Your observer's 'update()' method correctly does the update on the Event Thread by using invokeLater.

 

One reason why people will often put this in a separate PopupScreen is that they use this screen to 'block' UI interaction while the Screen is waiting for the network connection.  In this case, your MainScreen may have to have some special processing when the connection is in action to stop the user moving off the screen or to stop the network activity if the user does. 

Please use plain text.
Developer
Eugen
Posts: 467
Registered: ‎07-16-2009
My Carrier: Vodafone NL

Re: How to update UI field with background thread

[ Edited ]

All is looking fine. Just add these lines to Screen constructor:

wsThread = new WebServiceThread();
wsThread.setWebServiceStatusObserver(this);

 And in uiEungineAttached start the web thread:

wsThread.start();

 No needs to any instanceof operators.

 

Regards,

Eugen

Please use plain text.
New Developer
VariousArtist
Posts: 22
Registered: ‎08-18-2010

Re: How to update UI field with background thread

[ Edited ]

Thanks Eugen, but I am getting a compile error.  I realized that in my edited example I left an important part of the code which already has the weThread instantiated and starting so I have included just the screen constructor code below. 

 

You can see where I had added the one missing line (marked with **) along with the compile error message as a comment:

 

   public MyScreen() 
   {
      latestWsStatus = new LabelField("");
      wsThread = new WebServiceThread();
      wsThread.setWebServiceStatusObserver(this);

      HorizontalFieldManager hfmTitle = new HorizontalFieldManager
         (Manager.USE_ALL_WIDTH | NO_HORIZONTAL_SCROLL) 
      {
         hfmTitle.add(latestWsStatus);
      }

      myButton = new BitmapField(ScaledButtonOn, BitmapField.FOCUSABLE | ButtonField.CONSUME_CLICK) 
      {            
         boolean bFocus = false;
                        
         protected boolean buttonClick(int status, int time) 
         {
            UiApplication.getUiApplication().invokeLater
               (new Runnable() 
               {
                  public void run() 
                  {
                     UiApplication uiapp = UiApplication.getUiApplication();
       
                     wsThread = new WebServiceThread(myButton);
                     wsThread.start();
                     wsThread.setWebServiceStatusObserver(this);  // COMPILE ERROR**
                     //** 	this method in the type MyScreen.wsThread is not applicable 
                     //**  for the arguments (new Runnable(){})
                  }
               });
         }
      }

 

 

ERROR**

The method setWebServiceStatusObserver(WebServiceStatusObserver) in the type MyScreen.wsThread is not applicable for the arguments (new Runnable(){})

Please use plain text.
New Developer
VariousArtist
Posts: 22
Registered: ‎08-18-2010

Re: How to update UI field with background thread

[ Edited ]

Thanks peter_strange for your input -- indeed I based a lot of what I needed on your example, which was very helpful:

    http://supportforums.blackberry.com/t5/Java-Development/Sample-quot-Please-Wait-quot-Screen-part-3/t...

 

However, I need the updates from the thread to go to the main screen rather than a popup, for a few reasons:

  • I need to display more data (imagine a list of sport results and you get the idea that this won't work so well in a popup)
  • I'm really just using the popup to quickly announce an update and then automatically get out of the way;  i.e a 3-second popup display that demands more attention than the background statistics going on int he main screen (imagine announcing a goal has been scored in one of the games being displayed in the background)
  • there are other buttons on the main screen that need to be accessed while the background thread is running, and I don't know if it makes sense to move these to the popup

Are there any good examples of a main screen being updated by a background thread out there?  It seems like a basic scenario that would be behind most business scenarios of this nature.

 

Please use plain text.
Developer
peter_strange
Posts: 19,526
Registered: ‎07-14-2008

Re: How to update UI field with background thread

Replace this:

         protected boolean buttonClick(int status, int time)
         {
            UiApplication.getUiApplication().invokeLater
               (new Runnable()
               {
                  public void run()
                  {
                     UiApplication uiapp = UiApplication.getUiApplication();
      
                     wsThread = new WebServiceThread(myButton);
                     wsThread.start();
                     wsThread.setWebServiceStatusObserver(this);  // COMPILE ERROR**
                     //** this method in the type MyScreen.wsThread is not applicable
                     //**  for the arguments (new Runnable(){})
                  }
               });
         }

with this

 

         protected boolean buttonClick(int status, int time)
         {

                     wsThread = new WebServiceThread(myButton);
                     wsThread.setWebServiceStatusObserver(this);
                     wsThread.start();
         }

 

I suspect it will work.

Please use plain text.
New Developer
VariousArtist
Posts: 22
Registered: ‎08-18-2010

Re: How to update UI field with background thread

Thanks again peter_strange but I am now getting a different compile error -- probably because that buttonCllick code is encapsulated within a BitmapField button  (see "MyButton" in my code sample).

 

The error I am getting is complaining about the input parameter to my function, because it is seeing "this" as the BitmapField I guess.

 

I suspect we are getting close but I'm afraid I'm still not sure how to handle this situation.  If there's a way to make it work without having to tear up too much other "indirectly related" code that would be great...

Please use plain text.
Developer
peter_strange
Posts: 19,526
Registered: ‎07-14-2008

Re: How to update UI field with background thread

try replacing

wsThread.setWebServiceStatusObserver(this);

with

wsThread.setWebServiceStatusObserver(MyScreen.this);

 

Please use plain text.
New Developer
VariousArtist
Posts: 22
Registered: ‎08-18-2010

Re: How to update UI field with background thread

Excellent! Thanks for the amazingly quick response and working through this with me to get the solution.
Please use plain text.