<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Out Of What Box? &#187; Software Development</title>
	<atom:link href="http://www.outofwhatbox.com/blog/category/sw-dev/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.outofwhatbox.com/blog</link>
	<description>Ruminations on software and other impossible things</description>
	<lastBuildDate>Thu, 08 Sep 2011 15:57:30 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Android: Closing those database objects</title>
		<link>http://www.outofwhatbox.com/blog/2010/12/android-closing-those-database-objects/</link>
		<comments>http://www.outofwhatbox.com/blog/2010/12/android-closing-those-database-objects/#comments</comments>
		<pubDate>Thu, 16 Dec 2010 23:20:10 +0000</pubDate>
		<dc:creator>Dan Breslau</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[DatabaseObjectNotClosedException]]></category>
		<category><![CDATA[onDestroy]]></category>
		<category><![CDATA[SQLiteOpenHelper]]></category>

		<guid isPermaLink="false">http://www.outofwhatbox.com/blog/?p=691</guid>
		<description><![CDATA[Android applications based on the Notepadv3 tutorial are prone to a DatabaseObjectNotClosedException when they're closed. Here's how to prevent them.]]></description>
			<content:encoded><![CDATA[<div style="font-size:1.5em"><em><strong>(Or, what the Notepad tutorial never told you.</strong></em>)</div>
<p>If you&#8217;ve used Android&#8217;s <a href="http://developer.android.com/resources/tutorials/notepad/index.html">Notepad</a> tutorial (Version 3) , or modeled your own Activity on <a href="http://developer.android.com/resources/tutorials/notepad/notepad-ex3.html">Notepadv3</a>, then you&#8217;ve probably seen log messages that look something like this:</p>
<pre class="brush: plain;">
android.database.sqlite.DatabaseObjectNotClosedException:
    Application did not close the cursor or database object that was opened here
at android.database.sqlite.SQLiteCompiledSql.&lt;init&gt;(SQLiteCompiledSql.java:62)
at android.database.sqlite.SQLiteProgram.&lt;init&gt;(SQLiteProgram.java:80)
at android.database.sqlite.SQLiteStatement.&lt;init&gt;(SQLiteStatement.java:36)
at android.database.sqlite.SQLiteDatabase.compileStatement(SQLiteDatabase.java:1145)
at android.database.sqlite.SQLiteDatabase.updateWithOnConflict(SQLiteDatabase.java:1671)
at android.database.sqlite.SQLiteDatabase.update(SQLiteDatabase.java:1622)
at com.android.demo.notepad3.NotesDbAdapter.updateNote(NotesDbAdapter.java:186)
at com.android.demo.notepad3.NoteEdit.saveState(NoteEdit.java:106)
at com.android.demo.notepad3.NoteEdit.onPause(NoteEdit.java:87)
at android.app.Activity.performPause(Activity.java:3842)
at android.app.Instrumentation.callActivityOnPause(Instrumentation.java:1190)
at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3335)
at android.app.ActivityThread.performPauseActivity(ActivityThread.java:3305)
at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:3288)
at android.app.ActivityThread.access$2500(ActivityThread.java:125)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2044)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4627)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
at dalvik.system.NativeStart.main(Native Method)
</pre>
<p>This is resolved easily enough by overriding the <a href="http://developer.android.com/reference/android/app/Activity.html#onDestroy%28%29"><code>onDestroy</code></a> method in each of the Activities in your application — or at least, each Activity that uses the database. In the Notepadv3 app, this means overriding <code>onDestroy</code> in both the Notepadv3 and NoteEdit classes. The same definition is suitable for both classes:</p>
<pre class="brush: java; title: onDestroy;">
    public void onDestroy() {
        super.onDestroy();

        // Replace mDbHelper as needed with your database connection, or
        // whatever wraps your database connection. (See below.)
        mDbHelper.close();
    }
