• After 15+ years, we've made a big change: Android Forums is now Early Bird Club. Learn more here.

Apps Code design advice?

rektiphyr

Newbie
Mar 4, 2012
19
0
Hi all,

I'm encountering a bit of a design conundrum. I can think of two solutions for my problem, and I'm not sure which is better for my particular situation.

Essentially, the problem is how to propagate events from the controllers to the UI. I've got a class called Client which represents, you guessed it, a Client! The Client class contains references to ServerManager and CacheManager -- two classes which manage the server interaction and caching operations.

The problem is that the ServerManager may receive notifications from the Server asynchronously which require action on the UI. It seems to me the first potential solution is to have the UI add a listener to the ServerManager directly:

Code:
Client c = new Client();
c.getServerManager().addListener(new ServerManager.Listener(){
   public void onServerNotification(Notification n){
     handler.post(new Runnable(){
        // update UI
     });
   }
});

I personally don't like this at all... my instinct is that only the Client should be interacting with it's ServerManager. In order to make that the case I have to propogate the "onServerNotification" event from the ServerManager to the Client and THEN to the UI:

Code:
Client c = new Client();
c.addNotificationListener(new Client.ServerNotificationListener(){
   public void onServerNotification(Notification n){
      handler.post(new Runnable(){
        // update UI
      });
   }
});

This seems a lot cleaner to me, however, in order to do this, I need the ServerManager to tell its parent Client object to issue the notification it just received:

In ServerManager:
Code:
   // Called when we receive a notification
   public void onReceivedNotification(Notification n)
   {
     Client c = null;
     if( (c = _client.get()) == null )
       return;

     c.onReceivedNotification(n); // calls onServerNotification for each ServerNotificationListener added to the Client
   }

This part I don't like. Because this required that Client have a public method which loops through the list of listeners and issues the callback to each one. I don't think such a method should be public. That exposes behaviour to other parts of the application which have no business accessing it (random parts of the app should not be able to trick the Client into thinking it received a server notifiction).

SO that leaves me adding a protected Listener to the Client which listens to its own ServerManager for onReceivedNotification events. The UI then adds an ServerNotificationListener to the Client, and when the Client receives the event from it's ServerManager, it passes it along to the UI:

ServerManager:
Code:
// Called when we receive a notification
public void onReceivedNotification(Notification n)
{
   // Listener is a ServerManager.Listener
   if( this.listener != null )
      this.listener.onReceivedNotification(n);
}

Client:
Code:
public Client()
{
  serverManager = new ServerManager();
  serverManager.setListener(new ServerManager.Listener(){
    public void onReceivedNotification(Notification n)
    {
        for(ServerNotificationListener listener : this.serverNotificationListeners)
            listener.onServerNotification(n);
    }
  });
}

Finally, from the UI layer...

MainActivity:
Code:
public void onCreate(Bundle savedInstanceState)
{
   super.onCreate(savedInstanceState);
   this.client = new Client();
   this.client.addServerNotificationListener(new ServerNotificationListener(){
      public void onServerNotification(final Notification n)
      {
           handler.post(new Runnable(){
              public void run()
              {
                 // update UI with values from notification
              }
           });
      }
   });
}

So that's where I'm at now. I like the current implementation for its encapsulation. It seems clean to me. However, it also seems like it might be overly convoluted...

I'm sure this is a common problem, and I'd like to find the best solution possible -- if anyone out there has a better way, or can think of a good reason why this is TOO convoluted, I'd appreciate your comments.

Cheers!

PS. I typed all that code directly into the browser, so if there are any errors, or you can't tell what it's meant to do, please ask. The intention of the code is what matters here.
 

BEST TECH IN 2023

We've been tracking upcoming products and ranking the best tech since 2007. Thanks for trusting our opinion: we get rewarded through affiliate links that earn us a commission and we invite you to learn more about us.

Smartphones