Android 返回应用程序时背景 activity 消失
Android background activity disappears when coming back to the app
我有 activity A
和 B
同时在屏幕上可见。
A
是全屏 activity,B
是小对话框 activity。 B
(对话框)位于 A
之上并且当前处于活动状态。 A
在下方可见,但已暂停。
B
对话框中有一个按钮,单击该按钮后,用户将退出应用程序并共享 Intent
,例如 Gmail。回到应用程序后,背景全屏 activity A
是黑色的,只有对话框 activity 可见。
有没有办法在不关闭 activity B
(对话框)的情况下向 activity A
发出信号以在返回应用程序时重新绘制自身?
下面是退出应用前的屏幕截图。您可以同时看到这两个活动。
下面是返回应用程序后的屏幕截图。你可以看到背景 activity 不见了,而对话框 activity 仍然可见并且正常。
我想知道是否有一种方法可以在不关闭对话框的情况下向背景 activity 发出重绘自身的信号 activity(startActivity 不会成功,因为背景 activity 将成为前景)。
背景activity在AndroidManifest.xml中的定义是:
<activity
android:name="com.mypackage.thegame.GameActivity"
android:label="@string/app_name"
android:screenOrientation="portrait"
android:launchMode="singleTask"
/>
---更新---
我想我知道这其中的原因,但仍然没有成功的解决方法。
Activity A
不是根据 XML 定义构建的标准 activity。是纯粹的SurfaceView
activity。它创建一个 SurfaceView
并直接调用 setContent(mySurfaceView)
。表面视图启动一个线程 onResume
并杀死它 onPause
。这就是为什么当返回到应用程序时视图不会开始绘制,因为 onResume
没有被调用。
但是,我发现调用了 onStart
方法,我在其中放置了代码,以便在单独的线程中仅渲染当前状态的一帧(也在调用它的线程中尝试过)。但表面视图似乎无法获得要在其上绘制的 holder
和 canvas...我将继续调查,如果发现更多详细信息,请 post。
我终于做到了。我将描述我的解决方法,以防有人遇到同样的问题。
后台生命周期方法activityA
如下:
App Launch
-> onCreate
-> onStart
-> onResume (drawing thread is started)
Dialog Activity B Launches
-> onPause (drawing thread is killed)
Leave App
---
Come back to App
-> onStart (nothing happens, drawing thread does not exist)
A
唯一可以重绘自身的地方是 onStart
方法。在那里我检查我们是否来自 Share,如果是,我只渲染一个帧。 activity A
中的代码如下所示:
class MyActivity {
public void onStart() {
super.onStart();
if (afterShare) {
surfaceView.renderSingleFrame();
}
}
}
棘手的事情是我循环并尝试获取表面支架和 canvas。如果不成功,则休眠 50ms,然后重试几次。它通常会在第二次迭代时成功拿下 holder。
渲染单帧的代码是这样的:
public void renderSingleFrame() {
Runnable runnable = new Runnable() {
public void run() {
int retry = 0;
while(retry < 5) {
if (!holder.getSurface().isValid()) {
retry++;
try { Thread.sleep(50); } catch (InterruptedException e) {}
continue;
}
Canvas canvas = null;
try {
canvas = holder.lockCanvas();
if (canvas != null) {
this.drawFrame(canvas, 0); // canvas, deltaTime
}
}
catch(Exception e) {}
finally {
if (canvas != null && holder.getSurface().isValid()) {
holder.unlockCanvasAndPost(canvas);
}
}
break;
}
}
};
Thread thread = new Thread(runnable);
thread.start();
}
我有 activity A
和 B
同时在屏幕上可见。
A
是全屏 activity,B
是小对话框 activity。 B
(对话框)位于 A
之上并且当前处于活动状态。 A
在下方可见,但已暂停。
B
对话框中有一个按钮,单击该按钮后,用户将退出应用程序并共享 Intent
,例如 Gmail。回到应用程序后,背景全屏 activity A
是黑色的,只有对话框 activity 可见。
有没有办法在不关闭 activity B
(对话框)的情况下向 activity A
发出信号以在返回应用程序时重新绘制自身?
下面是退出应用前的屏幕截图。您可以同时看到这两个活动。
下面是返回应用程序后的屏幕截图。你可以看到背景 activity 不见了,而对话框 activity 仍然可见并且正常。
我想知道是否有一种方法可以在不关闭对话框的情况下向背景 activity 发出重绘自身的信号 activity(startActivity 不会成功,因为背景 activity 将成为前景)。
背景activity在AndroidManifest.xml中的定义是:
<activity
android:name="com.mypackage.thegame.GameActivity"
android:label="@string/app_name"
android:screenOrientation="portrait"
android:launchMode="singleTask"
/>
---更新---
我想我知道这其中的原因,但仍然没有成功的解决方法。
Activity A
不是根据 XML 定义构建的标准 activity。是纯粹的SurfaceView
activity。它创建一个 SurfaceView
并直接调用 setContent(mySurfaceView)
。表面视图启动一个线程 onResume
并杀死它 onPause
。这就是为什么当返回到应用程序时视图不会开始绘制,因为 onResume
没有被调用。
但是,我发现调用了 onStart
方法,我在其中放置了代码,以便在单独的线程中仅渲染当前状态的一帧(也在调用它的线程中尝试过)。但表面视图似乎无法获得要在其上绘制的 holder
和 canvas...我将继续调查,如果发现更多详细信息,请 post。
我终于做到了。我将描述我的解决方法,以防有人遇到同样的问题。
后台生命周期方法activityA
如下:
App Launch
-> onCreate
-> onStart
-> onResume (drawing thread is started)
Dialog Activity B Launches
-> onPause (drawing thread is killed)
Leave App
---
Come back to App
-> onStart (nothing happens, drawing thread does not exist)
A
唯一可以重绘自身的地方是 onStart
方法。在那里我检查我们是否来自 Share,如果是,我只渲染一个帧。 activity A
中的代码如下所示:
class MyActivity {
public void onStart() {
super.onStart();
if (afterShare) {
surfaceView.renderSingleFrame();
}
}
}
棘手的事情是我循环并尝试获取表面支架和 canvas。如果不成功,则休眠 50ms,然后重试几次。它通常会在第二次迭代时成功拿下 holder。
渲染单帧的代码是这样的:
public void renderSingleFrame() {
Runnable runnable = new Runnable() {
public void run() {
int retry = 0;
while(retry < 5) {
if (!holder.getSurface().isValid()) {
retry++;
try { Thread.sleep(50); } catch (InterruptedException e) {}
continue;
}
Canvas canvas = null;
try {
canvas = holder.lockCanvas();
if (canvas != null) {
this.drawFrame(canvas, 0); // canvas, deltaTime
}
}
catch(Exception e) {}
finally {
if (canvas != null && holder.getSurface().isValid()) {
holder.unlockCanvasAndPost(canvas);
}
}
break;
}
}
};
Thread thread = new Thread(runnable);
thread.start();
}