9

我注意到有時異步任務無法正常工作,實際上它的doInBackground()方法不會被調用,服務在該活動的後臺運行。 例如,當音樂在帶有服務的後臺運行時,Async任務不會在後臺解析XML,因爲它的doInBackground在當時不工作,並且進度對話框或progressBar保持旋轉狀態。當服務在後臺運行時,異步任務無法正常工作(doInBackground未執行),Android

我在幾篇文章中讀到AsyncTask.THREAD_POOL_EXECUTOR可以在這些問題幫助像:

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 
    new Test().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 
} else { 
    new Test().execute(); 
} 

沒有幫助在我的情況。在上述暗示之後有同樣的問題。

這裏我給剛剛有點我的示例代碼,瞭解我在做什麼::

public class TestAct extends Activity { 

    ImageButton play,forward,backward; 
    private ListView mList; 
    // many more variables 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.test_layout); 

     //binding the service here 
     // start service is called 

     init(); 
    } 

    private void init(){ 

     play=(ImageButton)findViewById(R.id.playBtn); 
     forward=(ImageButton)findViewById(R.id.forward); 
     backward=(ImageButton)findViewById(R.id.backward); 
     mList=(ListView)findViewById(R.id.list); 

     new GetData().execute(); 

     play.setOnClickListener(new OnClickListener() { 

      @Override 
      public void onClick(View v) { 
       // calling the play() method of ServiceConnection here 
      } 
     }); 

      // adding header to Listview 
      // other code and click listeners 

    } 

    class GetData extends AsyncTask<Void, Void, Void>{ 

     @Override 
     protected void onPreExecute() { 
      super.onPreExecute(); 

      // starting the progress Bar 
      // initializing the Arraylist,Maps etc 
     } 

     @Override 
     protected Void doInBackground(Void... params) { 
      //parsing the XML here 
      return null; 
     } 

     @Override 
     protected void onPostExecute(Void result) { 
      super.onPostExecute(result); 

      // stop the ProgressBar 
      // Updating my UI here 
        // setting Adapter for ListView 
     } 
    } 
} 

這工作一般正常,但當服務在backgound運行(我的意思是,當播放音樂時在後面掛)。

我沒有得到背後這個異步任務問題的確切原因。 在這種情況下mannual線程實現的幫助...... ??

嗯,我認爲這個問題是因爲「服務在主線程中運行,所以當它運行時,它會阻止我的AsyncTask運行」......所以我認爲如果我們可以在後臺線程中運行服務,那可以提供幫助。這就是爲什麼我嘗試IntentService在單獨的線程中運行服務,但我懷疑...如果IntentService可以運行無限期類似於服務...並且IntentService幾次阻止AsyncTask。 所以我不認爲它爲這類問題提供了100%完美的解決方案。

任何人都可以幫我解決這個問題,並理解完整的場景。

在此先感謝。

+0

是您擴展業務或IntentService – koti 2013-02-15 09:50:20

+0

我使用的服務,爲播放音樂背景 – 2013-02-15 09:54:35

+0

異步任務應該工作。你在某個地方犯了錯誤。 – Leonidos 2013-02-15 09:57:55

回答

1

這裏是一個暗示,如何我終於解決了我的問題::

1)我用IntentService而不是服務作爲服務mainThread同時運行IntentService在與mainThread不同的線程中運行,以確保我的後臺服務不會影響我當前的任務。此外,我使用AIDL來進行我的用戶界面和後臺線程之間的通信(這已經適用於服務,因此在這部分中沒有任何新功能)。

2)我用無痛線程代替的AsyncTask,我中斷線程的onDestroy()方法以確保線程不會無限期繼續。

應用似乎比早些時候表現好得多。

希望這將幫助其他人太:)

+0

這是不公平的。人們提出了所有解決方案...... – 2013-02-25 08:32:48

+1

@ user1521536:你說得對,人們向我建議的解決方案,但他們都沒有包含我應用的解決方案提示,所以只是爲了幫助其他人,我將它們組合在一起以獲得更好的解決方案。 – 2014-01-27 07:44:21

1

我認爲問題是在上一個完成之前開始另一個GetData AsyncTask。在執行另一個任務之前,確保前一個任務完成。要做到這一點使用以下代碼:

// make sure we don't collide with another pending AsyncTask 
if (getDataTask == null || getDataTask.getStatus() == AsyncTask.Status.FINISHED || getDataTask.isCancelled()) { 
    getDataTask= new GetData(); 
    getDataTask.execute(); 
} 

