2013-04-26 1 views
1

Я создаю игру, в которой используется шар робота Sphero. Когда игра запускается/возобновляется, она проверяет наличие парного или связанного мяча. Если Bluetooth отключен, или если нет пары в паре, он скрывает окно подключения. Если есть шар, сопряженный, но не подключенный, он переходит к этой функции.Android - Sphero - CalledFromWrongThreadException

// If the user clicked a Sphero and it failed to connect, this event will be fired 
@Override 
public void onRobotConnectionFailed(Robot robot) { 
    Log.d("activity", "onRobotConnectionFailed"); 
    removeConnectionView(); 
} 

Сбой в следующем способе.

private void removeConnectionView() { 
    mFrameLayout.removeView(mSpheroConnectionView); 
    mSpheroConnectionView = null; 
} 

Эта функция работает друг с другом по возможности. Это ошибка.

Thread [<14> Thread-2606] (Suspended (exception ViewRootImpl$CalledFromWrongThreadException)) 
<VM does not provide monitor information> 
ViewRootImpl.checkThread() line: 5031 
ViewRootImpl.invalidateChildInParent(int[], Rect) line: 998 
FrameLayout(ViewGroup).invalidateChild(View, Rect) line: 4358 
ImageView(View).invalidate(boolean) line: 10565 
ImageView(View).invalidate() line: 10520  
ImageView.invalidateDrawable(Drawable) line: 202  
XDrawable(Drawable).invalidateSelf() line: 382 
XDrawable(Drawable).setVisible(boolean, boolean) line: 578 
ImageView.onDetachedFromWindow() line: 1196 
ImageView(View).dispatchDetachedFromWindow() line: 12136  
FrameLayout(ViewGroup).dispatchDetachedFromWindow() line: 2824 
RelativeLayout(ViewGroup).dispatchDetachedFromWindow() line: 2824 
SpheroConnectionView$SpheroItemView(ViewGroup).dispatchDetachedFromWindow() line: 2824 
SpheroConnectionView$SpheroListView(ViewGroup).dispatchDetachedFromWindow() line: 2824 
SpheroConnectionView(ViewGroup).dispatchDetachedFromWindow() line: 2824 
FrameLayout(ViewGroup).removeViewInternal(int, View) line: 3943 
FrameLayout(ViewGroup).removeViewInternal(View) line: 3918 
FrameLayout(ViewGroup).removeView(View) line: 3850 
discgroove.removeConnectionView() line: 233 
discgroove.access$4(discgroove) line: 232 
discgroove$2.onRobotConnectionFailed(Robot) line: 191 
SpheroConnectionView$4.onRobotConnectionFailed(Robot) line: 157 
RobotProvider.update(Observable, Object) line: 570 
Robot(Observable).notifyObservers(Object) line: 138 
Robot.setConnected(boolean) line: 300 
DeviceConnection$4.run() line: 378 

ответ

5

Метод removeConnectionView вызывается из потока, который не является основной нити петлителя (или, то «UI нить»). Вид может только быть изменен из основного потока петлителя.

Для того, чтобы исправить это, экземпляр обработчика когда-то на главной нити петлителя (например, при создании представления или деятельности), а также использовать метод Hander#post(Runnable) назвать ваш метод, или использовать метод View#post(Runnable) на вашем FrameLayout.

Пример первого рода:

Поместите это в OnCreate метод деятельности, который всегда проходит в основной нити петлителя.

mHandler = new Handler(); 

Затем, когда вы хотите запустить этот метод:

handler.post(new Runnable() { 
     @Override 
     public void run() { 

      mFrameLayout.removeView(mSpheroConnectionView); 
      mSpheroConnectionView = null; 
     } 
    }); 

Пример второго рода:

mFrameLayout.post(new Runnable() { 
     @Override 
     public void run() { 
      mFrameLayout.removeView(mSpheroConnectionView); 
      mSpheroConnectionView = null; 
     } 
    }) 
2

Вы можете только сделать пользовательский интерфейс, связанные вещи от основного потока. Попробуйте создать обработчик, используя основной петлеукладчик и проводящие runnables для этого обработчика.

Ex.

private Handler mHandler = new Handler(Looper.getMainLooper()); 
. 
. 
. 
mHandler.post(new Runnable() { 
     public void run() { 
      removeConnectionView(); 
     } 
    });