Apr 11 2009

Reinventing the wheel: the fluent interface design pattern

Category: UncategorizedAleksander Kmetec @ 4:56 pm

What’s the fluent interface design pattern? It’s a design pattern which became very visible in recent time, mainly due to jQuery, which was designed around it. In this pattern, class methods return the same object they were called on (they end with “return this;”), which makes it possible to chain them. It also makes it easily spottable in code, due to the distinctive outline created by chained methods.

Let’s have a quick look at what I’m talking about.

If Java Swing libraries supported this kind of coding, then the following block of java code, copied from a random blog post, could be rewritten from this repetitive sequence:


JFrame mainFrame = new JFrame("Hello World");
mainFrame.add(label, BorderLayout.CENTER);
mainFrame.addWindowListener(new MainFrameListener());
mainFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
mainFrame.pack();
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible(true);

…to this chain of methods:


new JFrame("Hello World")
    .add(label, BorderLayout.CENTER)
    .addWindowListener(new MainFrameListener())
    .setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE)
    .pack()
    .setLocationRelativeTo(null)
    .setVisible(true);

It’s amazing how much cleaner the code looks just by eliminating all those mainFrame references.

But wait… doesn’t this look familiar from somewhere? Doesn’t it remind you of a certain language feature you may have used years ago?

Yes, you’re right! It looks remarkably like the “with” control structure available in Delphi/Pascal and VisualBasic! If Java also supported it, the above example could be rewritten like this:


with (new JFrame("Hello World")) {
    add(label, BorderLayout.CENTER);
    addWindowListener(new MainFrameListener());
    setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
    pack();
    setLocationRelativeTo(null);
    setVisible(true);
}

It looks almost almost exactly the same as the one using the fluent interface, doesn’t it?

The main difference is that such a built-in construct works with any object you happen to throw at it, doesn’t require any additional effort from the library designer, and doesn’t require you to write repetitive code or wrapper classes if the library author failed to include the fluent interface pattern into the library in the first place. It also doesn’t interfere with the command-query separation principle and is perfectly compatible with step through debuggers.

But the fluent interface pattern does make it possible for us to have a special name for a simple concept, a Wikipedia entry for it, and dozens of blog posts about a solution to a problem that’s been solved, in a better way, decades ago.

Tags: , , ,


Feb 19 2009

Mosembro r5 now available for download

Category: Android, Mobile, Mobile web, Mosembro, UncategorizedAleksander Kmetec @ 8:59 pm

The first major Mosembro release after r2 is now available for download.

If you already have Mosembro installed, uninstall it first by running: adb uninstall com.lexandera.mosembro
The new version can then be installed by executing the following command: adb install mosembro-r2.apk

New features include:

  • It is now possible to install addidional actions which extend Mosembro’s functionality.
  • Addresses can be copied to clipboard.
  • Improved security and various bugfixes.

Screenshots of new features:

Mosmbro r5 screenshots

Mosembro r5: dialogs for installing and managing installed actions

Several simple actions can be installed from the bottom of the demo page which is loaded when Mosembro starts up. Go & try them out.


Jan 29 2009

Extracting HTML from a WebView

Category: Android, Semantic Web, Uncategorized, WebView examplesAleksander Kmetec @ 8:30 pm

Here’s another Android WebView tutorial for those of you who are looking for a way to get the source code of a page loaded in a WebView instance.

This example is a bit more complicated than previous ones, so let me explain it step by step:

  • First, a class called MyJavaScriptInterface is defined. It implements a single public method showHTML() which displays a dialog with the HTML it receives as a parameter.
  • Then, an instance of this class is registered as a JavaScript interface called HTMLOUT. The showHTML() method can now be accessed from JavaScript like this: window.HTMLOUT.showHTML(‘…’)
  • In order to call showHTML() when the page finishes loading, a WebViewClient instance which overrides onPageFinished() is added to the WebView. When the page finises loading, this method will inject a piece of JavaScript code into the page, using the method I described in an earlier post.
  • Finally, a web page is loaded.

final Context myApp = this;

/* An instance of this class will be registered as a JavaScript interface */
class MyJavaScriptInterface
{
    @SuppressWarnings("unused")
    public void showHTML(String html)
    {
        new AlertDialog.Builder(myApp)
            .setTitle("HTML")
            .setMessage(html)
            .setPositiveButton(android.R.string.ok, null)
        .setCancelable(false)
        .create()
        .show();
    }
}

final WebView browser = (WebView)findViewById(R.id.browser);
/* JavaScript must be enabled if you want it to work, obviously */
browser.getSettings().setJavaScriptEnabled(true);

/* Register a new JavaScript interface called HTMLOUT */
browser.addJavascriptInterface(new MyJavaScriptInterface(), "HTMLOUT");

/* WebViewClient must be set BEFORE calling loadUrl! */
browser.setWebViewClient(new WebViewClient() {
    @Override
    public void onPageFinished(WebView view, String url)
    {
        /* This call inject JavaScript into the page which just finished loading. */
        browser.loadUrl("javascript:window.HTMLOUT.showHTML('<head>'+document.getElementsByTagName('html')[0].innerHTML+'</head>');");
    }
});

/* load a web page */
browser.loadUrl("http://lexandera.com/files/jsexamples/gethtml.html");

WARNING
Unfortunately, this approach suffers from a major security hole: if your JavaScript can call showHTML(), then so can JavaScript from every other page that might get loaded into the WebView. Use with care.

Reblog this post [with Zemanta]

Tags: , , ,


Jan 01 2009

This is it. Post zero.

Category: UncategorizedAleksander Kmetec @ 6:00 am

I would like to say a few words to mark the occasion, but I can’t think of anything.


« Previous Page