6

私の要件は、BlackBerryデバイスとサーバー間のソケット接続を維持し、要求と応答と同様にコマンドを交換するスレッドを用意することです。

私の問題は、このスレッドを常にバックグラウンドで実行し、ユーザーがUIを利用できるようにする必要があることです。したがって、サーバーからのコマンドがある場合、このスレッドはそれを解析してUIを更新します。また、BlackBerryユーザーからのアクションがある場合は、サーバーに送信し、サーバーがそれを処理します。

私はAndroidで同じアプリケーションを使用して開発しましたがAsyncTask、それはうまく機能しています。しかし、BlackBerryでは、そのようなクラスがないため、invokeLater()オプションを使用しました。サーバーとBBデバイス間の通信は正常に機能しますが、BlackBerryではUIがフリーズします。

誰かがこれを正しくする方法を知っていますか?

4

2 に答える 2

12

Vishalは正しい方向に進んでいますが、Androidに合わせるにはもう少し必要ですAsyncTask。列挙型とジェネリックはBlackBerryのJava1.3では使用できないため、AndroidAPIと完全に一致させることはできません。

しかし、あなたはこのようなことをすることができます(テストされていません...これはあなたの出発点にすぎません):

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スレッドで作成する必要があります。

  • execute(Params ...)はUIスレッドで呼び出す必要があります。

  • onPreExecute()、onPostExecute(Result)、doInBackground(Params ...)、onProgressUpdate(Progress ...)を手動で呼び出さないでください。

  • タスクは1回だけ実行できます(2回目の実行が試行されると、例外がスローされます)。

于 2012-10-22T11:12:55.713 に答える
4

クラスの実装を拡張するクラスを作成できますAsyncTask。幸運を :)

ここで、メソッドonPreExecuteonPostExecuteUIスレッドで実行され、doInBackgroundはワーカースレッドで呼び出されます。は抽象的であるためonPreExecuteonPostExecuteそれらをオーバーライドして、進行状況ダイアログの表示と非表示のような実装を提供できます。

メソッドが実行される順序は、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 に答える