2012-10-19 12 views
6

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

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

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

誰でもこの権利を取得する方法を知っていますか?

+2

私は、昔ながらのJavaスレッドを使用することになり... – Lawrence

+0

コンシューマー/プロデューサーの問題:http://en.wikipedia.org/wiki/Producer-consumer_problem –

+0

私は実際にこのアプローチが本当に好きです。 APIを模倣しようとすると、私のコードの多くはAndroidとBlackBerryの間で再利用できることがわかりました。私はこれをいくつかの一般的なクラスでやった。 – Nate

答えて

12

ヴィシャルは正しい軌道に乗っているが、もう少しは、AndroidのAsyncTaskを一致させるために必要とされています。 enumとジェネリックスは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、:

スレッディング規則 fは従わなければならないいくつかのスレッドのルールがあります。またはこのクラスが正しく動作するようにします。

  • AsyncTaskクラスは、UIスレッドにロードする必要があります。これはJELLY_BEANの時点で自動的に となります。

  • タスクインスタンスは、UIスレッド に作成する必要があります。

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

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

  • タスクは一度だけ実行することができます( 第二の実行が試行された場合、例外がスローされます。)

+0

ありがとうございました。それは働いた:) –

+1

@ネイト+1と私のためのいくつかの素晴らしい学習のもの。ありがとうNate –

+0

@VishalVyas、問題ありません。あなたは間違いなく正しい考えを持っていました。そして、私はこの答えのために何かを書いたので、私はBlackBerryのアプリケーションでそれを使い始めるでしょう:) – Nate

4

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

ここでは、メソッドonPreExecute,onPostExecuteはUIスレッドで実行され、doInBackgroundはワーカースレッドで呼び出されます。 onPreExecuteonPostExecuteは抽象であるため、それらを上書きして、進行状況ダイアログの表示や却下などの実装を提供することができます。

メソッドが実行者を取得する順序が 1である)onPreExecute 2) 3をdoInBackground)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()); 
    } 
} 
} 
+0

これが役立つことを願っています。 –

+2

これは素晴らしいスタートですが、いくつか問題があります。 (1)上の 'onPreExecute()'は、あなたの実装で 'doInBackground()'の前に実行されることは保証されておらず、 'doInBackground()'の前に**開始**することはほとんどありません。 (2)Androidの 'AsyncTask'には、バックグラウンド処理中の' publishProgress() 'メソッドも含まれています。 – Nate

+0

@Nateなぜなら、 'onPreExecute()'が 'doInBackground()'の前に呼び出されないことが保証されていない理由を説明できれば、この実装を改善するのに役立つでしょう。私はこのインプリメンテーションをブラックベリープロジェクトの多くで使用しています。進行状況インジケーターを表示し、プロセスが完了したらそれを却下します。 –

関連する問題