⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 july01_ericg.txt

📁 TechTips j2me的常用技巧. 网络功能
💻 TXT
📖 第 1 页 / 共 2 页
字号:

 J 2 M E    T  E  C  H    T  I  P  S

                      TIPS, TECHNIQUES, AND SAMPLE CODE


WELCOME to the Java Developer Connection(sm) (JDC)
Java(tm) 2 Platform, Micro Edition (J2ME(tm)) 
Tech Tips, for July 25, 2001. This issue covers:

     * Drawing Flicker-Free Graphics with the MIDP
     * Parsing XML in CLDC-based Profiles
         
The J2ME Tech Tips are written by Eric Giguere
(http://www.ericgiguere.com), an engineer at iAnywhere 
Solutions, inc. Eric is the author of the book "Java 2 Micro
Edition: Professional Developer's Guide" and co-author of the 
upcoming "Mobile Information Device Profile for Java 2 Micro 
Edition," both books in John Wiley & Sons' Professional 
Developer's Guide series."

You can view this issue of the J2ME Tech Tips on the Web at
http://java.sun.com/jdc/J2METechTips/2001/tt0725.html

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
DRAWING FLICKER-FREE GRAPHICS WITH THE MIDP

The Mobile Information Device Profile (MIDP) defines low-level 
user interface classes for drawing directly on a device's 
display. The March 19, 2001 J2ME Tech Tip "Using the MIDP 
Low-Level User Interface API" 
( http://java.sun.com/jdc/J2METechTips/2001/tt0319.html#tip2 )
covered how to use these classes to do basic drawing. Today's
Tech Tip builds on that foundation and discusses how to use
double buffering to draw flicker-free graphics.

The term "double buffering" refers to a common technique used in 
computer graphics. If you consider a device's display to be a 
memory buffer into which drawing primitives write (the drawing
primitives are the basic drawing methods such as drawLine and 
drawArc), with double buffering you draw into a second, 
offscreen memory buffer and then copy the entire contents of the 
second buffer into the display buffer. Copying from one buffer to 
another is a very fast operation on most devices, so that the 
display changes almost instantaneously. By comparison, directly 
drawing to a display sometimes causes users to see a flicker, as
individual parts of the display are updated. Double buffering 
avoids this flickering by combining multiple individual drawing 
operations (that is, those to the offscreen buffer) into a single 
copy operation to the display buffer.

It's easy to do double buffering in the context of the Mobile 
Information Device Profile. You can use the Image class (all 
classes mentioned in this tip are in the javax.microedition.lcdui 
package) to create an offscreen memory buffer. You use the 
Graphics class, the same class used to draw on the display, to 
draw to the offscreen buffer. You also use the Graphics class to 
copy the contents of the offscreen buffer onto the display. 
Double buffering is implemented with just a few adjustments to 
your painting routines. 

The first thing you need to do is determine if double buffering 
is even necessary. On some implementations, double buffering is 
automatically supported by the system. In other words, when the 
system calls your Canvas object's paint method, the Graphics 
object passed to the method is that of an offscreen buffer 
managed by the system; the object is not from the display buffer. 
The system then takes care of copying the offscreen buffer to the 
display. Checking if double buffering is supported is easy -- all 
you do is call the isDoubleBuffered method, like this:

public class MyCanvas extends Canvas {

    private Image offscreen = null;
    private int   height;
    private int   width;
        
    public MyCanvas(){
        height = getHeight();
        width = getWidth();

        if( !isDoubleBuffered() ){
            offscreen = Image.createImage( width, height );
        }
                
        ..... // other initialization as appropriate
    }
        
    ...... // other code, including paint method
}
        
Notice how if isDoubleBuffered returns false, the constructor 
creates an offscreen buffer of the same width and height as the 
canvas. If the display is double buffered, isDoubleBuffered
returns true and the offscreen buffer is not created.

The offscreen buffer is created by calling one of the 
Image.createImage methods. There are four such methods, each of
which does the following:

o Loads images from the MIDlet suite's JAR file
o Makes a copy of an existing image
o Creates an image from raw binary data
o Creates a blank image of a specific height and width

The last of these createImage methods is the one used for double 
buffering. The other three createImage methods cannot be used for 
double buffering because they create images that are immutable, 
that is, images that cannot be changed. Only the last createImage
method, the one that takes width and height parameters, can be 
used to create mutable images. Once you have a mutable image, you 
can call its getGraphics method to obtain a Graphics object that 
you can use to draw into the image's buffer, just like drawing on 
the display.

Of course, the real work occurs in the paint method. A simple
paint routine might look like this:

protected void paint( Graphics g ){
    g.setColor( 255, 255, 255 );
    g.fillRect( 0, 0, width, height );
}

Most paint routines are much more complicated, especially if 
animation is involved. To implement double buffering, add a few 
lines of code before and after the existing painting code, like 
this:

protected void paint( Graphics g ){
    Graphics saved = g;
        
    if( offscreen != null ){
        g = offscreen.getGraphics();
    }
    
    g.setColor( 255, 255, 255 );
    g.fillRect( 0, 0, width, height );
        
    if( g != saved ){
        saved.drawImage( offscreen, 0, 0,
                         Graphics.LEFT | Graphics.TOP );
    }
}

Basically all you're doing is obtaining the Graphics object for 
the offscreen buffer and using it to do the painting. At the 
end, the entire content of the offscreen buffer is copied to 
the display. Notice that this is done only if double buffering is
not automatically supported. You can easily determine this by 
checking to see if an offscreen buffer has been allocated. If
double buffering is automatically supported, you simply draw
directly onto the display as usual. 

Double buffering is not without its price. If you're only making 
small changes to the display, it might be slower to use double 
buffering. In addition, image copying isn't very fast on some 
systems; on those systems flicker can can happen even with double 
buffering. And there is a memory penalty to pay for double 
buffering: the offscreen memory buffer can consume a large 
amount of memory, memory that you might not be able to spare.
Keep the number of offscreen buffers to a minimum. You could free 
the offscreen buffer whenever the canvas is hidden, for example, 
and allocate it again when the canvas is shown again. This is easy 
to do by overriding the canvas' hideNotify and showNotify methods.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PARSING XML IN CLDC-BASED PROFILES

XML, the Extensible Markup Language, is a portable, text-based 
way of representing structured data. More and more applications 
are using XML to exchange information, and at some point your 
CLDC-based applications (those that run on CLDC-based profiles 
such as the Mobile Information Device Profile) are going to need 
to process XML documents. Over time, even HTML pages will likely
migrate to an XML-based format called XHTML. This means that 
fetching a page from a web server in order to extract data from 
it will require XML parsing technology.

Finding a Java-based XML parser is not hard, especially since 
there are several XML-based initiatives being defined as part of 
the Java Community Process. However, most of these parsers do not
work in the limited environment provided by the CLDC. The parsers 
either use too much memory or use J2SE(tm) classes that simply 
are not available in the CLDC. There are two open source XML 
parsers that work well with the CLDC, however: kXML and NanoXML.  
Their strengths are different -- this tip discusses both of them 
and leaves it up to you to decide which best fits your 
application's requirements. You should also consider alternatives
to XML, though, because XML documents are very verbose. If
you have control over the server, it might make more sense to
use your own binary format for exchanging data. This is fairly
easy to do if the Java-based client is talking to a Java-based
server application. In this case, use the DataInputStream and 
DataOutputStream classes to read and write data in a portable 
way.

There are two basic types of XML parsers: validating and 
non-validating. A validating parser checks an XML document 
against a document type definition or schema to ensure that the 
contents of the document are what the application expects. This 
requires work and slows down the processing. A non-validating 
parser skips this step and just ensures that an XML document is 
well-formed, in other words, that it conforms to the general 
rules that all XML documents must follow. Both kXML and NanoXML 
are non-validating parsers.

XML parsers can also be classified by how they process and 
represent an XML document. NanoXML is a single-step parser. Given 
a document, NanoXML parses it in a single operation and returns
the document as a tree of objects. kXML, by comparison, is an 
incremental parser: it parses documents a piece at a time. There 
are advantages and disadvantages to either approach. If you're 
dealing with large documents, the single-step approach uses 
much more memory because the entire document is held in memory.
But a single-step approach might make the most sense if you need 
to traverse through the document multiple times. The multi-step 
approach can easily deal with large documents, but you have do 
more bookkeeping to track of where you are in the document.

To use kXML, download the kXML source code from 
http://www.kxml.org, and include the kXML classes with your 
application. Not all the classes are required, so you might want 
to just download the ZIP file that contains the minimal 
implementation of kXML. After you install the files, add the
following import statements to your application:

import org.kxml.*;
import org.kxml.parser.*;

When you're ready to parse a document, create an instance of the 
XmlParser class, which takes a character stream as its only 
argument:

try {
    Reader    r = .....;
    XmlParser parser = new XmlParser( r );
}
catch( java.io.IOException e ){
    // handle exception....
}

If your document is stored as a string, for example, you can read 
it by converting the string to a byte array and then combining 
InputStreamReader and ByteArrayInputStream:

// Read from string (exception handling omitted)
String    xml = "<a>some xml</a>";
ByteArrayInputStream bin = 
            new ByteArrayInputStream( xml.getBytes() );
XmlParser parser = new XmlParser( new InputStreamReader( bin ) );

The more likely scenario, however, is to receive a document over 
the network, for example,  with the CLDC's Generic Connection 
Framework (GCF). You do this using the MIDP's built-in support 
for the HTTP protocol. You then take the input stream returned
by the GCF and convert it to a character stream:

// Read from web (exception handling omitted)
HttpConnection    conn = .....;
InputStreamReader doc = 
         new InputStreamReader( conn.openInputStream() );
XmlParser parser = new XmlParser( doc );

After the parser has been created, you call its read method to 
read the individual pieces of the document. The read method 
returns a ParseEvent object for each element of the document:

try {
    boolean keepParsing = true;
        
    while( keepParsing ){
        ParseEvent event = parser.read();
 
        switch( event.getType() ){
            case Xml.START_TAG:
                ..... // handle start of an XML tag
                break;
            case Xml.END_TAG:
                ..... // handle end of an XML tag
                break;
            case Xml.TEXT:
                ..... // handle text within a tag
                break;
            case Xml.WHITESPACE:
                ..... // handle whitespace
                break;
            case Xml.COMMENT:
                ..... // handle comment
                break;
            case Xml.PROCESSING_INSTRUCTION:
                ..... // handle XML PI
                break;
            case Xml.DOCTYPE:
                ..... // handle XML doctype
                break;
            case Xml.END_DOCUMENT:
                ..... // end of document;
                keepParsing = false;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -