2014-06-18 62 views
0

我的MainActivity有2個視圖:TextView和一個按鈕。點擊按鈕後,我正在運行一個AsyncTask,它進一步爲網絡操作創建10個新的AsyncTasks。每創建一項任務都會延遲1秒。代碼是:AsyncTask系列不會立即執行

public class MainActivity extends ActionBarActivity 
{ 
    TextView tv; 
    Button t; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     tv = (TextView) findViewById(R.id.textView1); 
     t = (Button) findViewById(R.id.toggleButton1);  
     t.setOnClickListener(new OnClickListener() 
     {   
      @Override 
      public void onClick(View v) 
      { 
       getData(); 
      } 
     }); 
    } 

    void getData() 
    { 
     SuperNetworkAsyncTask s = new SuperNetworkAsyncTask(); 
     s.execute(""); 
    } 


    private class SuperNetworkAsyncTask extends AsyncTask<String, Void, String> 
    { 
     @Override 
     protected String doInBackground(String... urls) 
     { 
      for(int i=0;i<10;i++) 
      { 
       { 
        nTask = new NetworkAsyncTask(); 
        nTask.execute(""); 
        try { 
         Thread.sleep(1000); 
        } catch (InterruptedException e) { 
         e.printStackTrace(); 
        } 
       } 
      }    
      return ""; 

     } 

     @Override 
     protected void onPostExecute(String result) 
     { 

     }      
    } 


    private class NetworkAsyncTask extends AsyncTask<String, Void, String> 
    { 
     @Override 
     protected String doInBackground(String... urls) 
     { 
      return String.valueOf(System.currentTimeMillis()); 
     } 

     @Override 
     protected void onPostExecute(String result) 
     { 
      tv.setText(result); 
     }      
    } 

} 

我在期待那個時候第一次調用NetworkAsyncTask執行方法時,它會啓動執行。但是當我運行它時,我沒有發現任何NetworkAsyncTask開始執行,直到控件從SuperNetworkAsyncTask中出來。一旦調用execute方法,有沒有辦法推動NetworkAsyncTask線程的執行?

一些澄清:

爲什麼NetworkAsyncTask由SuperNetworkAsyncTask產生的?因爲如果我在主線程中創建NetworkAsyncTask,我的UI會凍結一段時間。

爲什麼要製作10個對象? NetworkAsyncTask的目的是以1秒的間隔從服務器讀取數據n秒,這裏n = 10。

第2部分:做一些測試後更新。

觀察: 作爲同胞布賴恩共享的方式,以避免嵌套的方式創造AsyncTasks,我想他的代碼:

void getData() { 
    Runnable runnable = new Runnable() { 
     @Override 
     public void run() { 
      for (int i = 0; i <= 10; i++) { 

       nTask = new NetworkAsyncTask(); 
       nTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 
       try { 
        Thread.sleep(1000); 
       } 
       catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
    }; 
    new Thread(runnable).start(); 
} 

這凍結我的UI幾秒鐘,然後屏幕在幾分之一秒內更新。我也很驚訝。

觀察:

隨着java.lang.Thread中,我嘗試以確保1)運行時調用()的線程應立即執行。 2)下一個任務只有在完成前一個任務後纔會創建。

代碼:

public static void main(String[] args) { 
    myThread m; 
    for (int i=0;i<10;i++) 
    { 
     m=new myThread(String.valueOf(i)); 
     m.start(); 
     synchronized (m) 
     { 
      try { 
       m.wait(); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     }   
    } 
} 

public class myThread extends Thread 
{ 

    public String name = ""; 

    public myThread(String n) 
    { 
     name = n; 
    } 

    public void run() 
    { 
     synchronized (this) 
     {   
      System.out.println(" Thread Name = " + name); 
      try { 
       Thread.sleep(2000); 
      } catch (InterruptedException e) {   
       e.printStackTrace(); 
      }   
      notifyAll(); 
     } 
    } 
} 

輸出:

Thread Name = 0 
Thread Name = 1 
Thread Name = 2 
Thread Name = 3 
Thread Name = 4 
Thread Name = 5 
Thread Name = 6 
Thread Name = 7 
Thread Name = 8 
Thread Name = 9 

基於在此,我更新了我的NetworkAsyncTask & SuperNetworkAsyncTask爲:

private class NetworkAsyncTask extends AsyncTask<String, Void, String> 
{ 
    @Override 
    protected String doInBackground(String... urls) 
    { 
     synchronized (this) 
     { 
      return String.valueOf(System.currentTimeMillis());    
     } 

    } 

    @Override 
    protected void onPostExecute(String result) 
    { 
     synchronized (this) 
     { 
      tv.setText(result); 
      notifyAll(); 
     } 
    } 
} 

private class SuperNetworkAsyncTask extends AsyncTask<String, Void, String> 
{ 
    @Override 
    protected String doInBackground(String... urls) 
    { 
     for(int i=0;i<10;i++) 
     { 
      nTask = new NetworkAsyncTask(); 
      nTask.execute(url); 
      synchronized (nTask) 
      { 
       try { 
        nTask.wait(); 
       } catch (InterruptedException e1) { 
        e1.printStackTrace(); 
       } 
       try { 
        Thread.sleep(2000); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       }     
      } 

     }    
     return ""; 

    } 

    @Override 
    protected void onPostExecute(String result) 
    { 

    }      
} 

這段代碼的wait()的不斷無限期地等待。

最後我換成:

nTask.execute(url); 

nTask.executeOnExecutor(THREAD_POOL_EXECUTOR, ""); 

這個工作以及預期。

+0

從另一個AsyncTask啓動一系列AsyncTasks有什麼意義?你也可以從UI線程中完成。 – Egor

+3

使用'executeOnExecutor'而不是'execute'。 [From Here](http://developer.android.com/reference/android/os/AsyncTask.html#executeOnExecutor(java.util.concurrent.Executor,Params ...))。 – Marius

+0

AsyncTask裏面的AsyncTask不是一個好的選擇。調用多線程執行並行或串行的順序取決於API版本。 'executeOnExecutor'可以處理同時運行的多個線程。 – Pr38y

回答

0

用戶界面只會更新在onPostExecute()。請參閱AsyncTask 上的注意事項點擊here!儘量避免10個AysncTasks,它沒有任何意義。

0

你不需要使用「超級異步任務」使用一個可運行的,然後並行

void getData() { 
    Runnable runnable = new Runnable() { 
     @Override 
     public void run() { 
      for (int i = 0; i <= 10; i++) { 

       nTask = new NetworkAsyncTask(); 
       nTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 
       try { 
        Thread.sleep(1000); 
       } 
       catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
    }; 
    new Thread(runnable).start(); 
} 

後創建新的異步任務蜂巢您可以指定並行

+0

Brian,Egor,pr38y:我剛剛嘗試過Brian的這段代碼,之前也試過這個。每當我屏幕凍結時,我想20秒。我知道這不應該發生,因爲當我從UI線程創建Asynctasks時,我的其他應用程序中的一個可以很好地執行。我也很驚訝。我正在使用4.2.2。 – Mohitt

0

運行異步任務一個AsyncTask應該在UI線程中啓動,而不是在一個doInBackground上運行。每次睡眠後您都可以撥打publishProgress,並在產生的調用onProgressUpdate中產生每個AsyncTask,這些調用在UI線程上運行。