【问题标题】:onResume() and onRestart() not called when come back to APP from home screen从主屏幕返回应用程序时未调用 onResume() 和 onRestart()
【发布时间】:2013-03-11 13:59:15
【问题描述】:

我是 Android 新手。目前正在为 Android 构建一个简单的游戏。

我的问题是当按下主页按钮时,它会调用 onPause(),有时它会同时调用 onPause() 和 onStop()。但是,当我尝试返回游戏(通过单击主屏幕中的图标)时,既不会调用 onResume() 也不会调用 onRestart()。游戏一直在渲染,但我无法与游戏互动。触摸事件不起作用。当我尝试触摸按钮时,什么也没有发生,几秒钟后,它说“没有响应”,然后我必须强制关闭。

顺便说一句。我还注意到,当转到主屏幕时,会调用 MainGamePanel 中的 surfaceDestroyed() 函数。我以为这个函数会阻塞线程,但实际上在主屏幕时线程仍在运行。

谁能告诉我为什么 onRestart() 或 onResume() 没有触发以及为什么从主屏幕返回游戏后触摸事件不起作用?

非常感谢。

我重写了 onStop()、onPause()、onResume 和 onRestart(),以便在调用函数时在日志中输出一条消息:

@Override
    protected void onStop() {
        Log.d(TAG, "Stopping...");
        super.onStop();
    }

下面是我的 Activity 和表面视图的代码。 我有一个 ActivityMainGame 扩展了 Activity:

public class ActivityMainGame extends Activity 
{
    private MainGamePanel mainGamePanel;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_game);

        Log.w(TAG, "Creating the game");

        //set our MainGamePanel as the view
        mainGamePanel = new MainGamePanel(this);
        setContentView(mainGamePanel);
    }
}

我创建了一个 MainGamePanel 扩展了 SurfaceView 实现了 SurfaceHolder.Callback,这个类启动了一个线程来在画布上渲染东西:

public class MainGamePanel extends SurfaceView implements SurfaceHolder.Callback 
{
    private MainGameThread thread;

