2011-12-04 4 views
2

ここに私の問題があります:AsyncTask and Monitors

私はサーバー上でいくつかの要求をする必要があります。これらの要求は、混合を避けるために、順番に行う必要があります。そのために、私はモニターを使用しています。ここで

は、私がこれまでに作ってみたものです:

public class TestActivity extends Activity 
{ 
    private String key; 
    private HashMap<String, String> values; 

    @Override 
    public void onCreate(Bundle savedInstanceState) 
    { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

    values = new HashMap<String, String>(); 

    ArrayList<String> list = new ArrayList<String>(); 
    list.add("foo"); 
    list.add("bar"); 
    list.add("baz"); 

    createValues(list); 
    } 

    private void createValues(final ArrayList<String> list) 
    { 
    Thread thread = new Thread(new Runnable() { 
     @Override 
     public void run() 
     { 
     key = null; 
     for (String element : list) 
     { 
      if (key != null) // Every time except the first time. 
      { 
      synchronized (key) 
      { 
       try 
       { 
       key.wait(); 
       } 
       catch (InterruptedException e) 
       { 
       } 
      } 
      } 
      key = element; 
      DataProcessor dataProcessor = new DataProcessor(); 
      dataProcessor.execute("Processed " + element); 
     } 
     } 
    }); 
    } 

    private void putDataInValue(String element) 
    { 
    synchronized (key) 
    { 
     values.put(key, element); 
     key.notify(); 
    } 
    } 

    private class DataProcessor extends AsyncTask<String, Void, String> 
    { 
    @Override 
    protected String doInBackground(String... params) 
    { 
     // Fetching data on a server. This takes time. 
     try 
     { 
     Thread.sleep(10000); 
     } 
     catch (InterruptedException e) 
     { 
     } 
     return params[0] + " from the server"; 
    } 

    @Override 
    protected void onPostExecute(String result) 
    { 
     putDataInValue(result); 
    } 
    } 
} 

ことがvaluesのコンテンツがあるということです後、私が望む何を:私は値を保持する必要が

[ 
"foo" => "Processed foo from the server", 
"bar" => "Processed bar from the server", 
"baz" => "Processed baz from the server" 
] 

listであり、どのコンテンツがどのコンテンツ(したがってモニタ)に対応しているかを知る。

私の問題は、私は私のLogCatにエラーメッセージが出続けるということです。私は、ウェブを検索した

Can't create handler inside thread that has not called Looper.prepare() 

、それらのほとんどは私を言って、その問題を持っていた一部の人を見つけた答えを見てハンドラを使用する必要があります。ハンドラも機能しません。私はスレッドを交換しようとしました

handler = new Handler(Looper.getMainLooper); 
handler.post(new Runnable //... 
//... 

しかし、それは単にフリーズします。

私は自分のアプローチが間違っていることを認め、私が窮地に瀕していると思うならば、最初からやり直していきます。あなたならどうしますか ?

+0

UIスレッドでAsyncTask.execute()を呼び出す必要があります。API [here](http://developer.android.com/reference/android/os/AsyncTask.html)をチェックしてください。 。アプリのターゲティングはどのAndroidバージョンで実行されますか? – yorkw

+0

私はAPI 8(アンドロイド2.2)を使用しています。 UIスレッドに関しては、 'runOnUiThread()'を使用しようとしましたが、アプリケーションがフリーズしました。 – SteeveDroz

答えて

0

あなたはおそらくすでにこのためのソリューションに到着しましたが、どのような場合に、ここにあなたがExecutorを使用して、要求の順序強制することができます一つの方法です:あなたはAPI 11をターゲットにしている場合

public class SequentialTaskExampleActivity extends Activity { 

    /** 
    * will only execute one job at a time, in the order given to it. 
    */ 
    private Executor executor = Executors.newSingleThreadExecutor(); 
    private Map<String, String> values = new HashMap<String, String>(); 
    private TextView textView; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     textView = new TextView(this); 
     textView.setTextSize(24); 
     setContentView(textView); 

     // Initialise jobs and add to queue 
     ArrayList<String> list = new ArrayList<String>(); 
     list.add("foo"); 
     list.add("bar"); 
     list.add("baz"); 

     for (String key : list) { 
      executor.execute(new Job(key)); 
     } 
    } 

    public void addToResult(String key, String value) { 
     values.put(key, value); 

     // display result to UI 
     textView.setText(String.format("%s %s => %s\n", textView.getText(), key, value)); 
    } 

    private class Job implements Runnable { 
     private String key; 

     public Job(String key) { 
      this.key = key; 
     } 

     @Override 
     public void run() { 
      // simulate work 
      try { 
       Thread.sleep(10 * 1000); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 

      // retrieve result 
      final String value = key + " from the server"; 

      // post result back to UI 
      runOnUiThread(new Runnable() { 

       @Override 
       public void run() { 
        addToResult(key, value); 
       } 
      }); 
     } 
    } 
} 

は、 +代わりにAsyncTaskで使用する特定のエグゼキュータを指定することができます(実際には、デフォルトの新しい動作はシリアル処理です)。いずれにしても、UIスレッドでAsyncTaskを作成して実行する必要があります。 AsyncTask.onPostExecute()が正しく動作するようにするには、これが唯一の方法です。