6

我的要求是有一个线程来维护 BlackBerry 设备和服务器之间的套接字连接并交换命令,类似于请求和响应。

我的问题是我需要让这个线程一直在后台运行,保持 UI 对用户可用。因此,当有来自服务器的命令时,该线程解析它并更新 UI,如果 BlackBerry 用户有操作,它会将其发送到服务器,然后服务器依次处理它。

我使用 Android 开发了相同的应用程序,AsyncTask并且运行良好。但在 BlackBerry 中,由于没有此类,我使用了invokeLater()选项。服务器和 BB 设备之间的通信工作正常,但用户界面在 BlackBerry 上被冻结。

任何人都知道如何做到这一点?

4

2 回答 2

12

Vishal 走在正确的轨道上,但还需要多一点才能与 Android 的AsyncTask. 由于 BlackBerry 上的 Java 1.3 不提供枚举和泛型,因此您无法完美匹配 Android API。

但是,你可以做这样的事情(未经测试......这只是你的起点):

import net.rim.device.api.ui.UiApplication;

public abstract class AsyncTask {

    public static final int FINISHED = 0;
    public static final int PENDING = 1;
    public static final int RUNNING = 2;

    private int _status = PENDING;
    private boolean _cancelled = false;
    private Thread _worker;

    /** subclasses MUST implement this method */
    public abstract Object doInBackground(Object[] params);

    protected void onPreExecute() {
        // default implementation does nothing
    }
    protected void onPostExecute(Object result) {
        // default implementation does nothing
    }
    protected void onProgressUpdate(Object[] values) {
        // default implementation does nothing
    }
    protected void onCancelled() {
        // default implementation does nothing
    }
    protected void onCancelled(Object result) {
        onCancelled();
    }

    public final int getStatus() {
        return _status;
    }

    public final boolean isCancelled() {
        return _cancelled;
    }

    public final boolean cancel(boolean mayInterruptIfRunning) {
        if (_status == FINISHED || _cancelled) {
            return false;
        } else {
            _cancelled = true;
            if (mayInterruptIfRunning && _status == RUNNING) {
                // NOTE: calling Thread.interrupt() usually doesn't work
                //   well, unless you don't care what state the background
                //   processing is left in.  I'm not 100% sure that this is how
                //   Android's AsyncTask implements cancel(true), but I 
                //   normally just cancel background tasks by letting the
                //   doInBackground() method check isCancelled() at multiple
                //   points in its processing.
                _worker.interrupt();
            }
            return true;
        }
    }

    protected final void publishProgress(final Object[] values) {
        // call back onProgressUpdate on the UI thread
        UiApplication.getUiApplication().invokeLater(new Runnable() {
            public void run() {
                onProgressUpdate(values);
            }
        });
    }

    private void completeTask(final Object result) {
        // transmit the result back to the UI thread
        UiApplication.getUiApplication().invokeLater(new Runnable() {
            public void run() {
                if (isCancelled()) {
                    onCancelled(result);
                } else {
                    onPostExecute(result);
                }
                // TODO: not sure if status should be FINISHED before or after onPostExecute()
                _status = FINISHED;
            }
        }); 
    }

    public AsyncTask execute(final Object[] params) throws IllegalStateException {
        if (getStatus() != PENDING) {
            throw new IllegalStateException("An AsyncTask can only be executed once!");
        } else {
            try {
                onPreExecute();

                _worker = new Thread(new Runnable() {
                    public void run() {
                        try {
                            // run background work on this worker thread
                            final Object result = doInBackground(params);
                            completeTask(result);
                        } catch (Exception e) {
                            // I believe if Thread.interrupt() is called, we'll arrive here
                            completeTask(null);
                        }
                    }
                });
                _status = RUNNING;
                _worker.start();
            } catch (Exception e) {
                // TODO: handle this exception
            }
        }

        return this;
    }

}

此外,请务必记住 Android 的 AsyncTask 的线程规则,它也适用于上述实现:

线程 规则 要使此类正常工作,必须遵循一些线程规则:

  • AsyncTask 类必须在 UI 线程上加载。这是从 JELLY_BEAN 自动完成的。

  • 任务实例必须在 UI 线程上创建。

  • 必须在 UI 线程上调用 execute(Params...)。

  • 不要手动调用 onPreExecute()、onPostExecute(Result)、doInBackground(Params...)、onProgressUpdate(Progress...)。

  • 该任务只能执行一次(如果尝试第二次执行将引发异常。)

于 2012-10-22T11:12:55.713 回答
4

您可以创建一个类来扩展我的 class 实现AsyncTask。祝你好运 :)

这里的方法onPreExecuteonPostExecute在 UI 线程上执行,doInBackground 在工作线程上调用。由于onPreExecute,onPostExecute是抽象的,您可以覆盖它们并提供您的实现,例如显示和关闭进度对话框。

方法执行的顺序是 1) onPreExecute 2) doInBackground 3) onPostExecute

import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.Dialog;

public abstract class AsyncTask {
    Runnable runnable;
    Thread threadToRun;

    public abstract void onPreExecute();

    public abstract void onPostExecute();

    public abstract void doInBackground();

    public void execute() {
    try {
        runnable = new Runnable() {

            public void run() {
                // TODO Auto-generated method stub
                UiApplication.getUiApplication().invokeLater(
                        new Runnable() {

                            public void run() {
                                // TODO Auto-generated method stub
                                onPreExecute();
                            }
                        });

                doInBackground();

                UiApplication.getUiApplication().invokeLater(
                        new Runnable() {

                            public void run() {
                                // TODO Auto-generated method stub
                                onPostExecute();
                            }
                        });

            }
        };

        threadToRun = new Thread(runnable);
        threadToRun.start();
    } catch (Exception e) {
        // TODO: handle exception
        Dialog.alert("Async Error Occured. " + e.toString());
    }
}
}
于 2012-10-19T21:15:13.660 回答