Skip to content
donv edited this page Aug 7, 2011 · 3 revisions

Uwe and I have been discussing the need to revisit the startup, so I thought I'd post some thoughts to see if there are any strong opinions out there:

Goal:

  • Make the process of connecting ruby code with Android classes/ objects more natural.
  • Make the startup process more transparent.
  • Solutions that can be used from ruboto-core and Ruboto IRB. One of my personal goals is to keep open the option of connecting code to instances and not just classes...keeping open the ability to create new Activities without requiring a recompile of the app.

The current situation:

  • Born in a world with only Ruboto IRB, and moved over and expanded a little for ruboto-core.
  • The main goal is to attach some jruby code to an Android object so the script can handle callbacks from the Android side.
  • Sometimes the script code might exist before the Android object (e.g., launching a new Activity). Other times the Android object exist first (e.g., a ruboto-core generated Activity subclass that loads its related script).
  • Some Android object is going to have the pleasure of firing up the script engine. If the lucky object is an Activity, then we need to show a splash screen or loading dialog and finish fire off the necessary script later.
  • A RubotoActivity has two paths that it can take withing onCreate: 1) If there is a configuration bundle (set up by a script), then RubotoActivity sets up the necessary configuration and calls back into the engine; and 2) If there is no bundle (generally set up by a ruboto- core subclass of RubotoActivity), then it evaluate the specified script.
  • Both paths set up $activity to relate to the current Activity. In addition, path 1 can set up an additional global variable.This is still needed, but might be revisited because it was originally used for all calls back into the engine for this instance. This is no longer the case.
  • Activities have two ways of being created/configured from the script side: 1) start_ruboto_activity (the older way created for IRB...still works), and 2) handle_create (set up for ruboto-core).
  • Nether of these approaches is ideal because they involve evaluating the block in the context of the new instance. It is especially awkward to have other handle methods called inside of a handle_create block (but accurate in that handle_create is called from onCreate).
  • We have a mixture of code samples/examples/tutorials using both start_ruboto_activity and handle_create.

Ideas

A solution is easiest for generated subclasses of Ruboto classes (mainly RubotoActivity). They can load their own class code on the ruby side. All that is needed is an additional call to set up the callbacks. I can't think of an easy way to get the unique list of methods defined in the subclass (since all callbacks are already defined in the superclass), but if we can't determine it automatically, then it can just be specified in the code.

class RubotoActivity 
  def ruboto_callback_methods 
    (singleton_methods - ["on_create"]).select{|i| i =~ /^on_/} 
  end 
  def setup_ruboto_callbacks 
    ruboto_callback_methods.each do |i| 
      # TODO: Confirm existance of constant and method 
      const = i.sub(/^on_/, "CB_").upcase 
      setCallbackProc(self.class.const_get(const), method(i)) 
    end 
  end 
end 
class MyGeneratedActivity 
  def ruboto_callback_methods 
    ["on_create_options_menu"] 
  end 
  def on_create_options_menu(menu) 
    puts "menu pressed" 
  end 
end 

We might want to modify script loading for generated subclasses to perform a require on the script file instead of evaluating it each time. For script generated instances of RubotoActivity, we can use a similar method to the current start_ruboto_activity, but remove the handle_* code and directly define the on_* methods.

Using the RubotoActivity defined above

$activity.start_ruboto_activity("$ruboto_test_1") do 
  def on_create_options_menu(menu) 
    puts "menu pressed" 
  end 
end 

Again, all that is needed is a call to setup_ruboto_callbacks, but that should be easy to do from the Java instance. singleton_methods gives easy access to the locally defined methods in this case.

Clone this wiki locally