Xử lý màn hình chờ

Để cải tiến SimpleWaitMIDlet, chúng ta sẽ xử lý phương thức connect() vào một lớp riêng biệt, gọi là CleanWorker, lúc đó ta sẽ đổi lại SimpleWaitMIDlet thành CleanMIDlet.

Bởi vì mạng không dây có xu hướng chậm và không ổn định, nên ta sẽ thêm một tùy chọn để người dùng có thể hủy kết nối nếu chờ quá lâu.

CleanMIDlet sẽ xử lý việc tạo ra các command và lưu trữ một tham chiếu vào một biến thành viên có tên là mCancelCommand; đồng thời CleanMIDlet là một CommandListener chung cho cả mainform và waitform.

import java.io.*;
import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class CleanMIDlet extends MIDlet implements CommandListener {

private Display mDisplay;
private Form mMainForm, mWaitForm;
private Command mExitCommand, mConnectCommand, mCancelCommand;
private CleanWorker mWorker;

public void startApp() {

mDisplay = Display.getDisplay(this);

if (mMainForm == null) {

mMainForm = new Form(“CleanMIDlet”);
mMainForm.append(new StringItem(“”, “Select Connect to make a network connection”));
mExitCommand = new Command(“Exit”, Command.EXIT, 0);
mConnectCommand = new Command(“Connect”, Command.SCREEN, 0);

mMainForm.addCommand(mExitCommand);
mMainForm.addCommand(mConnectCommand);
mMainForm.setCommandListener(this);

mWaitForm = new Form(“Waiting…”);
mCancelCommand = new Command(“Cancel”, Command.CANCEL, 0);

mWaitForm.addCommand(mCancelCommand);
mWaitForm.setCommandListener(this);

}

mDisplay.setCurrent(mMainForm);

}

public void commandAction(Command c, Displayable s) {

if (c == mExitCommand)

notifyDestroyed();

else if (c == mConnectCommand) {

mDisplay.setCurrent(mWaitForm);

String url = getAppProperty(“NetworkThreading.URL”);

mWorker = new CleanWorker(this, url);

mWorker.start();

}

else if (c == mCancelCommand) {

mDisplay.setCurrent(mMainForm);

mWorker.cancel();

mWorker = null;

}

}

public void pauseApp() {}

public void destroyApp(boolean unconditional) {}

public void networkResponse(String s) {

Alert a = new Alert(“Response”, s, null, null);

a.setTimeout(Alert.FOREVER);

mDisplay.setCurrent(a, mMainForm);

}

public void networkException(IOException ioe) {

Alert a = new Alert(“Exception”, ioe.toString(), null, null);

a.setTimeout(Alert.FOREVER);

mDisplay.setCurrent(a, mMainForm);

}

}

Bây giờ, chúng ta xây dựng phương thức connect() trong lớp CleanWorker như sau:

import java.io.*;
import javax.microedition.io.*;

public class CleanWorker extends Thread {

private CleanMIDlet mMIDlet;
private String mURL;
private HttpConnection mHttpConnection;
private boolean mCancel;

public CleanWorker(CleanMIDlet midlet, String url) {

mMIDlet = midlet;
mURL = url;
mCancel = false;

}

public void run() {

connect();

}

public void cancel() {

try {

mCancel = true;
if (mHttpConnection != null)
mHttpConnection.close();

}
catch (IOException ignored) {}

}

private void connect() {

InputStream in = null;

try {

// Query the server and retrieve the response.

mHttpConnection = (HttpConnection)Connector.open(mURL);
mHttpConnection.setRequestProperty(“Connection”, “close”);
in = mHttpConnection.openInputStream();

// Pull back the server’s response. If a content length is not
// specified, we’ll just read 255 bytes.

int contentLength = (int)mHttpConnection.getLength();
if (contentLength == 1) contentLength = 255;
byte[] raw = new byte[contentLength];
int length = in.read(raw);

// Clean up.

in.close();
mHttpConnection.close();

// Show the response to the user.

String s = new String(raw, 0, length);
mMIDlet.networkResponse(s);

}

catch (IOException ioe) {

if (mCancel == false) {

try {

if (in != null) in.close();
if (mHttpConnection != null) mHttpConnection.close();

}
catch (IOException ignored) {}

mMIDlet.networkException(ioe);
}

mCancel = false;

}

}

}