</pre>
<p>In the Notepadv3 tutorial, the <code>mDbHelper</code> field is an instance of the class <code>NotesDbAdapter</code>, which wraps the database connection. <code>NotesDbAdapter</code> comes from google with the <code>close</code> method already defined, but there&#8217;s no code that calls it. With this change, we&#8217;re supplying the code that calls <code>close</code> at the right time. (<em>I think.</em>)</p>
<p>In general: If your activity opens a database by calling either <a href="http://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper.html#getReadableDatabase%28%29"><code>SQLiteOpenHelper.getReadableDatabase</code></a> or <a href="http://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper.html#getWritableDatabase%28%29"><code>SQLiteOpenHelper.getWritableDatabase</code></a>, then you should rely on <a href="http://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper.html#close%28%29"><code>SQLiteOpenHelper.close</code> </a>to close that database. Your activity&#8217;s <code>onDestroy</code> method must result in a call to the <code>close</code> method for any instances of <code>SQLiteOpenHelper</code>, or classes derived from it, that you&#8217;ve created. (In the code above, <code>mDbHelper.close</code> will have that effect.) <code>SQLiteOpenHelper.close</code> will then close any database handle that it created for you.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.outofwhatbox.com/blog/2010/12/android-closing-those-database-objects/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Android: Using DatabaseUtils.InsertHelper for faster insertions into SQLite database</title>
		<link>http://www.outofwhatbox.com/blog/2010/12/android-using-databaseutils-inserthelper-for-faster-insertions-into-sqlite-database/</link>
		<comments>http://www.outofwhatbox.com/blog/2010/12/android-using-databaseutils-inserthelper-for-faster-insertions-into-sqlite-database/#comments</comments>
		<pubDate>Wed, 15 Dec 2010 20:34:33 +0000</pubDate>
		<dc:creator>Dan Breslau</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[DatabaseUtils]]></category>
		<category><![CDATA[InsertHelper]]></category>
		<category><![CDATA[Optimization]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[SQLite]]></category>

		<guid isPermaLink="false">http://www.outofwhatbox.com/blog/?p=680</guid>
		<description><![CDATA[Using DatabaseUtils.InsertHelper, plus a couple other performance tweaks, yielded a nearly factor of ten performance improvement for bulk database insertions on AndroidOS.]]></description>
			<content:encoded><![CDATA[<p>AndroidOS includes the <a href="http://developer.android.com/reference/android/database/DatabaseUtils.InsertHelper.html"><code>DatabaseUtils.InsertHelper</code></a> class for speeding up insertions into an SQLite database. However, very little documentation or examples seem to be available to show how to use this class. I hope this post will help to make <code>InsertHelper</code> a little less mysterious than it apparently has been.</p>
<p>It&#8217;s often the case that bulk insertions are performed in the <a href="http://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper.html#onCreate(android.database.sqlite.SQLiteDatabase)"><code>onCreate</code></a> method of an <a href="http://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper.html"><code>SQLiteOpenHelper</code></a>, so I&#8217;ll use that context for this example. (This has implications on transaction management, which in turn affects performance, as described below.)</p>
<p>Suppose the <code>onCreate</code> method currently looks something like this:</p>
<pre class="brush: java; title: Old;">
private class DatabaseHelper extends SQLiteOpenHelper {
    @Override
    public void onCreate(SQLiteDatabase db) {
        ContentValues values = new ContentValues();
        while (moreRowsToInsert) {
            // ... create the data for this row (not shown) ...

            // Add the data for each column
            values.put(&quot;Greek&quot;, greekData);
            values.put(&quot;Ionic&quot;, ionicData);
            // ...
            values.put(&quot;Roman&quot;, romanData);

            // Insert the row into the database.
            db.insert(&quot;columnTable&quot;, null, values);
        }
    }
    //...
}
</pre>
<p>Using <code>DatabaseUtils.InsertHelper</code>, this would be re-written as:</p>
<pre class="brush: java; title: New;">
import android.database.DatabaseUtils.InsertHelper;
//...
private class DatabaseHelper extends SQLiteOpenHelper {
    @Override
    public void onCreate(SQLiteDatabase db) {
        // Create a single InsertHelper to handle this set of insertions.
        InsertHelper ih = new InsertHelper(db, &quot;columnTable&quot;);

        // Get the numeric indexes for each of the columns that we're updating
        final int greekColumn = ih.getColumnIndex(&quot;Greek&quot;);
        final int ionicColumn = ih.getColumnIndex(&quot;Ionic&quot;);
        //...
        final int romanColumn = ih.getColumnIndex(&quot;Roman&quot;);

        while (moreRowsToInsert) {
            // ... Create the data for this row (not shown) ...

            // Get the InsertHelper ready to insert a single row
            ih.prepareForInsert();

            // Add the data for each column
            ih.bind(greekColumn, greekData);
            ih.bind(ionicColumn, ionicData);
            //...
            ih.bind(romanColumn, romanData);

            // Insert the row into the database.
            ih.execute();
        }
    }
    //...
}
</pre>
<p>As this shows, using <code>InsertHelper</code> is barely more complicated than using <a href="http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#insert%28java.lang.String,%20java.lang.String,%20android.content.ContentValues%29"><code>SQLiteDatabase.insert</code></a>. The major differences are that you need to call     <code>ih.prepareForInsert()</code> before adding (&#8220;binding&#8221;) the column data; and you need to obtain each column&#8217;s numeric index, which we get by calling <code>ih.getColumnIndex()</code> prior to the loop.</p>
<p>After replacing <code>SQLiteDatabase.insert</code> with <code>DatabaseUtils.InsertHelper</code>, the database insertion speed went from the equivalent of about 95 rows per second to about 525 rows per second. (&#8220;Equivalent of&#8221;, because the app also spends cycles creating the data to insert. Here, the performance timings are measured using constant data, eliminating that overhead.)</p>
<div class="oowbbtw"><code>InsertHelper </code>isn&#8217;t really doing anything magical here. It&#8217;s essentially a wrapper around compiled statements, which you can create yourself using <a href="http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#compileStatement%28java.lang.String%29"><code>SQLiteDatabase.compileStatement</code></a>. Most people will probably find <code>InsertHelper</code> easier to use, though.</div>
<h3>Other ways to speed up insertions</h3>
<p>In addition to that gain, two more changes then brought the insertion speed to well over 900 rows per second. Whether these <s>tricks</s> techniques work for you will depend on your application.</p>
<h4>Don&#8217;t bind empty columns</h4>
<p>In my app, the data for at least 50% of the columns is empty. By skipping the call to <code>ih.bind()</code> when the column data is a <code>null</code> or empty string, I saw a roughly 30% performance boost.</p>
<h4>Temporarily disable database thread locking</h4>
<p>I&#8217;m loading the database during the <a href="http://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper.html#onCreate%28android.database.sqlite.SQLiteDatabase%29"><code>onCreate</code></a> method of my app&#8217;s <code>SQLiteOpenHelper</code>. During this time, it seems safe to assume that only one thread is accessing the database, so I use <a href="http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#setLockingEnabled%28boolean%29"><code>SQLiteDatabase.setLockingEnabled()</code></a> to temporarily (<em>let me emphasize that: <strong>temporarily</strong></em>) disable thread locks within the database API. This yielded about a 35% performance gain:</p>
<pre class="brush: java;">
    public void onCreate(SQLiteDatabase db) {
    //...
    try {
        // *Temporarily* (have I emphasized that enough?) disable
        // thread locking in the database. Be sure to re-enable locking
        // within a finally block.
        db.setLockingEnabled(false);
        // ... load the database ...
    }
    finally {
        db.setLockingEnabled(true);
    }
</pre>
<h3>Transactions and performance</h3>
<p>A <a href="http://notes.theorbis.net/2010/02/batch-insert-to-sqlite-on-android.html">number</a> <a href="http://sagistech.blogspot.com/2010/07/notes-on-android-sqlite-bukl-insert.html">of</a> <a href="http://stackoverflow.com/questions/3860008/bulk-insertion-on-android-device">people</a> have cited performance gains through use of explicit transactions in SQLite. However, <a href="http://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper.html"><code>SQLiteOpenHelper</code></a> creates a transaction before invoking its callback methods  (<code>onCreate</code>, <code>onUpgrade</code>, and <code>onOpen</code>), so explicit transaction control is unnecessary within those methods. (<code>SQLiteOpenHelper</code> will assume that the transaction was successful unless your method throws an exception.)</p>
<p>You <strong>would</strong> need to manage your own transactions if your insertion code is running outside of one of <code>SQLiteOpenHelper</code>&#8216;s callback methods. The main APIs for this are <a href="http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#beginTransaction()"><code>SQLiteDatabase.beginTransaction</code></a>, <a href="http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#setTransactionSuccessful()"><code>SQLiteDatabase.setTransactionSuccessful</code></a>, and <a href="http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#endTransaction()"><code>SQLiteDatabase.endTransaction</code></a>.</p>
<p>It is possible to nest transactions, but, not surprisingly, this doesn&#8217;t seem to help performance. In fact, I saw a very slight performance degradation when using nested transactions (approximately 1%, probably below the accuracy of the measurements.) I also tried periodically closing the current transaction — the first of these being the transaction that was opened by <code>SQLiteOpenHelper</code> — then opening a new one. This didn&#8217;t yield much improvement, if any.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.outofwhatbox.com/blog/2010/12/android-using-databaseutils-inserthelper-for-faster-insertions-into-sqlite-database/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>Android: Spinners, SimpleAdapter, and (maybe) ViewBinder</title>
		<link>http://www.outofwhatbox.com/blog/2010/12/android-spinners-simpleadapter-and-maybe-viewbinder/</link>
		<comments>http://www.outofwhatbox.com/blog/2010/12/android-spinners-simpleadapter-and-maybe-viewbinder/#comments</comments>
		<pubDate>Wed, 08 Dec 2010 16:45:48 +0000</pubDate>
		<dc:creator>Dan Breslau</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[SimpleAdapter]]></category>
		<category><![CDATA[Spinner]]></category>
		<category><![CDATA[ViewBinder]]></category>

		<guid isPermaLink="false">http://www.outofwhatbox.com/blog/?p=671</guid>
		<description><![CDATA[On older versions of AndroidOS, there's a bug that causes the combination of SimpleAdapter and Spinner to fail when displaying text data. There's also a workaround: Add a ViewBinder to the SimpleAdapter. This is simpler than it sounds.]]></description>
			<content:encoded><![CDATA[<p>The question came up on <a href="http://stackoverflow.com/questions/4383913">StackOverflow</a> yesterday: Can a Spinner be configured to use a SimpleAdapter (and if so, how?) The user who asked the question, <a href="http://stackoverflow.com/users/533635/chromium">Chromium</a>, ran into a couple of problems; the last of these was an IllegalStateException after clicking on the Spinner to make a selection.</p>
<p>A bit of searching turned up <a href="http://code.google.com/p/android/issues/detail?id=7251">this issue</a> about using a Spinner in combination with a SimpleAdapter to display a CheckedTextView; it seems that a ViewBinder must be set on the SimpleAdapter for that combination to work. Although it&#8217;s not the same problem, it still made me wonder if the SimpleAdapter / Spinner combination might need a ViewBinder for displaying TextView, too.</p>
<p>I wasn&#8217;t able to reproduce the IllegalStateException when I ran a sample program on AndroidOS 2.2, but I thought I&#8217;d try it on 1.5 in the emulator. Sure enough, I hit the same problem that Chromium reported. Apparently, whatever issue this is has been fixed by 2.2, and perhaps in earlier releases. (I haven&#8217;t tried other releases besides 2.2 and 1.5.)</p>
<p>And I also found that ViewBinder once again comes to the rescue, preventing the IllegalStateException from being thrown.</p>
<p>Like some other interfaces in Android (I&#8217;m looking at you, <a href="http://developer.android.com/reference/android/widget/SimpleCursorAdapter.CursorToStringConverter.html">CursorToStringConverter</a>. You too, <a href="http://developer.android.com/reference/android/widget/FilterQueryProvider.html">FilterQueryProvider</a>), <a href="http://developer.android.com/reference/android/widget/SimpleAdapter.ViewBinder.html">ViewBinder&#8217;</a>s bark is worse than its bite. In other words, the name may be a bit intimidating, but the implementation is a breeze.</p>
<div class="oowbbtw">Well, it <strong>would</strong> be a breeze, perhaps, if the documentation were clearer. The only method that you need to implement, <a href="http://developer.android.com/reference/android/widget/SimpleAdapter.ViewBinder.html#setViewValue(android.view.View,%20java.lang.Object,%20java.lang.String)">setViewValue</a>, receives three parameters: <code>View view, Object data, String textRepresentation</code>. But the documentation doesn&#8217;t tell us what these parameters really <em>mean</em> in a given context. I started by creating an empty setViewValue method, and set a breakpoint there. Inside the breakpoint, I verified that <code>view</code> is the TextView for displaying a single row in the Spinner; <code>data</code> is the String value in the Map for this row in the Spinner (&#8220;Red&#8221;, &#8220;Orange&#8221;, etc.); and textRepresentation is, well, the text representation of <code>data</code>, which in this case is that same String.</div>
<p>Here&#8217;s a sample program, adapted from <a href="http://stackoverflow.com/questions/4383913">Chromium&#8217;s example</a>, that adds a ViewBinder to a SimpleAdapter. This works on AndroidOS 1.5 and 2.2 (and, presumably, intermediate versions as well.)</p>
<pre class="brush: java; title: HelloSpinner;">
package org.oowb.HelloSpinner;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.SimpleAdapter;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemSelectedListener;

/**
 *  Displays a list of colors in a Spinner.
 */
public class HelloSpinner extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // The key to use for reading the color from the Map
        final String[] from = new String[] { &quot;color&quot; };

        // The type of View to use for displaying the color name.
        // android.R.id.text1 is a standard resource for displaying text.
        final int[] to = new int[] { android.R.id.text1  };

        // Create the List of strings for the spinner to display. Each string
        // is embedded within a Map, using &quot;color&quot; as the key.
        final List&lt;Map&lt;String, String&gt;&gt; data =
            new ArrayList&lt;Map&lt;String, String&gt;&gt;();
        final String[] colors = getResources().getStringArray(R.array.colors);

        for (int i = 0; i &lt; colors.length; i++) {
            data.add(addData(colors[i]));
        }

        final SimpleAdapter simpleAdapter =
            new SimpleAdapter(this, data,
                    android.R.layout.simple_spinner_item, from, to);
        simpleAdapter.setDropDownViewResource(
                android.R.layout.simple_spinner_dropdown_item);

        // Add a ViewBinder to display a color name in a TextView within the
        // Spinner. (This isn't needed in AndroidOS 2.2. In earlier releases,
        // when we're displaying text data within a Spinner, and no ViewBinder
        // is set in the SimpleAdapter, an IllegalStateException is thrown.)
        SimpleAdapter.ViewBinder viewBinder = new SimpleAdapter.ViewBinder() {

            public boolean setViewValue(View view, Object data,
                    String textRepresentation) {
                // We configured the SimpleAdapter to create TextViews (see
                // the 'to' array, above), so this cast should be safe:
                TextView textView = (TextView) view;
                textView.setText(textRepresentation);
                return true;
            }
        };
        simpleAdapter.setViewBinder(viewBinder);

        final Spinner spinner = (Spinner) findViewById(R.id.spinner);
        spinner.setAdapter(simpleAdapter);

        // Add an OnItemSelectedListener to display the selected Color
        spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView&lt;?&gt; parent, View view,
                    int position, long id) {
                // Get the color name out of the Map
                final Map&lt;String, String&gt; data =
                    (Map&lt;String, String&gt;) parent.getItemAtPosition(position);
                final String text = &quot;Selected Color:-  &quot; + data.get(&quot;color&quot;);

                Toast.makeText(parent.getContext(), text,
                        Toast.LENGTH_LONG).show();
            }

            @Override
            public void onNothingSelected(AdapterView&lt;?&gt; arg0) {
                // Do nothing
            }
        });
    }

    /**
     * Convert the String that's passed in into a Map, with
     * &quot;color&quot; as the key, and the String as the value.
     * @param    colorName  The color to be inserted into a new Map
     * @return   the new Map
     */
    private Map&lt;String, String&gt; addData(String colorName) {
        Map&lt;String, String&gt; map = new HashMap&lt;String, String&gt;();
        map.put(&quot;color&quot;, colorName);
        return map;
    }
}</pre>
<p>To complete the example, here are the layout (<code>main.xml</code>) and values files (<code>arrays.xml</code> and <code>strings.xml</code>):</p>
<pre class="brush: xml; title: main;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;LinearLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    android:orientation=&quot;vertical&quot;
    android:padding=&quot;10dip&quot;
    android:layout_width=&quot;fill_parent&quot;
    android:layout_height=&quot;wrap_content&quot;&gt;

    &lt;Spinner
        android:id=&quot;@+id/spinner&quot;
        android:layout_width=&quot;fill_parent&quot;
        android:layout_height=&quot;wrap_content&quot;
        android:drawSelectorOnTop=&quot;true&quot;
        android:prompt=&quot;@string/prompt&quot;
    /&gt;
&lt;/LinearLayout&gt;
</pre>
<pre class="brush: xml; title: arrays;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;resources&gt;
    &lt;string-array name=&quot;colors&quot;&gt;
        &lt;item&gt;Red&lt;/item&gt;
        &lt;item&gt;Orange&lt;/item&gt;
        &lt;item&gt;Yellow&lt;/item&gt;
        &lt;item&gt;Green&lt;/item&gt;
        &lt;item&gt;Blue&lt;/item&gt;
        &lt;item&gt;Purple&lt;/item&gt;
        &lt;item&gt;Violet&lt;/item&gt;
        &lt;item&gt;Octarine&lt;/item&gt;
    &lt;/string-array&gt;
&lt;/resources&gt;
</pre>
<pre class="brush: xml; title: strings;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
&lt;resources&gt;
    &lt;string name=&quot;app_name&quot;&gt;Color Chooser&lt;/string&gt;
    &lt;string name=&quot;prompt&quot;&gt;Choose a color:&lt;/string&gt;
&lt;/resources&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.outofwhatbox.com/blog/2010/12/android-spinners-simpleadapter-and-maybe-viewbinder/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Android: Simpler AutoCompleteTextView with SimpleCursorAdapter</title>
		<link>http://www.outofwhatbox.com/blog/2010/11/android-simpler-autocompletetextview-with-simplecursoradapter/</link>
		<comments>http://www.outofwhatbox.com/blog/2010/11/android-simpler-autocompletetextview-with-simplecursoradapter/#comments</comments>
		<pubDate>Mon, 15 Nov 2010 23:33:57 +0000</pubDate>
		<dc:creator>Dan Breslau</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[AutoCompleteTextView]]></category>
		<category><![CDATA[CursorAdapter]]></category>
		<category><![CDATA[SimpleCursorAdapter]]></category>

		<guid isPermaLink="false">http://www.outofwhatbox.com/blog/?p=663</guid>
		<description><![CDATA[AutoCompleteTextView doesn't require subclassing the CursorAdapter, after all. Where I'd thought it would be necessary to override certain methods, I've found that handler methods provided by SimpleCursorAdapter allow the same functionality without subclassing.]]></description>
			<content:encoded><![CDATA[<p>Sometimes it seems like nothing brings enlightenment as swiftly as publishing the results of one&#8217;s own confusion.</p>
<p>Earlier today, I published a <a href="http://www.outofwhatbox.com/blog/2010/11/android-autocompletetextview-sqlite-and-dependent-fields/">lengthy examination</a> of the work needed to supply an <a href="http://developer.android.com/reference/android/widget/AutoCompleteTextView.html">AutoCompleteTextView</a> with data using a <a href="http://developer.android.com/reference/android/widget/CursorAdapter.html">CursorAdapter</a>. My intentions were pure, but my code was not. Where I&#8217;d seen a need for subclassing, it was because I hadn&#8217;t caught on to some of the handler methods provided by the <a href="http://developer.android.com/reference/android/widget/SimpleCursorAdapter.html"><code>SimpleCursorAdapter</code></a> class.</p>
<p>Specifically, if we&#8217;re using a SimpleCursorAdapter, then:
<ul>
<li>We don&#8217;t need to override the <code><a href="http://developer.android.com/reference/android/widget/CursorAdapter.html#convertToString(android.database.Cursor)">convertToString</a></code> method, if instead we call <a href="http://developer.android.com/reference/android/widget/SimpleCursorAdapter.html#setCursorToStringConverter%28android.widget.SimpleCursorAdapter.CursorToStringConverter%29"><code>adapter.setCursorToStringConverter</code></a>.</li>
<li>And there&#8217;s no need to override <code>runQueryOnBackgroundThread</code>, if instead we call <a href="http://developer.android.com/reference/android/widget/CursorAdapter.html#setFilterQueryProvider%28android.widget.FilterQueryProvider%29"><code>adapter.setFilterQueryProvider</code></a>.</li>
</ul>
<p>This allows a significant refactoring of the <code>SelectState</code> class. Instead of the subclassed Adapter class, I&#8217;m now using anonymous inner classes to provide the cursor-to-name conversion and the filter query. The inner classes use essentially the same code as the methods that they&#8217;ve replaced.</p>
<p>The re-written <code>SelectState</code> follows. The full example can be <a href="http://static.outofwhatbox.com/AndroidAutoText/AutoCompleteInnerClasses.zip">downloaded as a ZIP file</a>.</p>
<p>(See the <a href="http://www.outofwhatbox.com/blog/2010/11/android-autocompletetextview-sqlite-and-dependent-fields/">earlier post</a> for a description of the sample application&#8217;s functionality.)</p>
<pre class="brush: java;">
package org.oowb.AutoCompleteExample;

import android.app.Activity;
import android.database.Cursor;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.FilterQueryProvider;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.SimpleCursorAdapter.CursorToStringConverter;

/**
 * A simple Android Activity to demonstrate:
 *
 * 1) How to use an AutoCompleteTextView with a SimpleCursorAdapter
 *
 * 2) How to access the cursor row for the user's choice, to obtain additional
 * data from that row when an item is selected.
 *
 * @author Dan Breslau
 *
 */
public class SelectState extends Activity {

    final static int[] to = new int[] { android.R.id.text1 };
    final static String[] from = new String[] { &quot;state&quot; };

    private TextView mStateCapitalView;
    private AutoCompleteTextView mStateNameView;
    private AutoCompleteDbAdapter mDbHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mDbHelper = new AutoCompleteDbAdapter(this);
        setContentView(R.layout.selectstate);
        Button confirmButton = (Button) findViewById(R.id.confirm);
        confirmButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
                setResult(RESULT_OK);
                finish();
            }
        });

        mStateCapitalView = (TextView) findViewById(R.id.state_capital);
        mStateNameView = (AutoCompleteTextView) findViewById(R.id.state_name);

        // Create a SimpleCursorAdapter for the State Name field.
        SimpleCursorAdapter adapter =
            new SimpleCursorAdapter(this,
                    android.R.layout.simple_dropdown_item_1line, null,
                    from, to);
        mStateNameView.setAdapter(adapter);

        // Set an OnItemClickListener, to update dependent fields when
        // a choice is made in the AutoCompleteTextView.
        mStateNameView.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView&lt;?&gt; listView, View view,
                        int position, long id) {
                // Get the cursor, positioned to the corresponding row in the
                // result set
                Cursor cursor = (Cursor) listView.getItemAtPosition(position);

                // Get the state's capital from this row in the database.
                String capital =
                    cursor.getString(cursor.getColumnIndexOrThrow(&quot;capital&quot;));

                // Update the parent class's TextView
                mStateCapitalView.setText(capital);
            }
        });

        // Set the CursorToStringConverter, to provide the labels for the
        // choices to be displayed in the AutoCompleteTextView.
        adapter.setCursorToStringConverter(new CursorToStringConverter() {
            public String convertToString(android.database.Cursor cursor) {
                // Get the label for this row out of the &quot;state&quot; column
                final int columnIndex = cursor.getColumnIndexOrThrow(&quot;state&quot;);
                final String str = cursor.getString(columnIndex);
                return str;
            }
        });

        // Set the FilterQueryProvider, to run queries for choices
        // that match the specified input.
        adapter.setFilterQueryProvider(new FilterQueryProvider() {
            public Cursor runQuery(CharSequence constraint) {
                // Search for states whose names begin with the specified letters.
                Cursor cursor = mDbHelper.getMatchingStates(
                        (constraint != null ? constraint.toString() : null));
                return cursor;
            }
        });
    }
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.outofwhatbox.com/blog/2010/11/android-simpler-autocompletetextview-with-simplecursoradapter/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Android: AutoCompleteTextView, SQLite, and Dependent Fields</title>
		<link>http://www.outofwhatbox.com/blog/2010/11/android-autocompletetextview-sqlite-and-dependent-fields/</link>
		<comments>http://www.outofwhatbox.com/blog/2010/11/android-autocompletetextview-sqlite-and-dependent-fields/#comments</comments>
		<pubDate>Mon, 15 Nov 2010 13:55:12 +0000</pubDate>
		<dc:creator>Dan Breslau</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[AutoCompleteTextView]]></category>
		<category><![CDATA[CursorAdapter]]></category>
		<category><![CDATA[SimpleCursorAdapter]]></category>

		<guid isPermaLink="false">http://www.outofwhatbox.com/blog/?p=659</guid>
		<description><![CDATA[There isn’t a wealth of documentation on the Web describing AutoCompleteTextView, especially for using it with a CursorAdapter. Here's a summary of my own experience implementing with this combination of classes.]]></description>
			<content:encoded><![CDATA[<div class="oowbnotice">Update: Subclassing from SimpleCursorAdapter isn&#8217;t necessary after all. Please see <a href="http://www.outofwhatbox.com/blog/2010/11/android-simpler-autocompletetextview-with-simplecursoradapter/">my follow-up post</a> for a simpler way of using AutoCompleteTextView together with database queries.</div>
<p>I recently integrated an <code><a href="http://developer.android.com/reference/android/widget/AutoCompleteTextView.html">AutoCompleteTextView</a></code> into a prototype <a href="http://developer.android.com/index.html">Android</a> application that I&#8217;m developing. There isn&#8217;t exactly a wealth of documentation on the Web describing <code>AutoCompleteTextView</code>, and what I&#8217;ve found didn&#8217;t match the scenario I had in mind. Specifically:</p>
<ul>
<li>The choices came from a database, so I needed to use a <code>CursorAdapter</code>; and</li>
<li>The <code>AutoCompleteTextView</code> had some dependent fields; changes to the value in the <code>AutoCompleteTextView</code> needed to be reflected in those dependent fields.
</li>
</ul>
<p>For example, let&#8217;s use a <code>AutoCompleteTextView</code> for choosing states. When the user chooses a state, I want to update a <code>TextView</code> to show the capital of the chosen state. </p>
<div class="oowbcaption">
<div class="oowb2col">
<img class="oowbleft2" alt="AutoCompleteTextView, with no selection" title="AutoCompleteTextView, with no selection" src="http://img.outofwhatbox.com/AndroidAutoText/BeforeSelection2.png"/><img class="oowbright2" alt="AutoCompleteTextView, selecting Massachusetts" title="AutoCompleteTextView, selecting Massachusetts" src="http://img.outofwhatbox.com/AndroidAutoText/ListAndAutosuggest6.png"/></div>
<p>First the form appears with no value in the State Capital field (left); then a state is chosen from the list (right.)</p></div>
<div class="oowbcaption"><img class="oowbcenter" alt="AutoCompleteTextView, updated with capital of Massachusetts." title="AutoCompleteTextView, updated with capital of Massachusetts." src="http://img.outofwhatbox.com/AndroidAutoText/AfterSelection2.png"/>
<div>After a state has been chosen, its capital is also displayed.</div>
</div>
<h3>Adapting SQLite to <code>AutoCompleteTextView</code></h3>
<p>The <a href="http://developer.android.com/reference/android/widget/AutoCompleteTextView.html">documentation</a> for <code>AutoCompleteTextView</code> says that it obtains suggestions from a <a href="http://developer.android.com/reference/android/widget/BaseAdapter.html">data adapter</a>. This should be familiar territory for anyone who&#8217;s used <code><a href="http://developer.android.com/reference/android/widget/ListView.html">ListView</a></code>, which also obtains its list items from a data adapter. Not surprisingly, <code>AutoCompleteTextView</code> uses a <code>ListView</code> internally.</p>
<p>However, <code>ListView</code> and <code>AutoCompleteTextView</code> require different interactions with their adapters. A standard <code>ListView</code> will typically need to fetch the list of items once, and only once. On the other hand, <code>AutoCompleteTextView</code> issues a query for matching choices whenever the user enters new text into the field. (In fact, the <code>AutoCompleteTextView</code> won&#8217;t issue a query <em>until</em> the user has typed some text. Hence the <code>CursorAdapter</code>&#8216;s constructor can take <code>null</code> for the Cursor parameter.)</p>
<p><code><a href="http://developer.android.com/reference/android/widget/SimpleCursorAdapter.html">SimpleCursorAdapter</a></code> wasn&#8217;t designed for this kind of usage pattern; in particular, it doesn&#8217;t know how you want to query for matching choices. So, you must derive from <code>SimpleCursorAdapter</code>, or from its base class, <code><a href="http://developer.android.com/reference/android/widget/CursorAdapter.html">CursorAdapter</a></code>. Your subclass must supply two methods that are essentially stubbed out in <code>CursorAdapter</code>: </p>
<ul>
<li><code><a href="http://developer.android.com/reference/android/widget/CursorAdapter.html#convertToString(android.database.Cursor)">convertToString</a></code>, which supplies the String value that is entered into the <code>AutoCompleteTextView</code> when a choice is made; and</li>
<li><code><a href="http://developer.android.com/reference/android/widget/CursorAdapter.html#runQueryOnBackgroundThread(java.lang.CharSequence)">runQueryOnBackgroundThread</a></code>. In this method, you invoke a query for choices that match the text entered by the user, and return a Cursor that provides the results.</li>
</ul>
<p>Let&#8217;s take a closer look at implementing the derived <code>CursorAdapter</code> class.</p>
<h3><a name="convertToString"></a><code>public CharSequence convertToString(Cursor cursor)</code></h3>
<p>This method receives the Cursor <em>positioned to a specific row</em>, and returns a String label or representation <em>for that row</em>.</p>
<div class="oowbbtw">Incidentally, if you derive from <code>SimpleCursorAdapter</code> without overriding <code>convertToString</code>, the choices shown in the drop-down will look fine. However, when an item in the list is chosen, the string entered in the <code>AutoCompleteTextView</code> field will be gibberish like &#8220;<code><em>android.database.sqlite.SQLiteCursor@43e8b260</em></code>&#8220;.</p>
<p>(This shows that <code>SimpleCursorAdapter</code> bypasses <code>convertToString</code> when building the choice list for an <code>AutoCompleteTextView</code>. Instead, it uses the <a href="#SimpleCursorAdapter"><code>from</code> and <code>to</code> arguments in its constructor</a> to pull the label text directly from the database. It also demonstrates that <code>SimpleCursorAdapter</code> does rely on <code>convertToString</code> when it comes time to update the field. This inconsistency seems like a bug in <code>SimpleCursorAdapter</code>.)</p>
<p>If you derive directly from <code>CursorAdapter</code> without implementing <code>convertToString</code>, then the behavior is consistent: you get the gibberish in the list <em>and</em> in the field value.</p>
<p>Perhaps <code>convertToString</code> should have been declared <code>abstract</code>, since the base class implementation doesn&#8217;t seem to be very helpful.</div>
<h3><a name="runQueryOnBackgroundThread"></a><code>public Cursor runQueryOnBackgroundThread(CharSequence constraint)</code></h3>
<p>Just to clarify, &#8220;On Background Thread&#8221; means that this method <em>is called in</em> a background thread — it does <em>not</em> mean that you have to spawn that thread within this method.</p>
<p>This method runs a query to get choices that match the input. It&#8217;s up to the application to determine what constitutes a match. (In this example, I&#8217;m searching for states whose names begin with the given letters.)</p>
<p>The <code>constraint</code> parameter is the input that the user has typed in. It may be <code>null</code> if the user has typed, and then erased, input text. In this case, all results should be returned.</p>
<div class="oowbbtw">Note that you must not call <code>changeCursor</code> within this method, because <code>changeCursor</code> is not thread-safe. The UI will invoke <code>changeCursor</code> from the main thread after this method returns the new Cursor.</div>
<h3>But wait, there&#8217;s more!</h3>
<p>It might seem&#8230; well, simpler, to derive the new Adapter class from <code>SimpleCursorAdapter</code>. However, deriving from <code>CursorAdapter</code> requires only two additional methods to be implemented, <code><a href="http://developer.android.com/reference/android/widget/CursorAdapter.html#newView(android.content.Context, android.database.Cursor, android.view.ViewGroup)">newView</a></code> and <code><a href="http://developer.android.com/reference/android/widget/CursorAdapter.html#bindView(android.view.View, android.content.Context, android.database.Cursor)">bindView</a></code>, both of which are straightforward. Hence for this example, I&#8217;m using <code>CursorAdapter</code> as the base class. Later, I&#8217;ll <a href="#SimpleCursorAdapter">describe the changes needed</a> to use <code>SimpleCursorAdapter</code> as the base.</p>
<h4><a name="newView"></a><code>public View newView(Context context, Cursor cursor, ViewGroup parent)</code></h4>
<p><code>newView</code> returns a newly constructed View suitable for displaying a single item in the choice list. The usual method for doing this is to use the Inflater, which is given the resource ID of a layout that describes the new View. It&#8217;s not necessary to create your own layout file; Android provides a standard layout that&#8217;s appropriate for this purpose, identified by  <code>android.R.layout.simple_dropdown_item_1line</code>.</p>
<div class="oowbbtw">Note: Many examples of <code>newView</code> on the web call <code>setText</code> on the view before returning. This unnecessarily duplicates the code in <code>bindView</code>. Nor is it necessary to invoke <code>bindView</code> explicitly: after we return the new view, <code>bindView</code> will be invoked to display the value.</div>
<h4><a name="bindView"></a><code>public void bindView(View view, Context context, Cursor cursor)</code></h4>
<p>This is called to display the label for the current row. If <code>newView</code> uses <code>android.R.layout.simple_dropdown_item_1line</code> for layout, then <code>bindView</code> will be called with a <code>TextView</code> as the <code>View</code> argument.</p>
<h3>Updating dependent fields</h3>
<p>To update dependent fields, start by creating a class that implements <code>OnItemClickListener</code>. (Here, it&#8217;s the Adapter class; it could also be your Activity, or some other class.) This interface defines a callback that&#8217;s invoked when the user makes a choice. The <code>setOnItemClickListener</code> method in <code>AutoCompleteTextView</code> associates the listener with the field.</p>
<p>The callback method, <code>onItemClick</code>, receives a <code>position</code> parameter that identifies the row number within the result set, starting from 0. For example, if the third state, &#8220;Arizona&#8221;, is chosen, the value of<code> position</code> will be 2. There&#8217;s also an <code>AdapterView&lt;?></code> parameter, whose purpose is a bit obscure. This is the <code>ListView</code> belonging to the <code>AutoCompleteTextView</code>. (This may be the only situation in which that <code>ListView</code> is directly exposed to the caller.)</p>
<p>We can then get the cursor from the <code>AdapterView&lt;?></code> parameter, and position it to the correct row, by calling <code>getItemAtPosition</code>. Note that <code>getItemAtPosition</code> returns an <code>Object</code>, so a cast is necessary. (It doesn&#8217;t seem to be documented anywhere that <code>listView.getItemAtPosition</code> will return a Cursor in this case.)</p>
<p>In the full example, this logic is seen in the line:</p>
<pre class="brush: java;">Cursor cursor = (Cursor) listView.getItemAtPosition(position)</pre>
<p>The result would probably be the same if we replaced the above line with:</p>
<pre class="brush: java;">
            Cursor cursor = getCursor();
            cursor.moveToPosition(position);
</pre>
<p>I went with the first approach because: 1) It&#8217;s (arguably) more in keeping with the Adapter&#8217;s contract. (There doesn&#8217;t seem to be any <em>guarantee</em> that <code>changeCursor</code> will be called by the main thread; without that call, <code>getCursor()</code> certainly won&#8217;t work.) And 2) it&#8217;s simpler, if by &#8220;simpler&#8221; we mean one less line of code.</p>
<h3>The code</h3>
<p>Now let&#8217;s have a look at the code. Here&#8217;s the Activity class, <code>SelectState</code>, with its nested Adapter class, <code>ItemAutoTextAdapter</code>. (The other class needed for this example, <code>AutoCompleteDbAdapter</code>, is available <a href="#AutoCompleteDbAdapter">below</a>.)</p>
<div class="oowbbtw">ZIP files are available for the full example, using either <a href="http://static.outofwhatbox.com/AndroidAutoText/AutoCompleteExample.zip">CursorAdapter </a>and <a href="http://static.outofwhatbox.com/AndroidAutoText/AutoCompleteSimpleCursor.zip">SimpleCursorAdapter</a> as the base classes.</div>
<pre class="brush: java; title: SelectState;">
package org.oowb.AutoCompleteExample;

import android.app.Activity;
import android.content.Context;
import android.database.Cursor;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.CursorAdapter;
import android.widget.TextView;

/**
 * A simple Android Activity to demonstrate:
 *
 * 1) How to use an AutoCompleteTextView with a CursorAdapter
 *
 * 2) How to access the cursor row for the user's choice, to obtain
 *    additional data from that row when an item is selected.
 *
 * @author Dan Breslau
 *
 */
public class SelectState extends Activity {
    /**
     * Specializes CursorAdapter to supply choices to a AutoCompleteTextView.
     * Also implements OnItemClickListener to be notified when a choice is made,
     * and uses the choice to update other fields on the Activity form.
     */
    class ItemAutoTextAdapter extends CursorAdapter
            implements android.widget.AdapterView.OnItemClickListener {

        private AutoCompleteDbAdapter mDbHelper;

        /**
         * Constructor. Note that no cursor is needed when we create the
         * adapter. Instead, cursors are created on demand when completions are
         * needed for the field. (see
         * {@link ItemAutoTextAdapter#runQueryOnBackgroundThread(CharSequence)}.)
         *
         * @param dbHelper
         *            The AutoCompleteDbAdapter in use by the outer class
         *            object.
         */
        public ItemAutoTextAdapter(AutoCompleteDbAdapter dbHelper) {
            // Call the CursorAdapter constructor with a null Cursor.
            super(SelectState.this, null);
            mDbHelper = dbHelper;
        }

        /**
         * Invoked by the AutoCompleteTextView field to get completions for the
         * current input.
         *
         * NOTE: If this method either throws an exception or returns null, the
         * Filter class that invokes it will log an error with the traceback,
         * but otherwise ignore the problem. No choice list will be displayed.
         * Watch those error logs!
         *
         * @param constraint
         *            The input entered thus far. The resulting query will
         *            search for states whose name begins with this string.
         * @return A Cursor that is positioned to the first row (if one exists)
         *         and managed by the activity.
         */
        @Override
        public Cursor runQueryOnBackgroundThread(CharSequence constraint) {
            if (getFilterQueryProvider() != null) {
                return getFilterQueryProvider().runQuery(constraint);
            }

            Cursor cursor = mDbHelper.getMatchingStates(
                    (constraint != null ? constraint.toString() : null));

            return cursor;
        }

        /**
         * Called by the AutoCompleteTextView field to get the text that will be
         * entered in the field after a choice has been made.
         *
         * @param Cursor
         *            The cursor, positioned to a particular row in the list.
         * @return A String representing the row's text value. (Note that this
         *         specializes the base class return value for this method,
         *         which is {@link CharSequence}.)
         */
        @Override
        public String convertToString(Cursor cursor) {
            final int columnIndex = cursor.getColumnIndexOrThrow(&quot;state&quot;);
            final String str = cursor.getString(columnIndex);
            return str;
        }

        /**
         * Called by the ListView for the AutoCompleteTextView field to display
         * the text for a particular choice in the list.
         *
         * @param view
         *            The TextView used by the ListView to display a particular
         *            choice.
         * @param context
         *            The context (Activity) to which this form belongs;
         *            equivalent to {@code SelectState.this}.
         * @param cursor
         *            The cursor for the list of choices, positioned to a
         *            particular row.
         */
        @Override
        public void bindView(View view, Context context, Cursor cursor) {
            final String text = convertToString(cursor);
            ((TextView) view).setText(text);
        }

        /**
         * Called by the AutoCompleteTextView field to display the text for a
         * particular choice in the list.
         *
         * @param context
         *            The context (Activity) to which this form belongs;
         *            equivalent to {@code SelectState.this}.
         * @param cursor
         *            The cursor for the list of choices, positioned to a
         *            particular row.
         * @param parent
         *            The ListView that contains the list of choices.
         *
         * @return A new View (really, a TextView) to hold a particular choice.
         */
        @Override
        public View newView(Context context, Cursor cursor, ViewGroup parent) {
            final LayoutInflater inflater = LayoutInflater.from(context);
            final View view =
                    inflater.inflate(android.R.layout.simple_dropdown_item_1line,
                            parent, false);

           return view;
        }

        /**
         * Called by the AutoCompleteTextView field when a choice has been made
         * by the user.
         *
         * @param listView
         *            The ListView containing the choices that were displayed to
         *            the user.
         * @param view
         *            The field representing the selected choice
         * @param position
         *            The position of the choice within the list (0-based)
         * @param id
         *            The id of the row that was chosen (as provided by the _id
         *            column in the cursor.)
         */
        @Override
        public void onItemClick(AdapterView&lt;?&gt; listView, View view, int position, long id) {
            // Get the cursor, positioned to the corresponding row in the result set
            Cursor cursor = (Cursor) listView.getItemAtPosition(position);

            // Get the state's capital from this row in the database.
            String capital = cursor.getString(cursor.getColumnIndexOrThrow(&quot;capital&quot;));

            // Update the parent class's TextView
            mStateCapitalView.setText(capital);
        }
    }

    private TextView mStateCapitalView;
    private AutoCompleteTextView mStateNameView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        AutoCompleteDbAdapter dbHelper = new AutoCompleteDbAdapter(this);
        setContentView(R.layout.selectstate);
        Button confirmButton = (Button) findViewById(R.id.confirm);
        confirmButton.setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
                setResult(RESULT_OK);
                finish();
            }
        });

        mStateCapitalView = (TextView) findViewById(R.id.state_capital);
        mStateNameView = (AutoCompleteTextView) findViewById(R.id.state_name);

        // Create an ItemAutoTextAdapter for the State Name field,
        // and set it as the OnItemClickListener for that field.
        ItemAutoTextAdapter adapter = this.new ItemAutoTextAdapter(dbHelper);
        mStateNameView.setAdapter(adapter);
        mStateNameView.setOnItemClickListener(adapter);
    }
}
</pre>
<p><a name="AutoCompleteDbAdapter"></a><br />
Here&#8217;s the <code>AutoCompleteDbAdapter</code> class.  It&#8217;s less interesting for this example, so the code is hidden by default. Click on the &#8220;show source&#8221; link to view it.</p>
<pre class="brush: java; collapse: true; light: false; title: AutoCompleteDbAdapter; toolbar: true;">
package org.oowb.AutoCompleteExample;

import android.app.Activity;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

/**
 * Simple database access helper class.
 *
 * @author Dan Breslau
 */
public class AutoCompleteDbAdapter {
    /**
     * List of states and capitals.
     */
    private static final String[][] States = {
            { &quot;Alabama&quot;, &quot;Montgomery&quot; },
            { &quot;Alaska&quot;, &quot;Juneau&quot; },
            { &quot;Arizona&quot;, &quot;Phoenix&quot; },
            { &quot;Arkansas&quot;, &quot;Little Rock&quot; },
            { &quot;California&quot;, &quot;Sacramento&quot; },
            { &quot;Colorado&quot;, &quot;Denver&quot; },
            { &quot;Confusion&quot;, &quot;\&quot;C\&quot;&quot; },
            { &quot;Connecticut&quot;, &quot;Hartford&quot; },
            { &quot;Delaware&quot;, &quot;Dover&quot; },
            { &quot;Florida&quot;, &quot;Tallahassee&quot; },
            { &quot;Georgia&quot;, &quot;Atlanta&quot; },
            { &quot;Hawaii&quot;, &quot;Honolulu&quot; },
            { &quot;Idaho&quot;, &quot;Boise&quot; },
            { &quot;Illinois&quot;, &quot;Springfield&quot; },
            { &quot;Indiana&quot;, &quot;Indianapolis&quot; },
            { &quot;Iowa&quot;, &quot;Des Moines&quot; },
            { &quot;Kansas&quot;, &quot;Topeka&quot; },
            { &quot;Kentucky&quot;, &quot;Frankfort&quot; },
            { &quot;Louisiana&quot;, &quot;Baton Rouge&quot; },
            { &quot;Maine&quot;, &quot;Augusta&quot; },
            { &quot;Maryland&quot;, &quot;Annapolis&quot; },
            { &quot;Massachusetts&quot;, &quot;Boston&quot; },
            { &quot;Michigan&quot;, &quot;Lansing&quot; },
            { &quot;Minnesota&quot;, &quot;St. Paul&quot; },
            { &quot;Mississippi&quot;, &quot;Jackson&quot; },
            { &quot;Missouri&quot;, &quot;Jefferson City&quot; },
            { &quot;Montana&quot;, &quot;Helena&quot; },
            { &quot;Nebraska&quot;, &quot;Lincoln&quot; },
            { &quot;Nevada&quot;, &quot;Carson City&quot; },
            { &quot;New Hampshire&quot;, &quot;Concord&quot; },
            { &quot;New Jersey&quot;, &quot;Trenton&quot; },
            { &quot;New Mexico&quot;, &quot;Santa Fe&quot; },
            { &quot;New York&quot;, &quot;Albany&quot; },
            { &quot;North Carolina&quot;, &quot;Raleigh&quot; },
            { &quot;North Dakota&quot;, &quot;Bismarck&quot; },
            { &quot;Ohio&quot;, &quot;Columbus&quot; },
            { &quot;Oklahoma&quot;, &quot;Oklahoma City&quot; },
            { &quot;Oregon&quot;, &quot;Salem&quot; },
            { &quot;Pennsylvania&quot;, &quot;Harrisburg&quot; },
            { &quot;Rhode Island&quot;, &quot;Providence&quot; },
            { &quot;South Carolina&quot;, &quot;Columbia&quot; },
            { &quot;South Dakota&quot;, &quot;Pierre&quot; },
            { &quot;Tennessee&quot;, &quot;Nashville&quot; },
            { &quot;Texas&quot;, &quot;Austin&quot; },
            { &quot;Utah&quot;, &quot;Salt Lake City&quot; },
            { &quot;Vermont&quot;, &quot;Montpelier&quot; },
            { &quot;Virginia&quot;, &quot;Richmond&quot; },
            { &quot;Washington&quot;, &quot;Olympia&quot; },
            { &quot;West Virginia&quot;, &quot;Charleston&quot; },
            { &quot;Wisconsin&quot;, &quot;Madison&quot; },
            { &quot;Wyoming&quot;, &quot;Cheyenne&quot; }
    };

    private static final String DATABASE_NAME = &quot;capitals&quot;;
    private static final String TABLE_NAME = &quot;state&quot;;
    private static final int DATABASE_VERSION = 1;

    private class DatabaseHelper extends SQLiteOpenHelper {

        DatabaseHelper(Context context) {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            final String DATABASE_CREATE_STATES =
                    &quot;create table &quot; + TABLE_NAME
                            + &quot;(_id integer primary key autoincrement&quot;
                            + &quot;, state text not null&quot;
                            + &quot;, capital text not null)&quot;;

            db.execSQL(DATABASE_CREATE_STATES);
            populateWithData(db);
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int old, int new) {
            db.execSQL(&quot;DROP TABLE IF EXISTS &quot; + TABLE_NAME);
            onCreate(db);
        }
    }

    private DatabaseHelper mDbHelper;
    private SQLiteDatabase mDb;
    private final Activity mActivity;

    /**
     * Constructor - takes the context to allow the database to be
     * opened/created
     *
     * @param activity
     *            the Activity that is using the database
     */
    public AutoCompleteDbAdapter(Activity activity) {
        this.mActivity = activity;
        mDbHelper = this.new DatabaseHelper(activity);
        mDb = mDbHelper.getWritableDatabase();
    }

    /**
     * Closes the database.
     */
    public void close() {
        mDbHelper.close();
    }

    /**
     * Return a Cursor that returns all states (and their state capitals) where
     * the state name begins with the given constraint string.
     *
     * @param constraint
     *            Specifies the first letters of the states to be listed. If
     *            null, all rows are returned.
     * @return Cursor managed and positioned to the first state, if found
     * @throws SQLException
     *             if query fails
     */
    public Cursor getMatchingStates(String constraint) throws SQLException {

        String queryString =
                &quot;SELECT _id, state, capital FROM &quot; + TABLE_NAME;

        if (constraint != null) {
            // Query for any rows where the state name begins with the
            // string specified in constraint.
            //
            // NOTE:
            // If wildcards are to be used in a rawQuery, they must appear
            // in the query parameters, and not in the query string proper.
            // See http://code.google.com/p/android/issues/detail?id=3153
            constraint = constraint.trim() + &quot;%&quot;;
            queryString += &quot; WHERE state LIKE ?&quot;;
        }
        String params[] = { constraint };

        if (constraint == null) {
            // If no parameters are used in the query,
            // the params arg must be null.
            params = null;
        }
        try {
            Cursor cursor = mDb.rawQuery(queryString, params);
            if (cursor != null) {
                this.mActivity.startManagingCursor(cursor);
                cursor.moveToFirst();
                return cursor;
            }
        }
        catch (SQLException e) {
            Log.e(&quot;AutoCompleteDbAdapter&quot;, e.toString());
            throw e;
        }

        return null;
    }

    /**
     * Populates the database with data on states and state capitals.
     *
     * @param db
     *            The database to be populated; must have the appropriate table
     *            (&quot;state&quot;) and columns (&quot;state&quot; and &quot;values&quot;) already set up.
     */
    private void populateWithData(SQLiteDatabase db) {
        try {
            db.beginTransaction();
            ContentValues values = new ContentValues();
            // Populate the database with the state/capital city
            // pairs found in the States array.
            for (String[] s : States) {
                values.put(&quot;state&quot;, s[0]);
                values.put(&quot;capital&quot;, s[1]);

                db.insert(TABLE_NAME, &quot;state&quot;, values);
            }
            db.setTransactionSuccessful();
        }
        finally {
            db.endTransaction();
        }
    }
}
</pre>
<h3><a name="SimpleCursorAdapter"></a>Using <code>SimpleCursorAdapter</code></h3>
<p>As mentioned above, changing the Adapter&#8217;s base class to <code>SimpleCursorAdapter</code> is fairly simple. Here&#8217;s a summary of the changes needed:</p>
<ul>
<li>The <code>SimpleCursorAdapter</code> constructor requires a resource ID for the layout used for items in the list. As before, we are using <code>android.R.layout.simple_dropdown_item_1line</code> for this layout.
</li>
<li>The constructor for <code>SimpleCursorAdapter</code> also requires parameters named <code>from</code> and <code>to</code>. These are arrays indicating which column(s) in the database hold the relevant data, and which field(s) in the View will display that data.</li>
<div>When the <code>SimpleCursorAdapter</code> is used to support an <code>AutoCompleteTextView</code>, only one column/field pair is used. The column, of course, is the column that supplies the names (here, &#8220;state&#8221;.) But how do we identify the field in the <code>to</code> array? Help comes to us through <code>android.R.id.text1</code>, a resource that is used to identify the first (and only) TextField within the standard item layout (<code>android.R.layout.simple_dropdown_item_1line</code>.)</div>
<div>This results in the following definitions for the <code>from</code> and <code>to</code> parameters. (I defined these in the outer <code>SelectState</code> class, because an inner class isn&#8217;t allowed to have static data.)</div>
<pre class="brush: java;">
    final static int[] to = new int[] { android.R.id.text1 };
    final static String[] from = new String[] { &quot;state&quot; };
</pre>
<li>The constructor is changed to call its superclass as follows:</li>
<pre class="brush: java;">
super(SelectState.this,
        android.R.layout.simple_dropdown_item_1line,
        null, from, to);
</pre>
<li>The <code>newView</code> and <code>bindView</code> methods can be removed.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.outofwhatbox.com/blog/2010/11/android-autocompletetextview-sqlite-and-dependent-fields/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>SyntaxHighlighter: Easier to load; faster to boot?</title>
		<link>http://www.outofwhatbox.com/blog/2010/02/syntaxhighlighter-easier-to-load-faster-to-boot/</link>
		<comments>http://www.outofwhatbox.com/blog/2010/02/syntaxhighlighter-easier-to-load-faster-to-boot/#comments</comments>
		<pubDate>Mon, 08 Feb 2010 00:45:14 +0000</pubDate>
		<dc:creator>Dan Breslau</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[syntaxhighlighter]]></category>

		<guid isPermaLink="false">http://www.outofwhatbox.com/blog/?p=625</guid>
		<description><![CDATA[I've introduced a new method for loading SyntaxHighlighter onto a web page. The goal was simply to make it easier to integrate SyntaxHighlighter into a web site. So, I was pleasantly surprised to find that the new method often loads faster than the traditional method.]]></description>
			<content:encoded><![CDATA[<p>SyntaxHighlighter has a relatively high surface area, typically requiring two CSS files and at least two JavaScript files to be linked into a web page. Here&#8217;s a truncated example:</p>
<pre class="brush: xml; auto-links: false;">
&lt;html&gt;
&lt;head&gt;
	&lt;!-- Stylesheets for SyntaxHighlighter --&gt;
&lt;link type=&quot;text/css&quot; rel=&quot;stylesheet&quot; href=&quot;styles/shCore.css&quot;/&gt;
&lt;link type=&quot;text/css&quot; rel=&quot;stylesheet&quot; href=&quot;styles/shThemeDefault.css&quot;/&gt;
...
&lt;/head&gt;
&lt;body&gt;

&lt;em&gt;...Some kind of interesting page content usually goes here,
but we're not interested in that right now...&lt;/em&gt;

	&lt;!-- Load the SyntaxHighlighter Core and Brush scripts. A
               separate Brush script is required for each language. --&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;scripts/shCore.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;scripts/shBrushJava.js&quot;&gt;&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;scripts/shBrushJScript.js&quot;&gt;&lt;/script&gt;
	&lt;!-- Don't forget the XML brush if you're using html-script --&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;scripts/shBrushXml.js&quot;&gt;&lt;/script&gt;

	&lt;!-- Now that all the script files are loaded, begin highlighting. --&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
SyntaxHighlighter.config.stripBrs = true;
// ... additional configuration, as needed ...

SyntaxHighlighter.all();
&lt;/script&gt;

&lt;/body&gt;
</pre>
<p>Some users have wanted a simpler way to integrate SyntaxHighlighter into their sites. Last year, <a href="http://davidchambersdesign.com/prototype-loader-for-syntaxhighlighter/">David Chambers</a> wrote a script that uses the <a href="http://www.prototypejs.org/">Prototype library</a> to load the required CSS and brush files. He ran into a troubling quirk in SyntaxHighlighter: It needs any required brush files to be loaded before it starts highlighting. I responded by updating the <a href="http://www.outofwhatbox.com/blog/2009/12/update-of-forked-syntaxhighlighter/">OOWB fork</a> of SyntaxHighlighter, so that <a href="http://www.outofwhatbox.com/blog/2009/06/occams-razor-and-brushes/">brushes could be loaded asynchronously</a>. But that&#8217;s as far as I&#8217;d gone towards automated loading, until now.</p>
<p>I recently looked into adding automated loading to SyntaxHighlighter itself, coming up with not one, but two automated solutions. I should really say one and a half, as one is still in the alpha stage and will likely stay there.</p>
<p>The &#8220;alpha-stage&#8221; approach comprises a new JavaScript file that loads SyntaxHighlighter and the necessary brush files through AJAX, by way of a pair of simple Java servlets. I&#8217;d hoped that this would lead to faster load times, by reducing the total number of downloads. And so it does—sometimes. For testing, I used <a href="http://code.google.com/appengine/">Google App Engine</a> as the servlet host (using the free quotas.) Performance was inconsistent, to say the least; this is probably due to the Google App Engine&#8217;s method of starting up and shutting down servlets. It seemed that only by making repeated hits on the servlets in rapid succession could I be sure of getting to a container that already had my servlets running, thus getting good load times.<sup><a href="#shBoot-1" name="shBoot-1-ref">1</a></sup> The servlets are still up there; if you&#8217;d like the Java source (to host them elsewhere), and/or the JavaScript for using them, <a href="http://www.outofwhatbox.com/blog/contact/">just let me know.</a></p>
<p>I also implemented a pure JavaScript approach, which I <em>hadn&#8217;t</em> expected to yield better load times. Yet I&#8217;ve seen a number of cases where this is faster than the original, static way of loading SyntaxHighlighter. I&#8217;m releasing a <a href="http://www.outofwhatbox.com/blog/syntaxhighlighter-downloads/">new download</a> so that you can try it out. I highly recommend that you test it thoroughly before putting it into real use.</p>
<p>To use this new method, the web page invokes <code>SyntaxHighlighter.boot</code> instead of <code>SyntaxHighlighter.all</code>. When <code>boot</code> is used as the entry point, SyntaxHighlighter determines which brushes are required by the web page, and issues HTTP requests for each brush file (as well as the appropriate CSS.) These requests use the age-old method of adding a <code><script></script></code> tag for each brush, and a <code>
<link></link></code> tag for each CSS file.</p>
<p>Using <code>SyntaxHighlighter.boot</code>, a web page only needs to add a couple of scripts, usually at the end of the <code><body></body></code>. No CSS link elements are required.</p>
<pre class="brush: xml; auto-links: false;">
&lt;!--  We just need to load shCore.js near the end of the &lt;body&gt; element,
	then call SyntaxHighlighter.boot() with our configuration options. --&gt;

&lt;script type=&quot;text/javascript&quot;
src=&quot;http://path/to/sh/directory/syntaxhighlighter/scripts/shCore.js&quot;&gt;&lt;/script&gt;

&lt;script type=&quot;text/javascript&quot;&gt;
	SyntaxHighlighter.boot(
		&quot;http://path/to/syntaxhighlighter/root/syntaxhighlighter/&quot;,
		{theme : &quot;Default&quot;}, // Configuration settings
		{stripBrs : true}      // Default settings
	);
&lt;/script&gt;

&lt;/body&gt;
</pre>
<p>That&#8217;s it. Every page on your site can use the same set-up, regardless of which brush files it needs. (For another example, look at the HTML source for this page.)</p>
<p>When an HTML page includes external scripts—that is, <code><script></script></code> elements with <code>src</code> attributes, the browser loads the script files synchronously, as it encounters them in the HTML. When the scripts are loaded dynamically, the browser can load them asynchronously; several scripts may then be loading simultaneously. This can be particularly helpful for pages that use multiple brushes. Here&#8217;s a Firebug sequence diagram of a web page with five brushes, loading in SyntaxHighlighter&#8217;s traditional way:</p>
<div class="oowbcenter"><a target="blank" href="http://img.outofwhatbox.com/shLoading/stdLoadTimeLarge.png"><img alt="" title="" src="http://img.outofwhatbox.com/shLoading/stdLoadTimeSmall.png" /></a>
<p class="oowb-caption-text">(Click on image for larger view)</p>
</div>
<p>Here&#8217;s the same page, modified to use the <code>boot</code> method. Notice that, unlike in the first picture, the <code>shBrush</code>..<code>.js</code> files are loaded in parallel:</p>
<div class="oowbcenter"><a target="blank" href="http://img.outofwhatbox.com/shLoading/bootLoadTimeLarge.png"><img alt="" title="" src="http://img.outofwhatbox.com/shLoading/bootLoadTimeSmall.png" /></a>
<p class="oowb-caption-text">(Click on image for larger view)</p>
</div>
<p>Of course, <a href="http://yuiblog.com/blog/2008/07/22/non-blocking-scripts/">this isn&#8217;t an entirely new discovery</a>, but it came as a pleasant surprise nonetheless.</p>
<h4>Availability</h4>
<p>In addition to SyntaxHighlighter itself, I also modified Viper007Bond&#8217;s <a href="http://wordpress.org/extend/plugins/syntaxhighlighter/">SyntaxHighlighter Evolved</a> plugin for WordPress to use the new <code>boot</code> method. This simplified the code quite a bit, though it may have introduced bugs.</p>
<p>SyntaxHighlighter and SyntaxHighlighter Evolved are each available on the <a href="http://www.outofwhatbox.com/blog/syntaxhighlighter-downloads/">downloads page</a>. <strong>Test before using.</strong> <em>Note: If you&#8217;ve been using SyntaxHighlighter Evolved, you will probably need to re-set your settings if you install this plugin.</em></p>
<h4>Implementation notes</h4>
<p>In the traditional SyntaxHighlighter, all brushes must be loaded before <code>SyntaxHighlighter.all</code> is invoked. In this fork, <a href="<a href="http://www.outofwhatbox.com/blog/2009/06/occams-razor-and-brushes/">&#8220;>brushes can load at any time</a> after <code>shCore.js</code> has been loaded. This flexibility was key to the design of the <code>boot</code> method: If a brush is loaded after <code>SyntaxHighlighter.all</code> or <code>SyntaxHighlighter.boot</code> is invoked, <code>SyntaxHighlighter</code> looks through the page to see if there&#8217;s any input requesting the newly loaded brush.</p>
<p>The <code>boot</code> method needs to map each brush name to the script file that implements that brush. I implemented this by modifying the Perl script that builds and stages SyntaxHighlighter. The script now parses the *Brush.js files in the source tree, pulling out the names and aliases supported by each file, and writes them into an array in <code>shCore.js</code>. The downside of this is that testing via the <code>boot</code> method requires re-running the script, which builds and stages the files into a new directory, from where I can run tests. Even though the script only takes about a second, it&#8217;s crossed the boundary between having <em>no</em> build step in the development cycle, and having <em>any</em> build step in the development cycle.</p>
<h3> When You Come To A Fork In The Road, Take It.</h3>
<p>I had two motives for working on SyntaxHighlighter: One, to improve its display of code on my own blog and elsewhere. Two, as a training ground for learning JavaScript.</p>
<p>I was between jobs when I took on this project. As of this Monday, that will no longer be the case. That&#8217;s great news for me, but much as I&#8217;d like to keep the SyntaxHighlighter work moving forward, I don&#8217;t really know if or when I&#8217;ll have the time for it. On the other hand, I no longer feel like I need a private JavaScript training ground. So, I&#8217;ve pushed <a href="http://bitbucket.org/dbreslau/syntaxhighlighter/">my repository</a> to bitbucket.org as a fork of <a href="http://bitbucket.org/alexg/syntaxhighlighter/">Alex&#8217;s repository</a>. If he so chooses (and so far he hasn&#8217;t, which is fine), Alex is welcome to merge the fork into his branch. Perhaps more importantly, anyone else can now fork the code, and/or make contributions to this fork.</p>
<p>I do have some more goals in mind for SyntaxHighlighter. I&#8217;ll be writing about them in the not-too-distant future.</p>
<div>
<hr /></div>
<p><sup><a href="#shBoot-1-ref" name="shBoot-1">1</a></sup>Perhaps a faster host would lead to the faster load times I&#8217;d hoped for; but that would probably require payment, which makes this approach considerably less attractive.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.outofwhatbox.com/blog/2010/02/syntaxhighlighter-easier-to-load-faster-to-boot/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Update of Forked SyntaxHighlighter</title>
		<link>http://www.outofwhatbox.com/blog/2009/12/update-of-forked-syntaxhighlighter/</link>
		<comments>http://www.outofwhatbox.com/blog/2009/12/update-of-forked-syntaxhighlighter/#comments</comments>
		<pubDate>Fri, 18 Dec 2009 17:20:19 +0000</pubDate>
		<dc:creator>Dan Breslau</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[syntaxhighlighter]]></category>

		<guid isPermaLink="false">http://www.outofwhatbox.com/blog/?p=613</guid>
		<description><![CDATA[I've updated this site's fork of the SyntaxHighlighter software by Alex Gorbatchev. These features a partial merge from Alex's 2.1.364 release. I've also added a "Hide" button to the toolbar.]]></description>
			<content:encoded><![CDATA[<p>As promised, I&#8217;ve updated this site&#8217;s fork of the <a href="http://alexgorbatchev.com/wiki/SyntaxHighlighter">SyntaxHighlighter</a> software by Alex Gorbatchev. I&#8217;ve merged in many of the changes that Alex included in his 2.1.364 release, but with the following differences:</p>
<ul>
<li>In 2.1.364, the ruler functionality was removed. It&#8217;s still included here.</li>
<li>2.1.364 changed the way that wrapped lines are presented. I&#8217;ve kept the old presentation, but modified the icon that&#8217;s used to signify wrapping.</li>
<li>Internally, 2.1.364 uses a separate HTML table to represent each line of source.  I&#8217;ve maintained the older pattern of simply using a separate <code>&lt;div&gt;</code> to represent each line.</li>
</ul>
<p>Other new bits in this release:
<ul>
<li>I&#8217;ve added a &#8220;Hide&#8221; button to the toolbar. Code blocks can now be expanded/collapsed at the user&#8217;s whim. (As before, an author can still choose to present a block in the hidden/collapsed state.)</li>
<li><del datetime="2009-12-18T19:16:34+00:00">When both a horizontal scrollbar and a gutter (the line number column) are displayed, the scrollbar no longer extends under the gutter. (I <em>think</em> this is an improvement; as always, feedback is welcome.)</del> <em>Update: I&#8217;ve backed out this change; it was causing problems with IE7.</em></li>
</ul>
<p>The ZIP file is available through the <a href="http://www.outofwhatbox.com/blog/syntaxhighlighter-downloads/">Download Page</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.outofwhatbox.com/blog/2009/12/update-of-forked-syntaxhighlighter/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Do not adjust your eyes; it&#8217;s just a new theme.</title>
		<link>http://www.outofwhatbox.com/blog/2009/12/do-not-adjust-your-eyes-its-just-a-new-theme/</link>
		<comments>http://www.outofwhatbox.com/blog/2009/12/do-not-adjust-your-eyes-its-just-a-new-theme/#comments</comments>
		<pubDate>Thu, 17 Dec 2009 05:43:33 +0000</pubDate>
		<dc:creator>Dan Breslau</dc:creator>
				<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[syntaxhighlighter]]></category>

		<guid isPermaLink="false">http://www.outofwhatbox.com/blog/?p=606</guid>
		<description><![CDATA[I&#8217;ve just gone live with a different WordPress theme. So, if you&#8217;re feeling a bit lost, don&#8217;t panic. This is a new theme, iTech, which was just released last month. I&#8217;ve tailored the CSS, fixed a bug or two in the php, and even managed to add a new customization option. It&#8217;s been a good [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve just gone live with a different <a href="http://codex.wordpress.org/Using_Themes">WordPress theme</a>. So, if you&#8217;re feeling a bit lost, don&#8217;t panic. This is a new theme, <a href="http://zacklive.com/itech-theme-free-wordpress-theme-for-gadgets-and-tech-blogs/690/">iTech</a>, which was just released last month. I&#8217;ve tailored the CSS, fixed a bug or two in the php, and even managed to add a new customization option. It&#8217;s been a good learning experience. Most importantly, I hope you&#8217;ll like the new look. Let me know what you think.</p>
<h4>New version of SyntaxHighlighter coming</h4>
<p>Some folks have asked me offline if I&#8217;m going to be merging Alex Gorbatchev&#8217;s 2.1.364 version of <a href="http://alexgorbatchev.com/wiki/SyntaxHighlighter">SyntaxHighlighter</a> with the <a href="http://www.outofwhatbox.com/blog/tag/syntaxhighlighter/">OOWB fork</a> that I&#8217;ve been supporting here. The answer to that is yes; if all goes well, I should be posting it in the next few days. As for creating a public repository, perhaps on <a href="http://bitbucket.org/">bitbucket</a>: Maybe. If you&#8217;d like to see this happen, please let me know. Actually, I&#8217;d like to hear from anyone who&#8217;s rolled out the OOWB fork: What site(s) are you using it on, and how is it working out? Please leave a comment, or <a href="http://www.outofwhatbox.com/blog/contact/">send email</a>.</p>
<p>Did I say &#8220;fork&#8221;? Uh, yeah. While 2.1.364 is solid, it doesn&#8217;t cover most of the improvements that I&#8217;ve made (check the <a href="http://www.outofwhatbox.com/blog/syntaxhighlighter-downloads/">Download Page</a> to see a summary.) Ultimately, I&#8217;d like to see these changes rolled back into Alex&#8217;s version, but that doesn&#8217;t appear to be happening anytime soon. There could be good reasons for that; certainly my version looks larger, just for starters. (I <em>think</em> that the <em>total</em> footprint may be smaller, but that&#8217;s a tough call.) All I can really say is that we&#8217;ll see how it goes. I plan to keep making improvements in the software, at least for my own sake; but I regard Alex as the primary author and will continue to do so.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.outofwhatbox.com/blog/2009/12/do-not-adjust-your-eyes-its-just-a-new-theme/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JavaScript Array Performance, And Why It Matters</title>
		<link>http://www.outofwhatbox.com/blog/2009/12/javascript-array-performance-and-why-it-matters/</link>
		<comments>http://www.outofwhatbox.com/blog/2009/12/javascript-array-performance-and-why-it-matters/#comments</comments>
		<pubDate>Tue, 01 Dec 2009 15:21:13 +0000</pubDate>
		<dc:creator>Dan Breslau</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[JavaScript arrays]]></category>
		<category><![CDATA[JavaScript performance]]></category>

		<guid isPermaLink="false">http://www.outofwhatbox.com/blog/?p=588</guid>
		<description><![CDATA[Arrays can present an unexpected performance bottleneck in JavaScript. Here I show that array performance is influenced by some surprising details of the array and how it's used.]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.outofwhatbox.com/blog/2009/11/javascript-array-performance-initialize-to-optimize/">My last post</a> described how a JavaScript array had become a performance bottleneck. Here, I&#8217;ll delve further into how some JavaScript programs become array-bound, and how to break that bind when you need to.</p>
<p>Let&#8217;s start with this:</p>
<div class="oowbcenter" ><img title="JavaScript array elements can be much slower than scalar variables" src="http://img.outofwhatbox.com/JSArrayOptimizationII/ArraysVsScalars.png" alt="JavaScript array elements can be much slower than scalar variables" /></div>
<p>As the graph shows, JavaScript array performance ranges from OK (nearly equivalent to scalars) to awful. The reasons for poor performance vary, but most can be boiled down to this: The JavaScript interpreter is essentially left guessing about how an array will be used. And guess it does. When an array is <a href="http://www.outofwhatbox.com/blog/2009/11/javascript-array-performance-initialize-to-optimize/">constructed and initialized</a>, the interpreter can observe where data is stored into a new array. Certain kinds of patterns may nudge it to optimize for better speed, or lower memory consumption. So, performance suffers when the interpreter makes the wrong interpretation.</p>
<p>I looked into performance of JavaScript arrays with three popular Windows browsers: Internet Explorer 8, Google Chrome 3.0, and Firefox 3.5. Broadly speaking, these all seem to look for two or three types of arrays:</p>
<ul>
<li><em>Dense arrays</em>: These provide faster access to individual elements of the array.</li>
<li><em>Sparse arrays</em>: These are typically optimized for lower memory use.
</li>
<li><em>Sized arrays</em>: A variant of sparse arrays that are optimized for speed for certain cases.</li>
</ul>
<p>The interpreters optimize for dense arrays if the array&#8217;s elements are initialized in a continuous range, starting at index 0. This initialization can be done before there&#8217;s any data for the array, by using placeholders such as <code>0</code>, <code>null</code>, or even <code>undefined</code>. (There are other ways to get this optimization; this is simply the most reliable approach.)</p>
<p>Passing the array&#8217;s size in the constructor may also bring better performance. In my testing, I saw this only with sparse arrays in IE8 and (perhaps) in Chrome. I&#8217;ll refer to these as <em>sized arrays</em>; see <a href="#jsarraysII-sized">below</a> for some additional notes.</p>
<p>If an array is created as neither a dense nor a sized array, it&#8217;s treated as a sparse array.</p>
<p>As a general rule, the array&#8217;s behavior is established shortly after construction. If you sparsely populate an array, then assign other values to the remaining elements, you&#8217;re left with a densely-populated sparse array.<a href="#jsarraysII-note-1" name="jsarraysII-ref-1"><sup>1</sup></a></p>
<div class="oowbsidebar">
Hold it there. A <em>densely populated sparse array</em>? Holy <a href="http://www.joelonsoftware.com/articles/LeakyAbstractions.html">leaky abstractions</a>, Batman!</p>
<p>Perhaps we&#8217;re lacking some terms. If we&#8217;re trying to coax better performance from a <em>sparse</em> array by filling it up with placeholder values, that doesn&#8217;t make it a <em>dense</em> array—not from your program&#8217;s perspective, at least. To describe it from the interpreter&#8217;s perspective, I’ll refer to an array that’s initialized after creation—with live or dead data—as a <em>cleared</em> array. An uninitialized array that is populated at random indices is a <em>default</em> array, regardless of how dense it eventually becomes. Finally, a <em>sized</em> array is, well, a sized array. So, that &#8220;densely populated sparse array&#8221; is now a &#8220;densely populated default array.&#8221; That&#8217;s still an awkward phrase, but at least it&#8217;s not an oxymoron.</div>
<p>Now that we can finally get to some data, let&#8217;s discuss scalability. This graph represents the time taken to read about 30,000,000 values from arrays of various sizes, using three Windows browsers. Seven data sets are presented: Cleared and default arrays for each of IE8, Google Chrome 3.0, and Firefox 3.5, plus sized arrays for IE8.</p>
<div class="oowbcenter" ><a href="http://img.outofwhatbox.com/JSArrayOptimizationII/ArraySizeVsRunTimeLarge.png" target="blank"><img title="As array size increases, run time may increase as well. (Click for larger graph with legend)" src="http://img.outofwhatbox.com/JSArrayOptimizationII/ArraySizeVsRunTimeSmall.png" alt="As array size increases, run time may increase as well. (Click for larger graph with legend)" /></a>
<p class="oowb-caption-text">Array Size Vs. Access Time. (Click for larger graph with legend)</p>
</div>
<p>Note that in three of the seven cases, time grows linearly as size increases<a href="#jsarraysII-note-2" name="jsarraysII-ref-2"><sup>2</sup></a>. This growth effectively multiplies the program&#8217;s <a href="http://en.wikipedia.org/wiki/Big_O_notation">complexity</a> by O(N). That is, an algorithm that might normally have O(N) performance instead shows O(N<sup>2</sup>) performance, and so on. This can have a sizable impact on scalability.</p>
<p>The graph makes it clear that the fastest arrays are cleared. However, making a very sparse cleared array would gobble up a large swath of memory for a small number of values. For such cases, you may want to stick with sparse or sized arrays. Here&#8217;s a closer look at their performance.</p>
<p>The following tests all used arrays of 180,000 elements. Each data point represents performance with a different &#8220;hit ratio&#8221;; that is, the ratio of defined values read from the array. While array density also varied, its effect appears in only one case, which I&#8217;ll show separately<a href="#jsarraysII-note-3" name="jsarraysII-ref-3"><sup>3</sup></a>. For reference, these graphs also show the performance with cleared arrays.</p>
<p>This graph shows the performance of sized, default, and cleared arrays in IE8. Notice that the &#8220;sized&#8221; trendline (in blue) begins significantly above the &#8220;default&#8221; trendline, and ends slightly above the &#8220;cleared&#8221; trendline. Clearly, IE optimizes sized arrays to work better when reading defined values.</p>
<div class="oowbcenter" ><a href="http://img.outofwhatbox.com/JSArrayOptimizationII/IEHitsLarge.png" target="blank"><img title="Performance of defined and undefined array elements in IE8. (Click for larger graph with legend)" src="http://img.outofwhatbox.com/JSArrayOptimizationII/IEHitsSmall.png" alt="Performance of defined and undefined array elements in IE8. (Click for larger graph with legend)" /></a>
<p class="oowb-caption-text">Array Hits Vs. Access Time in IE8. (Click for larger graph with legend)</p>
</div>
<p>Firefox 3.5 also looks slower when accessing undefined elements, but there&#8217;s no real gain from passing a size parameter to the array constructor:</p>
<div class="oowbcenter" ><a href="http://img.outofwhatbox.com/JSArrayOptimizationII/FFHitsLarge.png" target="blank"><img title="Performance of defined and undefined array elements in Firefox 3.5. (Click for larger graph with legend)" src="http://img.outofwhatbox.com/JSArrayOptimizationII/FFHitsSmall.png" alt="Performance of defined and undefined array elements in Firefox 3.5. (Click for larger graph with legend)" /></a>
<p class="oowb-caption-text">Array Hits Vs. Access Time in Firefox 3.5. (Click for larger graph with legend)</p>
</div>
<p>In Chrome, array access times are clustered into high and low ranges of values, based on array density. Chrome performs markedly better with arrays having a density of 10% or higher, vs. arrays of lower density. The data sets below have been split accordingly. Since there&#8217;s much more variation <em>between</em> these two ranges than here is <em>among</em> them, it&#8217;s a good bet that the 10% threshold is hard-coded somewhere in Chrome&#8217;s V8 JavaScript interpreter.</p>
<div class="oowbcenter" ><a href="http://img.outofwhatbox.com/JSArrayOptimizationII/ChromeSplitLarge.png" target="blank"><img title="Array Hits Vs. Access Time in Chrome, by array density. (Click for larger graph with legend)" src="http://img.outofwhatbox.com/JSArrayOptimizationII/ChromeSplitSmall.png" alt="Array Hits Vs. Access Time in Chrome, by array density. (Click for larger graph with legend)" /></a>
<p class="oowb-caption-text">Array Hits Vs. Access Time in Chrome, by array density. (Click for larger graph with legend)</p>
</div>
<p><a name="jsarraysII-sized"></a><br />
<h3>Notes on sized arrays</h3>
<p>It makes sense that <i>if</i> a size is passed to the array constructor, <i>and</i> the size value is accurate, then the interpreter can optimize the array for that size. The problem is that the size value won&#8217;t always be accurate; nor does it suggest how dense the array might become. Hence the interpreter may not be able to rely on the size value even when it&#8217;s present.</p>
<p>Sized array behavior in IE8 isn&#8217;t what I&#8217;d expected. I&#8217;d found a note written prior to IE8&#8242;s release by one of its developers, which I had taken to mean that <a href="http://blogs.msdn.com/jscript/archive/2008/03/25/performance-optimization-of-arrays-part-i.aspx">these arrays should perform like cleared arrays</a>, but that&#8217;s clearly not the case. Sized arrays in IE8 actually incur a small <em>penalty</em> when accessing undefined array elements, to the point where if you access <em>only</em> undefined elements, a sized array may be slower than a default array. On a closer reading, the note refers to &#8220;any <em>indexed</em> entry&#8221; within the array&#8217;s range <em>[emphasis mine.]</em> Of course, undefined entries wouldn&#8217;t be indexed. The note was accurate, but arguably didn&#8217;t go far enough.</p>
<p>In Chrome, using an explicit size for a sparse array does seem to make a small but measurable difference in some cases. But on the whole, there&#8217;s little reason to use this for improved performance, especially since Chrome is currently the browser <em>least in need</em> of a performance boost in these tests. </p>
<p>The performance of Firefox 3.5 suggests that it ignores the constructor&#8217;s size parameter. However, a quick trip through the <a href="http://hg.mozilla.org/releases/mozilla-1.9.1">browser&#8217;s source code</a> indicates that the size <i>should</i> make a difference. Perhaps other kinds of tests would be able to draw this out, or perhaps there&#8217;s an opportunity for improvement in the code.</p>
<h3>Memory Consumption</h3>
<p>Measuring the physical size of JavaScript data is a sketchy undertaking. About the best one can do is to compare the virtual memory size of the browser process before and after creating a large array. This isn&#8217;t going to be very accurate. All the same, where there&#8217;s a large difference between values, it&#8217;s probably significant.</p>
<table style="" border="0" cellspacing="0" cellpadding="2" >
<tbody>
<tr class="oowbfirstRow">
<th style="text-align: left;" ><strong><code>Browser</code></strong></th>
<th style="text-align: center;" ><strong><code>Size Estimate, Default / Sized Arrays (Bytes)</code></strong></th>
<th style="text-align: center;" ><strong><code>Size Estimate, Cleared Arrays (Bytes)</code></strong></th>
</tr>
<tr>
<td><strong>Internet Explorer 8</strong></td>
<td style="text-align: left;"><em>(# of values)</em> x (approximately 76)</td>
<td style="text-align: left;"><em>(Length of array)</em> x (approx. 46)</td>
</tr>
<tr>
<td><strong>Firefox 3.5</strong></td>
<td style="text-align: left;"><em>(# of values)</em> x (approx. 63)</td>
<td style="text-align: left;"><em>(Length of array)</em> x (approx. 5)</td>
</tr>
<tr>
<td><strong>Google Chrome 3.0</strong></td>
<td style="text-align: left;"><em>(Length of array)</em> x (30–70)</td>
<td style="text-align: left;"><em>(Length of array)</em> x (approx. 14)</td>
</tr>
</tbody>
</table>
<p>In my last post, I wrote that a sparse 12K array of integers, implemented as a hash table, would likely consume over 36K of memory. If these measurements are reasonable, that was a gross understatement; a sparse 12K array could actually consume more than 70 bytes per element, or upwards of 860K.</p>
<p>At the extremes, for two arrays with the same length, one that&#8217;s very dense may use <em>less</em> memory than one of lower density—even though the lower density array, by definition, contains fewer values. Chrome and Firefox seem to account for this internally as they organize the array structure, but I&#8217;m not sure whether IE8 does.</p>
<h3>Recommendations</h3>
<div class="oowbbtw">Remember that premature optimization is folly, and all optimization has its costs. If you use the hints that I&#8217;ve described, keep in mind that the interpreter isn&#8217;t obliged to obey your intentions. Consider creating a factory method for arrays, so that <del>if</del> <ins>as</ins> the rules change, you can most easily adapt your code to suit.</div>
<ul>
<li>Use cleared arrays if speed is critical, <strong>or</strong> if the array reaches around 50% density. But don&#8217;t use them habitually, especially not for sparse arrays.</li>
<li>Because of IE8&#8242;s quirks, you should think twice before creating sized arrays. They&#8217;re helpful <strong>only if</strong> you have sparse data <strong>and</strong> you won&#8217;t often access an undefined array element.</li>
</ul>
<h3>Looking ahead</h3>
<p>JavaScript&#8217;s arrays are pleasant enough in normal use; but like all abstractions, they have their leaks. As JavaScript is used for increasingly sophisticated applications, it might be worthwhile for its designers to take a fresh look at scalability. There are ways to get the desired results, but negotiation via secret handshake doesn&#8217;t scale terribly well.</p>
<p>Without marring JavaScript&#8217;s simplicity, it should be possible to extend the language so that, <em>when necessary</em>, the developer can make plain to the interpreter what it should expect for a particular array. For example, this could mean adding APIs or syntax that let the developer declare the array&#8217;s expected size, density, and so forth. Or the problem could be addressed from the other direction: Simply allow the developer to request a structure that favors higher speed, or more compactness, for a particular array.</p>
<p>And although read-only objects may be a special case, I started down this path by looking at an <a href="http://www.outofwhatbox.com/blog/2009/11/trimming-trim-via-razing-arrays-javascript/">array used as a lookup table</a> which is effectively read-only after initialization. It would be nice if I could let the interpreter know this. A version of <a href="http://ruby-doc.org/core/classes/Object.html#M000356">Ruby&#8217;s <code>freeze</code> method</a> would fit the bill. This would give the interpreter a hint to optimize the array for read-only access, though it wouldn&#8217;t be required to do so.</p>
<p>Dreaming further, I&#8217;m also holding out hope that closures can be better optimized. After initialization, the lookup table in my version of <code>String.trim()</code> was only accessible <a href="http://www.outofwhatbox.com/blog/2009/11/trimming-trim-via-razing-arrays-javascript/">to a single, read-only method</a>. If the interpreter can verify that nothing&#8217;s going to change the array, it could move it to faster storage. Yes, this brings us back around to secret handshakes. But since closures have their own merits, I see this more as the icing on the cake.</p>
<p />
<hr />
<div><a name="jsarraysII-note-1" href="#jsarraysII-ref-1"><sup>1</sup></a> Making a fresh copy using <code>slice(0)</code> should get you better performance. (Well, it&#8217;s worked for me, but I make no promises.)</p>
<p><a name="jsarraysII-note-2" href="#jsarraysII-ref-2"><sup>2</sup></a> There are really four cases, but the fourth one (cleared arrays in IE8) shows <em>very</em> slow growth in runtime. Also note that the numbers suggest that Chrome&#8217;s performance <em>improves</em> slightly as array size increases. This may be an artifact of the benchmark.</p>
<p><a name="jsarraysII-note-3" href="#jsarraysII-ref-3"><sup>3</sup></a> Density and hit ratio can be covariant, but here they aren&#8217;t. That is, these tests were designed so that, as long as the density was under 100%, the hit ratio could vary independently.</div>
]]></content:encoded>
			<wfw:commentRss>http://www.outofwhatbox.com/blog/2009/12/javascript-array-performance-and-why-it-matters/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>JavaScript Array Performance: Initialize to Optimize</title>
		<link>http://www.outofwhatbox.com/blog/2009/11/javascript-array-performance-initialize-to-optimize/</link>
		<comments>http://www.outofwhatbox.com/blog/2009/11/javascript-array-performance-initialize-to-optimize/#comments</comments>
		<pubDate>Tue, 17 Nov 2009 16:39:22 +0000</pubDate>
		<dc:creator>Dan Breslau</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[JavaScript arrays]]></category>
		<category><![CDATA[JavaScript performance]]></category>

		<guid isPermaLink="false">http://www.outofwhatbox.com/blog/?p=584</guid>
		<description><![CDATA[The JavaScript interpreters in the most popular browsers distinguish between sparse and dense arrays. Hence, you may get more  "array-like" performance if you initialize an array before using it. But this trades memory for speed, so it may not always be the best choice.]]></description>
			<content:encoded><![CDATA[<p>After delving into the issue of <a href="http://www.outofwhatbox.com/blog/2009/11/trimming-trim-via-razing-arrays-javascript/">JavaScript array performance</a>, I came upon a <a href="http://blogs.msdn.com/jscript/archive/2008/04/08/performance-optimization-of-arrays-part-ii.aspx">pair of</a> <a href="http://blogs.msdn.com/jscript/archive/2008/03/25/performance-optimization-of-arrays-part-i.aspx">blog entries</a> on MSDN addressing the topic. These posts describe situations where the then-forthcoming IE8 could provide more performant arrays. The blog also partially confirms, and partially refutes, my thoughts on how JavaScript interpreters handle arrays. The blog&#8217;s focus, of course, is the JScript engine in IE, but the advice that it offers seems to work well with other major browsers.</p>
<p>The blog confirms that IE&#8217;s JavaScript interpreter manages arrays using a nonlinear structure, essentially a hash table. I&#8217;d guessed at this after seeing lower performance in <code><a href="http://www.outofwhatbox.com/blog/2009/11/trimming-trim-via-razing-arrays-javascript/">trimOOWB</a></code> when its lookup table was implemented as a large, and sparse, array. But contrary to my guess, this isn&#8217;t about avoiding re-allocation bottlenecks. It&#8217;s for dealing with <a href="http://www.dragonthoughts.biz/technical/sparsearray.html">sparse arrays</a> without consuming unreasonable amounts of memory<sup><a href="#jsarray-init-note-1" name="jsarray-init-ref-1">1</a></sup>. (I&#8217;m feeling a little sheepish about this: Even though I&#8217;d noted the sparseness of the lookup table, I hadn&#8217;t made the connection. In fact, I&#8217;d been somewhat dismissive of that possibility. <a href="http://www.outofwhatbox.com/blog/2009/04/how_to_make_mistakes/">Live and learn</a>.)</p>
<p>The blog also says that as of IE8, the JScript engine has heuristics for determining if an array is &#8220;dense&#8221;. It implements a dense array with a linear, array-like index in addition to its standard hash-like data structure; this index can make random access into the array much faster. The blog indicates that IE8 considers an array to be dense if <strong>either</strong> of the following conditions is true:</p>
<ul>
<li>You construct the array with an explicit size, and you don&#8217;t grow the array past that initial size.</li>
<li>After creating the array, you initialize a continuous range of indices, starting from 0, up to and including the highest index that you expect to use. You must do this before writing into random indices within the array.<sup><a href="#jsarray-init-note-2" name="jsarray-init-ref-2">2</a></sup></li>
</ul>
<p>As the writer says, using either of these two techniques should <em>ensure</em> that the array heuristics in IE 8 will treat your array as a dense array. The interpreter is free to decide to treat other arrays as dense, too. However, the testing I&#8217;ve done suggests that it&#8217;s not quite as simple as this. Contrary to the blog&#8217;s guidelines, I found that:</p>
<ul>
<li>Creating the array with an explicit size (whether or not followed by initializing the elements) <em><strong>had no measurable impact</strong></em> on the speed of the <code>trim</code> method.
</li>
<li>Initializing the lookup table&#8217;s full range of 12,289 elements (the vast majority of which are not whitespace) <em><strong>did</strong></em> improve performance.
</li>
</ul>
<p>This finding is specific to the trim method, and so these results <strong>should not be used as general performance guidelines.</strong> The usage pattern for a particular array can greatly affect its performance profile. I&#8217;ve found unrelated cases where specifying the array&#8217;s size could help <em><strong>or</strong></em> hurt performance. (I&#8217;ll write more about this in my next post.)</p>
<p>Following up on these hints led to a <a href="#jsarray-trim18-implementation">new version of </a><a href="#jsarray-trim18-implementation"><code>trim</code></a> that&#8217;s simpler and faster than my previous effort. This version is actually more closely related to the <code><a href="http://yesudeep.wordpress.com/2009/07/31/even-faster-string-prototype-trim-implementation-in-javascript/">trim17</a></code> method from Yesudeep Mangalapilly than it is to <code>trimOOWB</code>. Hence I&#8217;ve named this newer one <code>trim18</code> to reaffirm its heritage. (In Steve Levithan&#8217;s original post on <a href="http://blog.stevenlevithan.com/archives/faster-trim-javascript">JavaScript trim methods</a>, he assigned numbers to each of the <code>trim</code> implementations that he examined. Yesudeep took up that naming scheme, and now I&#8217;m doing so as well.)</p>
<div class="oowbbtw">
<h3>An Intermediary Thought</h3>
<p>Remember that premature optimization is folly, and all optimization has its costs. In this case, we&#8217;re buying performance by fully initializing a 12K JavaScript array. If the interpreter stores this using a hash table <em>as well as</em> an array, then the table will likely consume over 36K of memory. Is the benefit worth the cost? It could be, especially if we&#8217;re not running on a cell phone. But <strong>please</strong> don&#8217;t take away from this that you should initialize <strong>every</strong> array that you create. That would ultimately be self-defeating: One of the worst things you can do for performance is to consume more memory than you really need.</div>
<h2>Performance</h2>
<p>Since the last post, I&#8217;ve revised the benchmark for better precision. The structure is the same—both benchmarks call the three <code>trim</code> methods repeatedly with a fixed set of input data—but in the newer benchmark, the input strings are much longer, and the number of iterations is lower. This should yield more precise measurements of execution time. All the same, these results should be used with care; as is often said in the U.S.A, your mileage will vary. </p>
<p>The benchmark results are shown below. Please remember that these tables are not directly comparable to the numbers in my previous post.</p>
<h3>ASCII data (only spaces and tabs used for whitespace)</h3>
<table style="" border="0" cellspacing="0" cellpadding="2" >
<tbody>
<tr class="oowbfirstRow">
<th style="text-align: right;"></th>
<th style="text-align: right;" ><strong><code>trim17</code></strong></th>
<th style="text-align: right;" ><strong><code>trimOOWB</code></strong></th>
<th style="text-align: right;" ><strong><code>% saved vs. trim17</code></strong></th>
<th style="text-align: right;" ><strong><code>trim18</code></strong></th>
<th style="text-align: right;" ><strong><code>% saved vs. trim17</code></strong></th>
</tr>
<tr>
<td><strong>Internet Explorer 8</strong></td>
<td style="text-align: right;">74,453</td>
<td style="text-align: right;">69,609</td>
<td style="text-align: right;">6.5</td>
<td style="text-align: right;" >69,922</td>
<td style="text-align: right;" >6.1</td>
</tr>
<tr>
<td><strong>Firefox 3.5</strong></td>
<td style="text-align: right;">6,776</td>
<td style="text-align: right;">3,732</td>
<td style="text-align: right;">44.9</td>
<td style="text-align: right;" >3,003</td>
<td style="text-align: right;" >55.7</td>
</tr>
<tr>
<td><strong>Google Chrome 3.0</strong></td>
<td style="text-align: right;">2,530</td>
<td style="text-align: right;">824</td>
<td style="text-align: right;">67.4</td>
<td style="text-align: right;" >754</td>
<td style="text-align: right;" >70.2</td>
</tr>
</tbody>
</table>
<h3>Unicode data (using all ASCII and Unicode whitespace characters)</h3>
<table style="" border="0" cellspacing="0" cellpadding="2" >
<tbody>
<tr class="oowbfirstRow">
<th style="text-align: right;"></th>
<th style="text-align: right;" ><strong><code>trim17</code></strong></th>
<th style="text-align: right;" ><strong><code>trimOOWB</code></strong></th>
<th style="text-align: right;" ><strong><code>% saved vs. trim17</code></strong></th>
<th style="text-align: right;" ><strong><code>trim18</code></strong></th>
<th style="text-align: right;" ><strong><code>% saved vs. trim17</code></strong></th>
</tr>
<tr>
<td><strong>Internet Explorer 8</strong></td>
<td style="text-align: right;">76,188</td>
<td style="text-align: right;">74,468</td>
<td style="text-align: right;">2.3</td>
<td style="text-align: right;" >72,484</td>
<td style="text-align: right;" >4.9</td>
</tr>
<tr>
<td><strong>Firefox 3.5</strong></td>
<td style="text-align: right;">6,779</td>
<td style="text-align: right;">5,025</td>
<td style="text-align: right;">25.6</td>
<td style="text-align: right;" >3,029</td>
<td style="text-align: right;" >55.3</td>
</tr>
<tr>
<td><strong>Google Chrome 3.0</strong></td>
<td style="text-align: right;">2,780</td>
<td style="text-align: right;">940</td>
<td style="text-align: right;">66.2</td>
<td style="text-align: right;" >810</td>
<td style="text-align: right;" >70.9</td>
</tr>
</tbody>
</table>
<p><a name="jsarray-trim18-implementation"><br />
<h2>trim18 implementation</h2>
<p></a><br />
<em>I left the explicit size in the array constructor call, even though I&#8217;d found no benefit from using it. It seems unlikely to cause any harm, and there may be environments where this method&#8217;s performance might benefit from it.</em></p>
<pre class="brush: jscript;">
var trim18 = (function() {

    var tableSize = 0x3000 + 1;
    var whiteSpace = new Array(tableSize);

    // Initialize the array elements before populating the data.
    // (This may help performance, by hinting to the interpreter that
    //  the array should not be managed as a sparse array.)

    for (var i = 0; i &lt; tableSize; i++) {
        whiteSpace[i] = false;
    }

    whiteSpace[0x0009] = true;  whiteSpace[0x000a] = true;
    whiteSpace[0x000b] = true;  whiteSpace[0x000c] = true;
    whiteSpace[0x000d] = true;  whiteSpace[0x0020] = true;
    whiteSpace[0x0085] = true;  whiteSpace[0x00a0] = true;
    whiteSpace[0x1680] = true;  whiteSpace[0x180e] = true;
    whiteSpace[0x2000] = true;  whiteSpace[0x2001] = true;
    whiteSpace[0x2002] = true;  whiteSpace[0x2003] = true;
    whiteSpace[0x2004] = true;  whiteSpace[0x2005] = true;
    whiteSpace[0x2006] = true;  whiteSpace[0x2007] = true;
    whiteSpace[0x2008] = true;  whiteSpace[0x2009] = true;
    whiteSpace[0x200a] = true;  whiteSpace[0x200b] = true;
    whiteSpace[0x2028] = true;  whiteSpace[0x2029] = true;
    whiteSpace[0x202f] = true;  whiteSpace[0x205f] = true;
    whiteSpace[0x3000] = true;

    function trim18(str) {
        var len = str.length, ws = whiteSpace, i = 0;
        while (ws[str.charCodeAt(--len)]);
        if (++len){
            while (ws[str.charCodeAt(i)]){ ++i; }
        }
        return str.substring(i, len);
    }

    return trim18;
})();
</pre>
<hr />
<div><sup><a name="jsarray-init-note-1" href="#jsarray-init-ref-1">1</a></sup> It&#8217;s also relevant that <em>every</em> JavaScript object needs a hash table to manage properties. Hence sparse arrays can be implemented easily by using this hash table for the same purpose. (Considering the design of JavaScript&#8217;s <code>for...in</code> loop statement, it looks as if the language designers intended this.)</div>
<div><sup><a name="jsarray-init-note-2" href="#jsarray-init-ref-2">2</a></sup> That is, you would need to initialize the array if you otherwise won&#8217;t be populating all of its elements, or if you won&#8217;t be populating them in strict order starting from 0. On the other hand, if your script would normally add data to the array starting from index 0 and working up from there, leaving no gaps, then you&#8217;re already squared away with IE8&#8242;s heuristics.</div>
]]></content:encoded>
			<wfw:commentRss>http://www.outofwhatbox.com/blog/2009/11/javascript-array-performance-initialize-to-optimize/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

