2010-05-04 5 views
1

간단한 멀티 플레이어 게임을 만들려고합니다. 모든 네트워크 통신을 처리해야하는 WorkerService이 있으며이 서비스와 내 활동 간의 모든 상호 작용은 AIDL을 통해 수행됩니다. 나는 이것이 표준 접근법이라고 생각한다 - 양방향 상호 작용을 가능하게하기 위해서 나는 또한 IWorkerCallback 인터페이스 (또한 AIDL)를 사용한다.다른 스레드에서 콜백하면 예외가 발생합니다.

문제는 콜백은 UI 스레드에서만 수행 될 수있는 UI에서 변경해야한다는 것입니다. 나는 Handler (UI 스레드에서)을 만들었으며 이것이 명백한 해결책이라고 생각했습니다. 그러나 놀랍게도, 작동하지 않습니다.

LoungeActivitystartServer() 방법을 IWorker 인터페이스로 호출합니다. 내 WorkerService의 해당 메소드는 일부 작업을 수행하고 콜백을 작성합니다. 제대로 작동합니다. 그런 다음 WorkerService가 슬로우 나쁜 예외이 스레드 결과에서 새 스레드 및 콜백을 생성합니다 : 여기

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

는 일부 코드가 만들어이다 분명히 :

startServer() 구현 :

private void startServerImpl(String name, float latStart, float latEnd, 
float lonStart, float lonEnd) 
{ 
    // some instructions here 

    // this works fine: 
    callback.notifySocketCreated(); 

    // my naughty thread: 
    new ServerThread().start(); 

    // some instructions here 
} 

ServerThread 코드 :

private class ServerThread extends Thread { 
    @Override 
    public void run() 
    { 
     //some instructions here 

     // this call will cause an error 
     callback.notifyGameRegistered(); 

    } 
} 
에서210

모든 방법은 다음과 같습니다 처리기의 handleMessage() 방법에서

public void notifyGameRegistered() throws RemoteException 
{ 
    handler.dispatchMessage(handler.obtainMessage(CALLBACK_GAME_REGISTERED)); 
} 

내가 간단한 switch(msg.what)을하고 모든 경우에 (축배를 보여주는, 텍스트 변경 등) 간단한 UI 수정 거기에 있어요.

왜이 예외가 throw되는지 전혀 알 수 없습니다. Runnable에 코드를 포장하고 runOnUiThread()을 호출하여 문제를 해결할 수 있지만 여전히 호기심을 유발합니다. Handler가 항상 생성 된 스레드에서 실행해서는 안됩니다. ? 아니면 뭔가 잘못하고있는 걸까요?

답변

0

어쨌든 주 스레드에서 문제가되는 기능을 호출해야합니다.

+0

글쎄 .. 지금하고 있습니다. 하지만 handleMessage가 두 개의 다른 스레드에서 실행되는 이유는 무엇입니까?일단 UI에 있으면 (notifySocketCreated()) not another (notifyGameRegistered()). – omarcin

0

UI를 변경하는 기능은 UI를 소유하는 활동에 있어야합니다.

이 링크는 당신을 도움이 될 것입니다 http://android-developers.blogspot.com/2009/05/painless-threading.html

+0

오, 언급하는 걸 깜빡 했어. 이 메서드는 UI를 소유하고있는 액티비티로부터도 호출해야합니다. – Sid

+0

링크를 제공해 주셔서 감사합니다. 그러나 이미 본 적이 있습니다. 나는 AsyncTask가 설명 된 상황에서 과잉이라고 믿는다. 내 코드를 수정하는 법을 알아내는 것이 중요하지 않습니다. Runnables의 코드를 래핑하면 도움이되었습니다.하지만 Handler 인스턴스가 UI 스레드에 있었던 이유와 그렇지 않은 경우가 궁금합니다. 설명서에는 "각 처리기 인스턴스는 단일 스레드 및 해당 스레드의 메시지 대기열과 연결되어 있습니다." – omarcin

1

나는이 조금 늦게 알고 -하지만 문제는 dispatchMessage()라는 점이다.

올바른 방법은 sendMessage()입니다.

dispatchMessage()은 동일한 스레드에서 handleMessage()을 호출합니다.

문제는 Handler가 잘못된 스레드에 있지 않다는 것을 짐작하고 있지만, UI는 youHandle() 메소드에서 Handler를 생성하려고합니다. onHandle()이 잘못된 스레드에서 호출되었으므로 예외가 발생합니다.

/** 
* Handle system messages here. 
*/ 
public void dispatchMessage(Message msg) 
{ 
    if (msg.callback != null) { 
     handleCallback(msg); 
    } else { 
     handleMessage(msg); 
    } 
}