2017-03-07 26 views
2

我有什麼似乎是一個愚蠢的要求:我可以在調用UI線程上的方法時阻止我的服務線程?

我需要阻止我IntentService線程同時運行我必須從UI線程訪問一個方法。我怎樣才能做到這一點?

顯然,我可以通過HandlerLooper.getMainLooper()運行UI方法,但當然我的服務處理的其餘部分會繼續。

一些詳細信息:

我的服務同步的內容,而使用粘合劑回調,逐步更新與新項目的UI。所有影響項目列表的方法都是UI-Thread綁定,以避免我的StaggeredGridLayout引發ConcurrentModificationExceptions。

然而,當我服務啓動我想打電話給名單之前,我同步的內容每個源獲得電流id的,這是需要的UI線程訪問。

我不能在啓動服務時提供此列表的原因是應用程序必須保持響應(意味着可以在我們同步時刪除項目),並且需要在每個額外的內容源之前檢查列表是同步

解決方案:

我想出了,是創建兩個處理器,一個在主尺蠖的UI方法,其它的一切,他們之間發送短信的最佳解決方案。它不覺得自己是個可以接受的,乾淨的解決方案

另一個是使相同的用戶界面方法的線程版本,做的內容的arraycopy並與複製循環開始。我不確定arraycopy操作是否不安全(容易發生ConcurrentModificationException),因爲很難觸發該錯誤。所以我不確定這是可以接受的。

+0

通常,您的服務線程*是* UI線程。 –

+0

這是一個IntentService,我應該澄清 –

+0

包裝訪問列表的方法應該這樣做'synchronized'塊應該這樣做 – nandsito

回答

0

我寫了使用AsyncTask的解決方案。

這裏是一個Activity調用任務:

public class CallingActivity extends Activity { 

    // method that does all the synchronization 
    private void doSync() { 

     // for each item you want to sync 
     int itemId; 

     new ItemUpdateAsyncTask(itemId, this).execute(); 
    } 

    // this method is called for each synced item 
    public void syncItem(int itemId, Object syncedItem) { 
     // update list etc. 
    } 
} 

現在,更新背景的項目的AsyncTask

public class ItemUpdateAsyncTask extends AsyncTask<Void, Void, Object> { 

    // the id of the item to be updated 
    private final int mItemId; 
    // reference to the activity that will be notified 
    // of the item update 
    private final WeakReference<CallingActivity> mCallingActivity; 

    public ItemUpdateAsyncTask(int itemId, CallingActivity callingActivity) { 
     super(); 
     mItemId = itemId; 
     mCallingActivity = new WeakReference<>(callingActivity); 
    } 

    @Override 
    protected Object doInBackground(Void... params) { 

     // sync item in background 
     Object syncedItem; 

     return syncedItem; 
    } 

    @Override 
    protected void onPostExecute(Object syncedItem) { 
     CallingActivity callingActivity = mCallingActivity.get(); 
     if (callingActivity != null) { 

      // update item in main thread 
      callingActivity.syncItem(mItemId, syncedItem); 
     } 
    } 
} 

我認爲這是更容易設計使用AsyncTask!而非該解決方案Service由於回調對象的傳遞。服務和活動只能通過Intents進行通信,Intents只能攜帶可序列化的數據。正如你所看到的,asynctasks可以引用回調對象,這使得事情變得更簡單。否則,你就必須註冊在活動的廣播接收器和服務必須發送一個廣播與更新的項目,這將需要可序列化。不過,這也是一個可行的解決方案。

用戶可以在多個時間activites之間去它正在運行

值得一當你設計一個這樣的架構注意點,那確實在後臺的東西,推結果到呼叫者。呼叫者可以是例如一個Activity可能已經完成,並在後臺工作完成時垃圾收集。這就是我將呼叫者打包在WeakReference中的原因。

+1

意向服務有一個活頁夾,您可以使用它與您知道的客戶進行交談。我的應用程序有一個對象,該綁定對話,每個活動然後觀察我的對象(因爲它太長時間運行異步任務)。我會接受這個答案,因爲它是唯一的,寫得很好 –

相關問題