2012-02-08 5 views
0

何千ものオブジェクトをダウンロードする必要があります。私は、一時停止してダウンロードを再開し、進行状況を表示できるようにする必要があります。私は、マルチスレッドではよくないので、私は(私は数学とUIを簡素化しましたが、左のロジックはそのまま)異なるソースからの私のコードをコンパイルした:Android搭載のマルチスレッド化(コードレビュー)の方法は?

public class DownloadActivity extends Activity { 
    private static final int MSG_FINISH = 1; 
    private static final int MSG_PROGRESS = 2; 

    private long total; 
    private ProgressBar progress; 

    private static DownloadThread thread; 

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

     progress = (ProgressBar) findViewById(R.id.progress); 

     total = 10000; 
     progress.setMax((int) total); 

     if (thread == null) 
      thread = new DownloadThread(progressHandler, 15000, 25000); 
     else 
      thread.setHandler(progressHandler); 

     ((Button) findViewById(R.id.start_button)).setEnabled(thread.paused()); 
     ((Button) findViewById(R.id.pause_button)).setEnabled(! thread.paused()); 

     ((Button) findViewById(R.id.start_button)).setOnClickListener(startOnClickListener); 
     ((Button) findViewById(R.id.pause_button)).setOnClickListener(pauseOnClickListener); 
    } 

    @Override 
    public void onBackPressed() 
    { 
     thread.pause(); 
     thread = null; 
     super.onBackPressed(); 
    } 

    private OnClickListener startOnClickListener = new OnClickListener() { 
     public void onClick(View v) { 
      ((Button) findViewById(R.id.start_button)).setEnabled(false); 
      thread.unpause(); 
      ((Button) findViewById(R.id.pause_button)).setEnabled(true); 
     } 
    }; 

    private OnClickListener pauseOnClickListener = new OnClickListener() { 
     public void onClick(View v) { 
      ((Button) findViewById(R.id.pause_button)).setEnabled(false); 
      thread.pause(); 
      ((Button) findViewById(R.id.start_button)).setEnabled(true); 
     } 
    }; 

    final Handler progressHandler = new Handler() { 
     public void handleMessage(Message msg) 
     { 
      switch (msg.what) 
      { 
       case MSG_PROGRESS: 
        if (progress != null) 
        { 
         long current = msg.getData().getLong("current"); 
         progress.setProgress((int) current); 
        } 
        break; 
       case MSG_FINISH: 
        Button pause = ((Button) findViewById(R.id.pause_button)); 
        if (pause != null) 
         pause.setEnabled(false); 
        break; 
      } 
     } 
    }; 

    private class DownloadThread extends Thread 
    { 
     Handler handler; 
     long current; 
     long x; 
     long x2; 
     LinkedList<Long> pendingList; 
     Thread threadA; 
     Thread threadB; 
     Thread threadC; 
     Thread threadD; 

     boolean paused = true; 

     DownloadThread(Handler h, long x1, long x2) 
     { 
      current = 0; 
      this.x = x1; 
      this.x2 = x2; 

      pendingList = new LinkedList<Long>(); 
      handler = h; 
      threadA = new Thread(this); 
      threadA.start(); 
      threadB = new Thread(this); 
      threadB.start(); 
      threadC = new Thread(this); 
      threadC.start(); 
      threadD = new Thread(this); 
      threadD.start(); 
     } 

     public void run() 
     { 
      while (! isInterrupted()) 
      { 
       synchronized (this) 
       { 
        if (paused) 
        { 
         try { 
          wait(); 
         } catch (InterruptedException e) { 
          e.printStackTrace(); 
         } 
         continue; 
        } 
       } 
       Long l; 
       synchronized (pendingList) 
       { 
        if (pendingList.size() == 0) 
        { 
         x++; 
         if (x > x2) 
         { 
          continue; 
         } 
         l = new Long(x); 
         pendingList.add(l); 
         synchronized (this) 
         { 
          notifyAll(); 
         } 
         continue; 
        } 
        else 
        { 
         l = pendingList.poll(); 
         if (l == null) 
         { 
          synchronized (this) 
          { 
           try { 
            wait(); 
           } catch (InterruptedException e) { 
            e.printStackTrace(); 
           } 
          } 
          continue; 
         } 
        } 
       } 
       Object d = DownloadFactory.download(l); 
       if (d != null) 
       { 
        synchronized (DownloadActivity.this) 
        { 
         current++; 
         sendProgress(); 
        } 
       } 
       else 
       { 
        synchronized (pendingList) 
        { 
         pendingList.add(l); 
        }     
       } 
      } 
     } 

     public void interrupt() 
     { 
      threadA.interrupt(); 
      threadB.interrupt(); 
      threadC.interrupt(); 
      threadD.interrupt(); 
     } 

     public synchronized boolean paused() 
     { 
      return paused; 
     } 

     public synchronized void pause() 
     { 
      paused = true; 
     } 

     public synchronized void unpause() 
     { 
      sendProgress(); 
      paused = false; 
      notifyAll(); 
     } 

     public synchronized void setHandler(Handler h) 
     { 
      handler = h; 
      sendProgress(); 
     } 

     private void sendProgress() 
     { 
      Message msg = handler.obtainMessage(MSG_PROGRESS); 
      Bundle b = new Bundle(); 
      b.putLong("current", current); 
      msg.setData(b); 
      handler.sendMessage(msg); 
      if (current == total) 
       handler.sendEmptyMessage(MSG_FINISH); 
     } 
    } 
} 

このコードは正常に動作し、私が望むすべてを行いますが、私それが醜いのではないことを理解してください(少なくとも入れ子のスレッドを入れて)。それで、同じタスクを達成するための素晴らしいアンドロイドの方法は何ですか?私はプロの同時実行が、4つの、他のスレッドが含まれているスレッドを使用していないです

答えて

0

[OK]を、あまりにも、かなり悪に聞こえる:)

あなただけのダウンロードマネージャを作りたい場合は、この方法を越えて必要な作業です。 API 9以上を使用する場合は、DownloadManagerを確認してください。

それ以外の場合は、キューが含まれ、ダウンロードの追加/削除と開始/再起動/停止を処理する単純なManagerクラスを使用することをお勧めします。キューに要素がある場合、AsyncTaskを開始して要素をダウンロードし、正常にダウンロードされた場合はその要素をキューから削除します。そうでなければ、再開しようとします。