2013-05-03 52 views
1

我正在嘗試爲我的Android遊戲添加USB控制器支持。我正在使用Marmalade,並基於USB示例代碼創建了一個擴展。那就是:無法在未調用Looper.prepare()的線程中創建處理程序 - Android Marmalade

public class GameControllerInput extends Activity 
      implements InputManager.InputDeviceListener 
{ 
    private static final String TAG = "GameControllerInput"; 

    private InputManager mInputManager; 
    private SparseArray<InputDeviceState> mInputDeviceStates; 

    private static int numEvents = 0; 


    public int EDK_GameControllerInput_Init() 
    { 
     LoaderActivity.m_Activity.runOnUiThread(new Runnable() 
     { 
     public void run() 
     { 
      Log.i(TAG, "Running 1 ========================="); 
     } 
    }); 
    Log.i(TAG, "Init 2 ========================="); 
    return 1; 

當我調用init函數我得到這個錯誤:

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

我讀過的其他線程這個錯誤,他們說,解決辦法是添加LoaderActivity.m_Activity.runOnUiThread(new Runnable()代碼。然而,正如你所看到的,添加這隻會給我同樣的錯誤。

我對Java沒有經驗,而且我對如何解決這個問題不知所措。任何幫助將不勝感激。

乾杯, 史蒂夫

回答

1

Looper(一個消息隊列處理器)被綁定到單個線程,每個線程具有至多一個彎針。 A Handler需要自己註冊一個Looper才能工作,所以每次調用new Handler()時,它都會嘗試爲當前線程(即創建Handler的線程)獲取Looper,該線程可以存在或不存在。您看到的異常被拋出,因爲創建處理程序的線程沒有活套。

有一兩件事情,你可以做些什麼來解決這個問題:

  • 添加Looper到當前線程。
  • 確保您在已具有Looper的線程上創建Handler

在幾乎所有情況下,處理程序都用於從後臺線程與UI線程進行通信,我假設這裏是這種情況。這意味着選項2.您的runOnUiThread(Runnable)的東西很接近,但沒有雪茄,因爲它所做的只是寫入日誌文件。

您需要將創建new Handler()(未在您的發佈代碼示例中顯示)的代碼移動到runOnUiThread塊中,或者使用其他方式使其在UI線程上運行。執行此操作的典型方法是在您的活動或片段的onCreate(Bundle)方法中創建它。

請記住,根據您的初始化順序,這可能意味着它初始爲null,如後臺線程所示,所以後臺代碼必須能夠處理該問題。

+0

謝謝,但我沒有任何代碼與Handler相關。這只是我從NDK中複製的示例代碼。我是一個完全的Java noob(因此我選擇使用Marmalade)。你能指點我一些示例代碼來顯示正在使用的處理程序嗎? – ColdBeamGames 2013-05-03 15:21:45

+1

我寫了一篇關於loopers的短篇文章(http://blog.xebia.com/2013/02/24/android-looper-anatomy/),但它可能不會給你足夠的信息。如果處理程序的目標是在UI線程上進行,實際上有一個簡單的方法可以讓Handler正確初始化:'new Handler(Looper.getMainLooper())'。無論調用線程是什麼,這都可以工作。 我不熟悉Marmalade框架,所以我不知道它在何處或什麼時候初始化它的處理程序。我認爲必須有一些init或啓動方法,你目前不在主線程上調用,但應該。 – Barend 2013-05-03 16:21:12

+0

感謝您抽出寶貴時間來解釋這一點。我會試一試。 – ColdBeamGames 2013-05-04 18:18:17

0

那麼最好有一個回調方法,並且只需在s4e文件中的方法聲明後調用run_on_os_thread將其標記爲主線程。

相關問題