466
|
Chapter 12, Miscellany
#93 Code Models That Don’t Block
HACK
Models Aren’t Always Dumb
Adapt Example 12-8 to create AWTBlockModels.java. To illustrate the load-
ing, this hack has a
JProgressBar that you need to declare before the con-
structor, and which you add at the bottom of
initMainLayout( )
:
progressBar = new JProgressBar (0, 100);
getContentPane( ).add (progressBar, BorderLayout.SOUTH);
The strategy in this hack is to make the JTextArea’s model responsible for its
own threaded loading, so get rid of the
loadURL( ) method. That code will
move to the models, which subclass
javax.swing.text.PlainDocument. First,
change the actions to use these documents:
class BlockingLoadAction extends AbstractAction {
public void actionPerformed (ActionEvent e) {
BlockingURLDocument bud =
new BlockingURLDocument (urlField.getText( ));
progressBar.setEnabled (true);
progressBar.setValue (0);
contentArea.setDocument (bud);
progressBar.setValue (100);
}
}
class NonBlockingLoadAction extends AbstractAction {
public void actionPerformed (ActionEvent e) {
NonBlockingURLDocument nbud =
new NonBlockingURLDocument (urlField.getText( ));
contentArea.setDocument (nbud);
// makeProgressBarUpdaterFor (nbud);
}
}
The actions are pretty much the same, except for the fact that the blocking
version sets the
JProgressBar before and after setting the JTextArea’s docu-
ment. Why doesn’t the non-blocking action touch the progress bar? We’ll
get back to that.
Example 12-9 is the blocking document, so named because it loads all the
data from the URL in its constructor, which will cause the
Action’s construc-
tor to block until everything is loaded.
Example 12-9. A document that will block while loading a URL
class BlockingURLDocument extends PlainDocument {
public BlockingURLDocument (String urlString) {
super( );
try {
URL url = new URL (urlField.getText( ));
BufferedReader in =
new BufferedReader (
new InputStreamReader (url.openStream( )));
Code Models That Don’t Block #93
Chapter 12, Miscellany
|
467
HACK
The implementation here is pretty simple: read bytes and stuff them into a
StringBuffer until the stream is exhausted, then stuff them into the Document
with insertString( ). This makes for clean code because the Document loads
its own data. The downside is that the caller, which is on the event-dispatch
thread, blocks until all the data is read and inserted into the
Document. And,
of course, a blocked event-dispatch thread means nothing in your GUI gets
repainted, mouse events aren’t processed…basically, nobody’s happy.
A more enlightened approach requires a
Document to load its own data and
yet not block the caller. In other words, it will need to return almost imme-
diately, thread whatever work doesn’t need to be on event dispatch, and use
a worker thread to do the Swing work in a thread-safe manner.
Example 12-10 is what a non-blocking document looks like.
StringBuffer sbuf = new StringBuffer( );
char[] buffy = new char [16 * 1024];
int bytesRead = 0;
while ((bytesRead = in.read (buffy, 0, buffy.length)) > -1) {
sbuf.append (buffy, 0, bytesRead);
// if your net connection is too fast to see blocking
// add the following here
// Thread.sleep (1000);
}
remove (0, getLength( ));
insertString (0, sbuf.toString( ), null);
} catch (Exception e) {
CharArrayWriter writer = new CharArrayWriter( );
e.printStackTrace (new PrintWriter (writer));
try {
remove (0, getLength( ));
insertString (0, writer.toString( ), null);
} catch (Exception e2) {e2.printStackTrace( );}
}
}
}
Example 12-10. Document that will not block on URL loading
class NonBlockingURLDocument extends PlainDocument
implements Runnable {
protected int length = -1;
protected int totalBytesRead = 0;
protected String urlString;
protected Thread readThread;
public NonBlockingURLDocument (String urlString) {
super( );
this.urlString = urlString;
Example 12-9. A document that will block while loading a URL (continued)

Get Swing Hacks now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.