Chỉ sử dụng một thread cho việc kết nối mạng

Ở ví dụ trên, ta thấy mỗi khi người dùng nhấn command Connect, ứng dụng lại tạo ra một thread mới CleanWorker để thực hiện công việc kết nối mạng.

Trên các platform nhỏ chạy MIDP, tạo ra một thread mới sẽ làm tiêu tốn rất nhiều năng lượng(power) và bộ nhớ. Chính vì thế, chúng ta có thể tái sử dụng một thread duy nhất để làm tất cả các công việc kết nối mạng thay vì tạo ra một thread mới mỗi khi người dùng nhấn command Connect. Sơ đồ dưới đây minh hoạ kỹ thuật này.

Trong ví dụ trên,các hoạt động mạng được chia thành một lớp worker riêng biệt, sự thay đổi này không phải là quá khó khăn. Bây giờ, chúng ta sẽ tạo một lớp SingleWorker mới dựa trên lớp CleanWorker. Trong phương thức run(), thay vì gọi phương thức connect() một lần, chúng ta sẽ sử dụng vòng lặp và sử dụng phương thức wait(). Khi một thread khác sử dụng phương thức notify() để đánh thức thread SingleWorker, thì nó sẽ gọi phương thức connect(). Và để notify() thread, ta xây dựng phương thức go() để đánh thức thread đang chờ đợi để tiếp tục thực hiện công việc của mình. Biến thành viên mTrucking là một biến kiểu boolean cho biết thể hiện(instance) SingleWorker hiện đang chạy, hay sẽ được kết thúc.

public synchronized void run() {

while (mTrucking) {

try { wait();

}

catch (InterruptedException ie) {}

if (mTrucking) connect();

}

}

public synchronized void go() {

notify();

}
Chúng ta sẽ xây dựng lớp SingleWorker như sau:

import java.io.*;

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class SingleMIDlet extends MIDlet implements CommandListener {

private Display mDisplay;
private Form mMainForm, mWaitForm;
private SingleWorker mWorker;
private Command mExitCommand, mConnectCommand, mCancelCommand;

public void startApp() {

mDisplay = Display.getDisplay(this);

if (mMainForm == null) {

mMainForm = new Form(“SingleMIDlet”);
mMainForm.append(new StringItem(“”, “Select Connect to make a network connection”));
mExitCommand = new Command(“Exit”, Command.EXIT, 0);
mConnectCommand = new Command(“Connect”, Command.SCREEN, 0);

mMainForm.addCommand(mExitCommand);
mMainForm.addCommand(mConnectCommand);
mMainForm.setCommandListener(this);

mWaitForm = new Form(“Waiting…”);
mCancelCommand = new Command(“Cancel”, Command.CANCEL, 0);
mWaitForm.addCommand(mCancelCommand);
mWaitForm.setCommandListener(this);

String url = getAppProperty(“NetworkThreading.URL”);
mWorker = new SingleWorker(this, url);
mWorker.start();

}

mDisplay.setCurrent(mMainForm);

}

public void commandAction(Command c, Displayable s) {

if (c == mExitCommand)

notifyDestroyed();

else if (c == mConnectCommand) {

mDisplay.setCurrent(mWaitForm);
mWorker.go();

}

else if (c == mCancelCommand) {

mDisplay.setCurrent(mMainForm);
mWorker.cancel();

}

}

public void pauseApp() {}

public void destroyApp(boolean unconditional) {

mWorker.stop();

}

public void networkResponse(String s) {

Alert a = new Alert(“Response”, s, null, null);
a.setTimeout(Alert.FOREVER);
mDisplay.setCurrent(a, mMainForm);

}

public void networkException(IOException ioe) {

Alert a = new Alert(“Exception”, ioe.toString(), null, null);
a.setTimeout(Alert.FOREVER);
mDisplay.setCurrent(a, mMainForm);

}

}

Bạn thấy bài viết này thế nào?

Các bài liên quan:
Sử dụng Thread hiệu quả trong J2ME – Phan 1
Sử dụng Thread hiệu quả trong J2ME – Phan 2
Sử dụng Thread hiệu quả trong J2ME – Phan 4