2013-05-03 43 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将其标记为主线程。

相关问题