這篇文章將教你學(xué)習(xí)在MIDlet中怎樣使用線程訪問網(wǎng)絡(luò)鏈接。
沒有了多線程,MIDlet在等待網(wǎng)絡(luò)響應(yīng)時會有一個網(wǎng)絡(luò)阻塞。
在現(xiàn)實中,用戶希望即使是有個網(wǎng)絡(luò)鏈接在被處理,在此過程中程序也能繼續(xù)運行。
第一階段 開始之前
我們用單線程MIDlet訪問網(wǎng)絡(luò),從它出現(xiàn)的問題上來開始這個話題。這樣,你會學(xué)習(xí)到關(guān)于線程你需要了解什么,和使用線程的兩種方式。
在最后一個階段,你將建立一個多線程的MIDlet。這個程序?qū)槟銖木W(wǎng)絡(luò)上下載一張圖片。一旦鏈接被初始,進(jìn)行著下載,用戶會返回到程序主界面。即使是下載在進(jìn)行,用戶也可以操作界面,包括鍵入一個新的URL地址。下載完畢后,MIDlet會啟動一個提示對話框,提示用戶下載的結(jié)果,是完成還是失敗,然后再顯示下載的圖片。
通過這篇文章,你應(yīng)該對多線程重要性有了一個深刻的理解并有堅實的基礎(chǔ)寫出自己的多線程MIDlet。
準(zhǔn)備資料:
你需要兩個軟件工具來完成該文章的實現(xiàn):
JDK JDK提供了JAVA的源代碼編譯器和生成JAR包的工具。如果使用WT2.2你需要下載JDK1.4或最新的版本。
WTK WTK是一個J2me的集成開發(fā)環(huán)境。WTK下載包包含了一個IDE,當(dāng)然也有創(chuàng)建MIDlet的庫。
安裝軟件
這里不在贅述。
第二階段 單線程MIDlet
概述
從手邊的問題開始,開起來不錯,也就是說,需要知道為什么我們在訪問網(wǎng)絡(luò)的時候需要采用多線程。接下來你就會看到多線程的重要性。
這個MIDlet顯示了一個儲存在遠(yuǎn)方服務(wù)器的報價。這里有九個報價可以獲得。用戶輸入一到九的數(shù)字去檢索和顯示其中一個報價。MIDlet程序的目的就是來顯示在獲得網(wǎng)絡(luò)請求時是怎么阻塞的。
讓我們來開始創(chuàng)建一個project。你將在程序運行時看到彈出屏幕顯示問題出在哪里。
創(chuàng)建MIDlet
文章中所有的MIDlet的建立,請遵循下面的步驟來使用wtk:
1.創(chuàng)建工程
2.編寫代碼
3.編譯代碼
4.運行MIDlet
下面我們馬上來創(chuàng)建一個project。
創(chuàng)建工程
1. 點擊New Project。
2. 鍵入工程名和MIDlet名
3. 點擊Create Project。
編寫代碼
把下面的代碼復(fù)制粘貼到文本編輯器中。
GetQuote.java
/*--------------------------------------------------
* GetQuote.java
*-------------------------------------------------*/
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.io.*;
import java.io.*;
public class GetQuote extends MIDlet implements CommandListener
{
private Display display; // Reference to Display object
private Form fmMain; // The main form
private Command cmRetrieve; // Command to get quote
private Command cmExit; // Command to exit MIDlet
private TextField tfQuote; // Phone number
private String url = "http://www.corej2me.com/ibm/quotes2.php";
/*--------------------------------------------------
* Constructor
*-------------------------------------------------*/
public GetQuote()
{
display = Display.getDisplay(this);
// Create commands
cmRetrieve = new Command("Retrieve", Command.SCREEN, 1);
cmExit = new Command("Exit", Command.EXIT, 1);
// Textfield to prompt for quote number
tfQuote = new TextField("Get quote between 1 and 9:", "", 1,
TextField.NUMERIC);
// Create Form, add Commands & textfield, listen for events
fmMain = new Form("Quote MIDlet");
fmMain.addCommand(cmExit);
fmMain.addCommand(cmRetrieve);
fmMain.append(tfQuote);
fmMain.setCommandListener(this);
}
// Called by application manager to start the MIDlet.
public void startApp()
{
display.setCurrent(fmMain);
}
public void pauseApp()
{ }
public void destroyApp(boolean unconditional)
{ }
public void commandAction(Command c, Displayable s)
{
if (c == cmRetrieve)
{
try
{
// Connect to the server, passing in request quote
String str = connect(tfQuote.getString());
fmMain.append("Quote: " + str);
}
catch (Exception e)
{
System.out.println("Unable to get quote " + e.toString());
}
}
else if (c == cmExit)
{
destroyApp(false);
notifyDestroyed();
}
}
/*--------------------------------------------------
* Connect to the remote server, run the php script
* and return the request quote.
*-------------------------------------------------*/
private String connect(String number) throws IOException
{
InputStream iStrm = null;
ByteArrayOutputStream bStrm = null;
HttpConnection http = null;
String quote_string = null;
try
{
// Create the connection
http = (HttpConnection) Connector.open(url + "?number=" + number);
System.out.println(url + "?number=" + number);
//----------------
// Client Request
//----------------
// 1) Send request method
http.setRequestMethod(HttpConnection.GET);
// If you experience connection/IO problems, try
// removing the comment from the following line
//http.setRequestProperty("Connection", "close");
// 2) Send header information
// 3) Send body/data - No data for this request
//----------------
// Server Response
//----------------
// 1) Get status Line
if (http.getResponseCode() == HttpConnection.HTTP_OK)
{
// 2) Get header information
// 3) Get data from server
iStrm = http.openInputStream();
int length = (int) http.getLength();
int ch;
bStrm = new ByteArrayOutputStream();
while ((ch = iStrm.read()) != -1)
{
// Ignore any carriage returns/linefeeds
if (ch != 10 && ch != 13)
bStrm.write(ch);
}
quote_string = new String(bStrm.toByteArray());
}
}
finally
{
// Clean up
if (iStrm != null)
iStrm.close();
if (bStrm != null)
bStrm.close();
if (http != null)
http.close();
}
return quote_string;
}
}
保存代碼
在你創(chuàng)建工程的時候,WTK就給你提供了一個工程路徑。你只需要把你的代碼拷貝到目錄下。
下面的階段里我們將詳細(xì)復(fù)習(xí)代碼的細(xì)節(jié)部分。
編寫PHP
現(xiàn)在,寫一個PHP來處理用戶輸入的數(shù)字,返回一個適當(dāng)?shù)膱髢r信息。把下面的代碼粘貼到文本編輯器。
<?php
$quotes[] = "I think there is a world market for maybe five computers.
Thomas Watson.";
$quotes[] = "The answer to life's problems aren't at the bottom of a
bottle, they're on TV! Homer Simpson.";
$quotes[] = "I love
Dan Quayle.";
$quotes[] = "640K ought to be enough for anybody. Bill Gates.";
$quotes[] = "Some people are afraid of heights. Not me, I'm afraid
of widths. Steven Wright";
$quotes[] = "Start every day off with a smile and get it over
with. W. C. Fields ";
$quotes[] = "I am not a vegetarian because I love animals;
I am a vegetarian because I hate plants. A. Whitney Brown";
$quotes[] = "A conclusion is simply the place where someone got
tired of thinking. Arthur Block";
$quotes[] = "A rich man's joke is always funny. Proverb.";
//-------------------------------------------------------
// It all starts here.
// Get requested quote number parameter passed in the url
//-------------------------------------------------------
if (isset($_GET))
{
$quote_num = $_GET["number"];
}
// Create a delay to make the problem of no-threads more obvious
sleep(5);
// User entered a quote number
if ($quote_num > 0)
{
// Decrement the quote requested because our array is zero based
echo $quotes[$quote_num - 1];
}
else // User did NOT enter a quote number, return a random quote
{
// Initialize random number generator
srand((double)microtime() * 1000000);
// Get a random value that is between 0 and the length of our array
(minus 1) rand_num = rand(0, (count($quotes) - 1));
// Echo the quote from the array
echo $quotes[$rand_num];
}
?>
保存PHP代碼
把這個PHP保存為quotes2.php,放置在web服務(wù)器根目錄下。
關(guān)于PHP代碼的解釋我們會在下面安排。
編譯代碼
點擊Build去編譯,并把MIDlet打包。
點擊RUN來執(zhí)行
執(zhí)行工程
開始啟動MIDlet
點擊Launch
在程序執(zhí)行過程中,我將顯示問題出現(xiàn)在哪里。下面是運行的步驟演示。
當(dāng)用戶沒有輸入任何東西就提交的時候,PHP程序會返回一個隨機(jī)的信息,下面的圖片就是在沒有輸入的情況下出現(xiàn)的結(jié)果:
代碼回顧:commandAction()
讓我們來簡短地回顧一下事件是怎么被處理和鏈接PHP服務(wù)器的細(xì)節(jié)部分。下面就是處理命令的程序代碼。在用戶傳入自己想要的報價信息的時候,connect()方法被調(diào)用了。
public void commandAction(Command c, Displayable s)
{
if (c == cmRetrieve)
{
try
{
// Connect to the server, passing in request quote
String str = connect(tfQuote.getString());
fmMain.append("Quote: " + str);
}
catch (Exception e)
{
System.out.println("Unable to get quote " + e.toString());
}
}
else if (c == cmExit)
{
destroyApp(false);
notifyDestroyed();
}
}
在connect()方法的核心就是鏈接到服務(wù)器并處理服務(wù)器反饋的信息。上面的代碼中,當(dāng)接受到服務(wù)器的響應(yīng)后,相應(yīng)的報價信息已經(jīng)被更新了。
代碼回顧:connect()
如果你做過很多J2ME鏈接網(wǎng)絡(luò)的程序,很多代碼看起來都很相似。注意我是怎么樣把用戶輸入的請求編輯到URL上的。例如,如果用戶輸入了5,URL就會變成:
http://www.corej2me.com/ibm/quotes2.php?number=5。用這個URL,我簡單地打開鏈接,指定提交方式,等待反饋結(jié)果。
private String connect(String number) throws IOException
{
InputStream iStrm = null;
ByteArrayOutputStream bStrm = null;
HttpConnection http = null;
String quote_string = null;
try
{
// Create the connection
http = (HttpConnection) Connector.open(url + "?number=" + number);
System.out.println(url + "?number=" + number);
//----------------
// Client Request
//----------------
// 1) Send request method
http.setRequestMethod(HttpConnection.GET);
// If you experience connection/IO problems, try
// removing the comment from the following line
//http.setRequestProperty("Connection", "close");
// 2) Send header information
// 3) Send body/data - No data for this request
//----------------
// Server Response
//----------------
// 1) Get status Line
if (http.getResponseCode() == HttpConnection.HTTP_OK)
{
// 2) Get header information
// 3) Get data from server
iStrm = http.openInputStream();
int length = (int) http.getLength();
int ch;
bStrm = new ByteArrayOutputStream();
while ((ch = iStrm.read()) != -1)
{
// Ignore any carriage returns/linefeeds
if (ch != 10 && ch != 13)
bStrm.write(ch);
}
quote_string = new String(bStrm.toByteArray());
}
}
finally
{
// Clean up
if (iStrm != null)
iStrm.close();
if (bStrm != null)
bStrm.close();
if (http != null)
http.close();
}
return quote_string;
}
一旦服務(wù)器響應(yīng),我就檢查鏈接請求是否正確。如果正確,我就把服務(wù)器響應(yīng)讀出來并存儲到變量quote_string。在connect()方法的末尾,我把這個變量的值返回。
這就是MIDlet程序的執(zhí)行過程,你想要得到報價信息,把請求發(fā)送給服務(wù)器,然后讀取顯示服務(wù)器的響應(yīng)結(jié)果?,F(xiàn)在只剩下PHP代碼是怎么處理請求報價還沒有說了。下面我們就來看看PHP代碼:
代碼回顧: php
為了生成報價信息,我簡單地創(chuàng)建了一個數(shù)組并把每一個賦值為一個報價信息。一個更健壯的方式是從文件中讀取報價信息。即使不太難,我想我們還是把焦點放在如何完成手邊的任務(wù)--------怎么樣把MIDlet中參數(shù)傳到服務(wù)器并返回和參數(shù)對應(yīng)的響應(yīng)信息。
前面幾行是用來寫九條報價信息,他們分別儲存在數(shù)組里面。檢查時候用參數(shù)從MIDlet中傳過來,如果有,獲得這個值并存儲在quote_num中。接下來,你就看到一個調(diào)用的sleep()方法,休眠5秒鐘。你想要添加一個延遲來保證MIDlet有個明顯的停頓在等待PHP完成。目的是在顯示MIDlet如何停止,如果沒有這個停頓,快速的網(wǎng)絡(luò)和很短的PHP程序會執(zhí)行的非??於焕蔑@示。
<?php
$quotes[] = "I think there is a world market for maybe five computers.
Thomas Watson.";
$quotes[] = "The answer to life's problems aren't at the bottom of a
bottle, they're on TV! Homer Simpson.";
$quotes[] = "I love
Dan Quayle.";
$quotes[] = "640K ought to be enough for anybody. Bill Gates.";
$quotes[] = "Some people are afraid of heights. Not me, I'm afraid of
widths. Steven Wright";
$quotes[] = "Start every day off with a smile and get it over with.
W. C. Fields ";
$quotes[] = "I am not a vegetarian because I love animals; I am a
vegetarian because I hate plants. A. Whitney Brown";
$quotes[] = "A conclusion is simply the place where someone got tired
of thinking. Arthur Block";
$quotes[] = "A rich man's joke is always funny. Proverb.";
//-------------------------------------------------------
// It all starts here.
// Get requested quote number parameter passed in the url
//-------------------------------------------------------
if (isset($_GET))
{
$quote_num = $_GET["number"];
}
// Create a delay to make the problem of no-threads more obvious
sleep(5);
// User entered a quote number
if ($quote_num > 0)
{
// Decrement the quote requested because our array is zero based
echo $quotes[$quote_num - 1];
}
else // User did NOT enter a quote number, return a random quote
{
// Initialize random number generator
srand((double)microtime() * 1000000);
// Get a random value that is between 0 and the length of our array
(minus 1) $rand_num = rand(0, (count($quotes) - 1));
// Echo the quote from the array
echo $quotes[$rand_num];
}
?>
單線程MIDlet總結(jié)
當(dāng)用J2ME寫這個程序時,你會發(fā)現(xiàn)運行在單線程下訪問網(wǎng)絡(luò)的問題。MIDlet阻塞的原因是程序在系統(tǒng)的線程中運行。如果程序執(zhí)行過程中等待網(wǎng)絡(luò)鏈接的結(jié)束,MIDlet也會等待。
任何情況下,這種代碼是不被接受的。解決辦法就是用一個新的線程來執(zhí)行網(wǎng)絡(luò)鏈接處理。下面我們就會講述。
第三階段: 多線程
概述
多線程允許一個程序就多個片段執(zhí)行。一個多線程程序的例子就是我們都很熟悉的瀏覽器。當(dāng)一個網(wǎng)頁在下載的時候,你可以移動瀏覽器,打開菜單項,鍵入新的網(wǎng)絡(luò)地址,等等。在一個單線程程序中,這樣的操作是不可能的。
回到我們上一個例子。該程序中必須一個操作:訪問網(wǎng)絡(luò)任務(wù)的線程,其他的都可以不用改變。
線程創(chuàng)建后,調(diào)用start()來啟動。線程的運行在run()時開始。你可以暫時調(diào)用sleep()停止線程。不像j2se可以調(diào)用別的方法來停止線程。在下面開發(fā)多線程MIDlet的過程中,你將會看到我們?nèi)绾慰朔@個問題。
多線程技術(shù)
在J2SE中,有兩種方式來實現(xiàn)多線程。一種是繼承自Thread,另一種是實現(xiàn)Runnable接口。我們將會瀏覽每一種選擇,你會發(fā)現(xiàn)不同情況下各自的差異和優(yōu)劣。
直接從繼承Thread開始是個不錯的開頭。讓我們看看這是怎么做的。
繼承Thread
如下所示:
class NetworkThread extends Thread
{
...
public void run()
{
// Thread code goes here
...
}
...
}
創(chuàng)建一個線程并啟動它一氣呵成。
NetworkThread thread1 = new NetworkThread();
thread1.start();
...
記住,調(diào)用start()的結(jié)果是run()方法被調(diào)用。
實現(xiàn)Runnable接口
如下顯示:
public class AppletTest extends Applet implements Runnable
{
...
public void run()
{
// Thread code goes here
...
}
...
}
想要啟動AppletTest線程,你需要像下面這么做.
AppletTest someclass = new AppletTest();
...
Thread thread2 = new Thread(AppletTest));
thread2.start();
...
這和前面的例子有點像,你必要要做一些調(diào)整,因為你沒有直接從Thread中繼承。
對比兩個方式
我們到底應(yīng)該怎么樣選擇使用實現(xiàn)線程的方法呢?
第二個例子就說明了一切:
public class AppletTest extends Applet implements Runnable
{
...
public void run()
{
// Thread code goes here
...
}
...
}
AppletTest繼承自Applet,在java中你只能繼承一個類,也就是說一個子類只能有一個直接父類。為了實現(xiàn)多個繼承,就需要實現(xiàn)接口。
J2SE&J2ME線程的區(qū)別
J2ME中的很多東西都是J2SE的縮版,是為了適應(yīng)移動設(shè)備。說到線程,我需要指出幾個不同點。
沒有線程組 線程是基于object運行的,在J2ME中你不能通過一個方法啟動或停止一群線程。
沒有守護(hù)線程 守護(hù)線程是需要要執(zhí)行的給其他線程提供幫助或服務(wù)的。例如,在HotJava瀏覽器中就有一個守護(hù)線程為其他對象或是線程在它們需要的時候讀圖片。
沒有stop()方法 J2ME中的線程終止在run()方法執(zhí)行完畢。我將會出示一個例子來說明在多線程網(wǎng)絡(luò)MIDlet中它是這么完成的。
第四階段 多線程MIDlet
概述
不要再啰嗦了,我們現(xiàn)在就開始寫我在文章開頭提及的MIDlet-----一個多線程的J2ME程序。這個程序從網(wǎng)絡(luò)上下載圖片,并用TtxtBox組件提示用戶。一旦用戶開始下載你就會從textBox上獲得URL,在彈出的Alert上有一條信息提示下載開始,最后,啟動線程進(jìn)行下載。
下載結(jié)束時,MIDlet會用一個新的Alert提示用戶下載成功或失敗的信息,最后圖片會顯示出來。
下面是可獲得的圖片的地址和顯示:
http://www.corej2me.com/ibm/lighthouse.png
http://www.corej2me.com/ibm/car.png
http://www.corej2me.com/ibm/pond.png
MIDlet的第一個任務(wù)是提示用戶輸入一個圖片的URL。在處理事件的時候我們看到了兩個按鈕:exit用來退出MIDlet,view用來下載圖片。
url textbox
用戶選擇下來后,彈出一個Alert提示下載開始。
用戶返回到主界面。下載工作用一個單獨的線程來做,主頁面是可操作的,允許你改變TEXTBOX里面的內(nèi)容指向一個新的URL。
可以重復(fù)上面的步驟下載新的圖片。
當(dāng)?shù)谝粋€圖片下載完畢,就會提示用戶,顯示圖片。
點擊Done
編寫代碼
前面的步驟都演示過,我們就不再贅述,請復(fù)制下面的代碼:
/*--------------------------------------------------
* ViewImage.java
**
Download and view png files. Downloading is
* done in the background with a separate thread
*-------------------------------------------------*/
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;
import javax.microedition.io.*;
import java.io.*;
/*--------------------------------------------------
* Constructor
*-------------------------------------------------*/
public class ViewImage extends MIDlet implements CommandListener
{
private Display display; // Main display object
private TextBox tbMain; // Textbox to prompt for URL
private Alert alStatus; // Dialog box for download status
private Form fmViewImg; // Form to display images
private Command cmExit; // Command to exit
private Command cmView; // Command to initiate image download
private Command cmBack; // Return to main screen
private String imageName = null; // Name of image to download
Image im = null; // Downloaded image
private static final int ALERT_DISPLAY_TIME = 3000;
public ViewImage()
{
display = Display.getDisplay(this);
// Create the Main textbox with a maximum of 75 characters
tbMain = new TextBox("Enter url",
"http://www.corej2me.com/ibm/lighthouse.png", 75,
TextField.ANY);
// Create commands and add to textbox
cmExit = new Command("Exit", Command.EXIT, 1);
cmView = new Command("View", Command.SCREEN, 2);
tbMain.addCommand(cmExit);
tbMain.addCommand(cmView );
// Set up a listener for textbox
tbMain.setCommandListener(this);
// Create the form that will hold the png image
fmViewImg = new Form("");
// Create commands and add to form
cmBack = new Command("Back", Command.BACK, 1);
fmViewImg.addCommand(cmBack);
// Set up a listener for form
fmViewImg.setCommandListener(this);
}
public void startApp()
{
// Display the textbox that prompts for URL
display.setCurrent(tbMain);
}
public void pauseApp()
{ }
public void destroyApp(boolean unconditional)
{ }
/*--------------------------------------------------
* Process events
*-------------------------------------------------*/
public void commandAction(Command c, Displayable s)
{
// If the Command button pressed was "Exit"
if (c == cmExit)
{
destroyApp(false);
notifyDestroyed();
}
else if (c == cmView)
{
// Save the name of the image to download so we can
// display it in the alert (dialog box).
// This will be the entry after the last '/' in the url
imageName =
tbMain.getString().substring(tbMain.getString().lastIndexOf('/')
+ 1);
// Show alert indicating we are starting a download.
// This alert is NOT modal, it appears for
// approximately 3 seconds (see ALERT_DISPLAY_TIME)
showAlert("Downloading - " + imageName, false, tbMain);
// Create an instance of the class that will
// download the file in a separate thread
Download dl = new Download(tbMain.getString(), this, imageName);
// Start the thread/download
dl.start();
}
else if (c == cmBack)
{
display.setCurrent(tbMain);
}
}
/*--------------------------------------------------
* Called by the thread after attempting to download
* an image. If the parameter is 'true' the download
* was successful, and the image is shown on a form.
* If parameter is 'false' the download failed, and
* the user is returned to the textbox.
**
In either case, show an alert indicating the
* the result of the download.
*-------------------------------------------------*/
public void showImage(boolean flag, String imageName)
{
// Download failed
if (flag == false)
{
// Alert followed by the main textbox
showAlert("Download Failure", true, tbMain);
}
else // Successful download...
{
ImageItem ii = new ImageItem(null, im, ImageItem.LAYOUT_CENTER,
null);
// If there is already an image, set (replace) it
if (fmViewImg.size() != 0)
fmViewImg.set(0, ii);
else // Append the image to the empty form
fmViewImg.append(ii);
// Alert followed by the form holding the image
showAlert("Download Successful - " + imageName, true, fmViewImg);
}
}
/*--------------------------------------------------
* Show an alert with the parameters determining
* the type (modal or not) and the displayable to
* show after the alert is dismissed
*-------------------------------------------------*/
public void showAlert(String msg, boolean modal, Displayable
displayable)
{
// Create alert, add text, associate a sound
alStatus = new Alert("Status", msg, null, AlertType.INFO);
// Set the alert type
if (modal)
alStatus.setTimeout(Alert.FOREVER);
else
alStatus.setTimeout(ALERT_DISPLAY_TIME);
// Show the alert, followed by the displayable
display.setCurrent(alStatus, displayable);
}
}
/*--------------------------------------------------
* Class - Download
**
Download an image file in a separate thread
*-------------------------------------------------*/
class Download implements Runnable
{
private String url;
private ViewImage MIDlet;
private String imageName = null;
private boolean downloadSuccess = false;
public Download(String url, ViewImage MIDlet, String imageName)
{
this.url = url;
this.MIDlet = MIDlet;
this.imageName = imageName;
}
/*--------------------------------------------------
* Download the image
*-------------------------------------------------*/
public void run()
{
try
{
getImage(url);
}
catch (Exception e)
{
System.err.println("Msg: " + e.toString());
}
}
/*--------------------------------------------------
* Create and start the new thread
*-------------------------------------------------*/
public void start()
{
Thread thread = new Thread(this);
try
{
thread.start();
}
catch (Exception e)
{}
}
/*--------------------------------------------------
* Open connection and download png into a byte array.
*-------------------------------------------------*/
private void getImage(String url) throws IOException
{
ContentConnection connection = (ContentConnection)
Connector.open(url);
DataInputStream iStrm = connection.openDataInputStream();
ByteArrayOutputStream bStrm = null;
Image im = null;
try
{
// ContentConnection includes a length method
byte imageData[];
int length = (int) connection.getLength();
if (length != -1)
{
imageData = new byte[length];
// Read the png into an array
iStrm.readFully(imageData);
}
else // Length not available...
{
bStrm = new ByteArrayOutputStream();
int ch;
while ((ch = iStrm.read()) != -1)
bStrm.write(ch);
imageData = bStrm.toByteArray();
}
// Create the image from the byte array
im = Image.createImage(imageData, 0, imageData.length);
}
finally
{
// Clean up
if (connection != null)
connection.close();
if (iStrm != null)
iStrm.close();
if (bStrm != null)
bStrm.close();
}
// Return to the caller the status of the download
if (im == null)
MIDlet.showImage(false, null);
else
{
MIDlet.im = im;
MIDlet.showImage(true, imageName);
}
}
}
代碼的分析我就不再贅述了。