Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

My requirement is to have a thread that maintains a socket connection between a BlackBerry device and a server and exchanges commands, similar to request and response.

My problem is that I need to have this thread running in the background all the time and keep the UI available to the user. So, when there is a command from the server, this thread parses it and updates the UI and also if there's an action from the BlackBerry user, it sends it to the server and the server in turn handles it.

I developed the same application in Android using AsyncTask and it's working well. But in BlackBerry, as there's no such class, I used the invokeLater() option. The communication works fine between the server and the BB device, but the UI is frozen on the BlackBerry.

Anyone have any idea how to get this right?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
102 views
Welcome To Ask or Share your Answers For Others

1 Answer

Vishal is on the right track, but a little more is needed to match Android's AsyncTask. Since enums and generics aren't available with Java 1.3 on BlackBerry, you can't match the Android API perfectly.

But, you could do something like this (not tested ... this is just a starting point for you):

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;
    }

}

Also, it's important to keep in mind the Threading Rules for Android's AsyncTask, which apply to the above implementation, too:

Threading rules There are a few threading rules that must be followed for this class to work properly:

  • The AsyncTask class must be loaded on the UI thread. This is done automatically as of JELLY_BEAN.

  • The task instance must be created on the UI thread.

  • execute(Params...) must be invoked on the UI thread.

  • Do not call onPreExecute(), onPostExecute(Result), doInBackground(Params...), onProgressUpdate(Progress...) manually.

  • The task can be executed only once (an exception will be thrown if a second execution is attempted.)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...