此外,請確保您有運行任務的參考。在您的應用程序正在運行時,您可以使用Application類的子類來執行此操作,或者覆蓋onSaveInstanceState(Bundle outState) 並在onCreate(Bundle savedInstanceState)中收到對它的引用。

+0

感謝您的寶貴建議 – 2013-02-22 12:05:33

0

根據Android開發人員AsyncTask文檔的線程規則部分,AsyncTask必須在UI線程上創建並啓動,因此如果您從服務中的後臺線程啓動它,則會導致錯誤行爲。

http://developer.android.com/reference/android/os/AsyncTask.html

+1

向任何一個downvoted,我可以問澄清爲什麼downvote?根據我對用戶問題的理解,他將在一個意圖服務中啓動它,但不會在UI線程上運行,除非我只是用後臺線程或IntentService誤導有關服務的底層聲明。 – 2013-02-22 16:03:48

-2

你真的不應該使用AsyncTasks一般:)有一個很好的解釋here。想想如果用戶在設備運行的同時旋轉設備,會發生什麼情況。該活動被重新創建,但該任務在後臺運行並持有對「舊」活動的引用。有很多方法可以解決這個問題,而且他們肯定還是有些情況下AsyncTasks是正確的方法。

但是,你真的應該考慮切換到一個Loader或者(如果你覺得冒險的)嘗試RoboSpice :)

+0

感謝您的寶貴建議 – 2013-02-22 12:09:33

3

有時候你會想在比什麼IntentService向你的服務的生命週期更多的控制權,在這種情況下,你可以只需在服務中創建一個線程並在其中運行後臺代碼即可。實際上,更具體地說,創建一個包含Looper的HandlerThread,以便您可以在主線程和後臺線程之間使用標準的android方法進行通信(消息)。

Answered here

+0

感謝您的寶貴意見 – 2013-02-22 12:09:18

1

閱讀已經張貼在這裏的所有問題和解答。糾正我,如果我錯了你的情況是你解析XML和獲取歌曲列表,當用戶選擇任何歌曲,你想要與服務播放權?

如果場景是正確的,那麼我們可以用更簡單的方式實現它。

  1. 活動中,onResume()方法解析XML文件並獲得歌曲列表,更新列表視圖(不開始在這裏與服務相關的任何東西)
  2. 當歌用戶點擊,然後通過特定的鍵/字符串意圖的服務和啓動服務
  3. 在服務的OnStartCommand()方法得到的標識,並開始了歌曲作爲正常媒體API

這將真正爲你做的工作。

關於

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 
    new Test().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); 
} else { 
    new Test().execute(); 
} 

問題這是AsyncTask對不同版本的Android的不同的行爲。 查看你的代碼正在做的事情是在你正在初始化服務的活動中,因此服務在後臺運行而沒有做任何有益的事情。 當用戶點擊播放時,您正在調用創建問題的服務的播放功能。

所以要從Activity中調用服務的功能,您應該正確使用您未提及的AIDL。如果你寫了這樣的話應該是完美的。

但這裏的建議是將歌曲ID傳遞給服務,它應該從服務播放不應該在活動中調用服務的功能。

,如果你想在活動的onResume更新歌曲列表,那麼你必須編寫AIDL和完成情況

希望這會有所幫助。

+0

感謝drax您寶貴的建議,但我已經實現了使用IntentService而不是Service的事情,並用無痛線程取代了異步任務,事情工作相當不錯:) – 2013-02-22 11:56:53

+1

我已經實現了你的在我的測試項目中的場景。出於這個原因你甚至可以使用AIDL。如果你發現答案接受任何答案。 – 2013-02-22 12:00:26

1

我注意到,有時異步任務工作不正常,其實 其doInBackground()方法不會被調用,出現這種情況主要是

你知道,有AsyncTasks是可以的限制一次執行?我曾經遇到過任務沒有開始/正常工作的問題,這是因爲我超過了這個數字。有關該主題的更多信息,請查看Android AsyncTask threads limits?

當任何服務在該活動的後臺運行時。例如, 音樂在服務後臺運行時,Async任務不會在後臺解析XML,因爲其doInBackground在當時不工作 以及進度對話框或progressBar保持旋轉狀態。

你檢查死鎖的可能性(特別是,如果你使用wait()notify())?

嗯,我認爲這個問題是因爲「服務在主線程中運行,因此 當它運行時,它阻止我的AsyncTask運行」 ......所以,我認爲如果我們能在後臺線程 運行服務那麼可以幫助 。這就是爲什麼我

你要在服務中要做的事情應該在自己的線程運行。這樣你就可以確定什麼都不會被阻止。例如,如果你有東西需要填充,你可以使用接收器。

希望我能幫助有點...

相關問題