    public MainGamePanel(Context context) 
    {
        super(context);
        // adding the callback (this) to the surface holder to intercept events
        getHolder().addCallback(this);

        // create the game loop thread
        thread = new MainGameThread(getHolder(), this);

        // make the GamePanel focusable so it can handle events
        setFocusable(true);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) 
    {
        if (thread.getState() == Thread.State.NEW)
        {
            thread.setRunning(true);
            thread.start();
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder)
    {
        boolean retry = true;
        while (retry)
        {
            try
            {
                thread.join();
                retry = false;
            }
            catch (InterruptedException e)
            {
                Log.d(TAG, e.getMessage());
            }
        }
    }

应阿迪尔的要求,我将错误信息放在 logcat 中。这些是我的游戏被强制关闭时的消息:

03-11 15:04:21.491: E/ActivityManager(58): ANR in com.myslotgame (com.myslotgame /.ActivityMainGame)
03-11 15:04:21.491: E/ActivityManager(58): Reason: keyDispatchingTimedOut
03-11 15:04:21.491: E/ActivityManager(58): Load: 0.52 / 0.19 / 0.18
03-11 15:04:21.491: E/ActivityManager(58): CPU usage from 551359ms to 51ms ago:
03-11 15:04:21.491: E/ActivityManager(58):   system_server: 4% = 3% user + 0% kernel / faults: 5766 minor
03-11 15:04:21.491: E/ActivityManager(58):   adbd: 0% = 0% user + 0% kernel / faults: 55 minor
03-11 15:04:21.491: E/ActivityManager(58):   m.android.phone: 0% = 0% user + 0% kernel / faults: 17 minor
03-11 15:04:21.491: E/ActivityManager(58):   ndroid.launcher: 0% = 0% user + 0% kernel / faults: 1625 minor
03-11 15:04:21.491: E/ActivityManager(58):   qemud: 0% = 0% user + 0% kernel
03-11 15:04:21.491: E/ActivityManager(58):   events/0: 0% = 0% user + 0% kernel
03-11 15:04:21.491: E/ActivityManager(58):   zygote: 0% = 0% user + 0% kernel / faults: 1201 minor
03-11 15:04:21.491: E/ActivityManager(58):   id.defcontainer: 0% = 0% user + 0% kernel / faults: 77 minor
03-11 15:04:21.491: E/ActivityManager(58):   logcat: 0% = 0% user + 0% kernel
03-11 15:04:21.491: E/ActivityManager(58):   rild: 0% = 0% user + 0% kernel
03-11 15:04:21.491: E/ActivityManager(58):   ndroid.settings: 0% = 0% user + 0% kernel / faults: 9 minor
03-11 15:04:21.491: E/ActivityManager(58):   roid.alarmclock: 0% = 0% user + 0% kernel / faults: 14 minor
03-11 15:04:21.491: E/ActivityManager(58):   re-initialized>: 0% = 0% user + 0% kernel / faults: 7 minor
03-11 15:04:21.491: E/ActivityManager(58):   d.process.media: 0% = 0% user + 0% kernel / faults: 9 minor
03-11 15:04:21.491: E/ActivityManager(58):   com.android.mms: 0% = 0% user + 0% kernel / faults: 16 minor
03-11 15:04:21.491: E/ActivityManager(58):  +myslotgame: 0% = 0% user + 0% kernel
03-11 15:04:21.491: E/ActivityManager(58):  -myslotgame: 0% = 0% user + 0% kernel
03-11 15:04:21.491: E/ActivityManager(58): TOTAL: 7% = 6% user + 1% kernel + 0% irq + 0% softirq

【问题讨论】:

  • 按HOME返回游戏时,onCreate()会再次被调用吗?
  • 不,onCreate() 只是第一次调用。
  • 同样的问题,onRestart()onCreate()onResume()... 都不是在 onStop() 之后调用的。太奇怪了,不幸的是还没有关于这个问题的答案。你那边有什么消息吗?

标签: android


【解决方案1】:

onStop() 不能保证被调用,因为 Android 有时可能不得不在后台提前结束游戏而不事先通知,但onPause() 将始终被调用!因此,在onPause() 方法中,执行您在停止时会执行的操作,例如结束渲染线程,但您也可以放置类似if (isFinishing()) 的 if 语句并执行如果活动实际结束时您会执行的操作.

注意:如果您的活动扩展了Activity 类,您只能使用isFinishing() 方法,在这种情况下是您的ActivityMainGame 类。

【讨论】:

  • 谢谢。是的,总是调用 onPause()。你的意思是我需要在调用 onPause() 时结束或暂停线程,所以下次我回到游戏时,可以调用 onResume() 吗?我想即使我不暂停线程,也应该调用 onResume()。
  • 正确,无论你是否真的暂停线程,都会调用 onResume()。因此,您应该在 onPause() 中暂停线程并在 onResume() 中启动一个新线程。因为如果活动未完成,游戏中的变量(例如 x 和 y 位置)会被保留,因此您可以安全地执行此操作。但是,在 onPause() 中,您可以使用 isFinishing() 检查活动是否真正结束,您可以在其中保存高分、时间等变量。
  • 好的,我会按照您在 onPause() 中告诉我的操作。但问题是,目前,当我从主屏幕返回时,未调用 onResume(),是因为活动已完成吗?如果是这样,应该调用 onRestart() 吗?
  • onResume() 应始终在恢复活动时调用,无论是从主屏幕返回、从待机模式打开屏幕还是其他方式。我不会亲自使用onRestart()。在onCreate() 中设置组件,在onResume() 中激活和启动线程,并在onPause() 中杀死它。在onPause() 中,检查活动是否以if(isFinishing() {} 结束,并在大括号({})内执行方法,例如保存高分。
【解决方案2】:

我认为当您进入主屏幕时,会调用 onPause 和 onStop 和 onDestroy。强制关闭后能否发布logcat。

【讨论】:

  • 感谢您的回复。强制关闭时的日志是这样的。 03-11 14:36:20.081: I/dalvikvm(792): threadid=3: 对信号 3 做出反应 03-11 14:36:20.081: I/dalvikvm(792): 将堆栈跟踪写入 '/data/anr/ traces.txt'
  • 对不起格式,我不知道如何格式化评论中的消息
  • 其实onDestroy()没有被调用,我刚刚检查了这个。
  • 我已将错误发布在主要问题帖子的底部。谢谢
  • 还是不行,好像surfaceCreated()是第一次初始化视图才被调用,从主屏幕恢复时,onResume()没有被调用,surfaceCreated()也没有
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多