【问题标题】:Where is the main thread in android app?android应用程序的主线程在哪里?
【发布时间】:2012-01-26 20:05:01
【问题描述】:

我编写了一个游戏(我将其命名为“Gamer”),其中我具有以下一般结构(代码已大大简化):

public class Gamer extends Activity implements View.OnClickListener
{
    public void onCreate(Bundle savedInstanceState) 
    {
        mpt = new MicksPanelThing(this);
    }
}
public class MicksPanelThing extends SurfaceView implements SurfaceHolder.Callback
{
    public MicksPanelThing(Context context) 
    {
        super(context);
        micks_thread_thing = new MicksThreadThing(getHolder(), this);
        getHolder().addCallback(this);
        setFocusable(true);
    }
    void updateView()
    {
        final SurfaceHolder holder = getHolder();

        try 
        {
            Canvas canvas = holder.lockCanvas();
        if(canvas != null)
            {
            onDraw(canvas);
            holder.unlockCanvasAndPost(canvas);
        }
        } 
        catch (Exception e) 
        {
        e.printStackTrace();
        }
    }
    public void onDraw(Canvas canvas) 
    {
        // blah
    }

}
class MicksThreadThing extends Thread 
{
    public MicksThreadThing(SurfaceHolder surfaceHolder, MicksPanelThing mpt)
    {
        // blah
    }
    public void run() 
    {
        while (this_thread_is_currently_active) 
        {
            micks_panel_thing.updateView();
        }
    }
}

游戏运行良好,非常强大。现在我想测试某个条件,如果是真的,就设置一个 AlertDialog。我认为我可以将这段代码放在我的 onDraw 方法中。然后我收到一条消息“无法在未调用 Looper.prepare() 的线程内创建处理程序”——这让我感到困惑,因为我认为 onDraw 方法正在由我认为不需要的主线程执行设置任何东西。

我想我可以通过将我的测试和对话框移动到主线程中的某个位置(在哪里?)或在某处添加一些 Looper.prepare() 代码来解决这个问题。

请有人告诉我哪个更容易 - 任何必要的代码应该放在哪里。

【问题讨论】:

    标签: android ui-thread


    【解决方案1】:

    尝试使用方法:runOnUIThread() 强制应用在ma​​inThread(即UIThread)上运行您的代码,示例:

    class MicksThreadThing extends Thread 
    {
        public MicksThreadThing(SurfaceHolder surfaceHolder, MicksPanelThing mpt)
        {
            // blah
        }
        public void run() 
        {
             Gamer.this.runOnUiThread(new Runnable(){
             @Override
             public void run(){
                //update/create your views here
                while (this_thread_is_currently_active) 
                {
                    micks_panel_thing.updateView();
                }
            }
        });
        }
    }
    

    其他解决方案是:您可以使用AsyncTask,而不是使用Thread

    【讨论】:

    • 你说你想从你的 Thread 显示你的对话框,所以你的线程不能触摸或修改 UI ,唯一可以这样做的线程是 UIThread ,所以强制你的线程修改 UI(创建对话框、视图、修改视图...等),您应该重写方法 runOnUIThread() 以强制您的线程在 UIThread 中运行该代码,
    • 你的意思是在我的跑步跑步吗?还是简单地将我现有的一个运行包装在 runOnUiThread 中?...也许您可以显示 MicksThreadThing 的修改版本以避免任何混淆。
    • 感谢您的编辑,但是当我修改代码时,eclipse 会在代码的其他地方突出显示大量新错误 - 例如,类型 Gamer 必须实现继承的抽象方法 View.OnClickListener.onClick(View) ...这是为什么?
    【解决方案2】:

    这样做:

    class MicksThreadThing extends Thread 
    {
        public MicksThreadThing(SurfaceHolder surfaceHolder, MicksPanelThing mpt)
        {
            // blah
        }
        public void run() 
        {
            while (this_thread_is_currently_active) 
            {
                //micks_panel_thing.updateView();
    
                Gamer.this.runOnUiThread(new Runnable(){
                   @Override
                   public void run(){
                      micks_panel_thing.updateView();
                   }
                });
            }
        }
    }
    

    【讨论】:

    • 是run within run 打错了吗?
    • 不... Gamer.this.runOnUiThread 中的运行将在您的 UI 线程上执行
    • 嗯……代码编译得很好——我看到游戏状态被绘制,但它被冻结了——没有响应任何触摸事件……还有什么你可能忘记的吗?
    【解决方案3】:

    您从 MicksThreadThing 调用 onDraw(canvas);。显然,它不是应用程序的主线程。主线程是那些,你的活动的onCreate() 被调用。

    【讨论】:

      【解决方案4】:

      您无法从普通线程更新 UI。 使用 runOnUiThread() 更新 UI。

      【讨论】:

        【解决方案5】:

        主线程是 ui 线程...所以您可以在 AsyncTask 中使用 HandleronPostExecute() or onPreexecute()

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-02-23
          • 2011-06-06
          • 2011-06-17
          相关资源
          最近更新 更多