gpt4 book ai didi

android - 在 Android 10 中启动 Activity 时崩溃

转载 作者:行者123 更新时间:2023-11-29 02:18:29 26 4
gpt4 key购买 nike

我在 Android 10 (SDK 29) 上运行我的应用(最低 SDK 21)时遇到问题。

应用程序的初始 Activity 正在按预期出现并显示。现在,当按下一个按钮在顶部调出第二个 Activity 时,我看到了这个崩溃日志:

java.lang.IllegalStateException: Activity top position already set to onTop=false
at android.app.ActivityThread.handleTopResumedActivityChanged(ActivityThread.java:4370)
at android.app.servertransaction.TopResumedActivityChangeItem.execute(TopResumedActivityChangeItem.java:39)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)

对于低于 SDK 29 的所有 Android 版本,第二个 Activity 可以正常启动。代码非常简单

    this.startActivity (new Intent (MyFirstActivity.this, MySecondActivity.class));

关于什么可能触发此问题以及异常(“Activity top position already set to onTop=false”)实际上告诉我什么的任何提示?

为方便起见,这是 ActivityThread.java 代码:

@Override
public void handleTopResumedActivityChanged(IBinder token, boolean onTop, String reason) {
ActivityClientRecord r = mActivities.get(token);
if (r == null || r.activity == null) {
Slog.w(TAG, "Not found target activity to report position change for token: " + token);
return;
}
if (DEBUG_ORDER) {
Slog.d(TAG, "Received position change to top: " + onTop + " for activity: " + r);
}
if (r.isTopResumedActivity == onTop) {
throw new IllegalStateException("Activity top position already set to onTop=" + onTop);
}
r.isTopResumedActivity = onTop;
if (r.getLifecycleState() == ON_RESUME) {
reportTopResumedActivityChanged(r, onTop, "topStateChangedWhenResumed");
} else {
if (DEBUG_ORDER) {
Slog.d(TAG, "Won't deliver top position change in state=" + r.getLifecycleState());
}
}
}

这是 AndroidManifest 的摘录:

<application
...

<activity
android:name="com.xxx.MyFirstActivity"
android:label="@string/${applicationLabel}"
android:launchMode="singleTask"
android:configChanges="orientation|keyboardHidden|screenSize" >

<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>

</activity>

...

<activity
android:name="com.xxx.MySecondActivity"
android:label="@string/ls_Quick_Reference"
android:icon="@drawable/action_help" >
</activity>

...

</application>

最佳答案

我在这里回答我自己的问题。我已经在谷歌/Android 的跟踪工具中提交了一个错误,并同时联系了作者。

https://issuetracker.google.com/issues/140571893

总而言之,我的部分代码搞砸了 Android 的 Activity 堆栈,而崩溃是由此导致的延迟结果。

详细说明:启动我的应用程序时,有时需要从之前的运行中运行一些迁移或修复操作。由于这些操作需要在主线程上完成,并且我想通知用户他/她需要稍等一下,所以我提出了一个显示消息的 View 。由于我的应用程序在主线程上很忙,显示没有刷新, View 也没有变得可见。为了解决这个问题,我运行了一个“内部循环”以允许发送显示消息:

try
{
// At this point all draw events should be in the event queue,
// now add another event to the end of queue to finish the loop once everything is processed.
Handler handler = new Handler (Looper.myLooper());

handler.postDelayed (new Runnable() {
@Override
public void run() {
throw new FinishLoopRunTimeException();
}
}, 50);

Looper.loop();
}
catch (FinishLoopRunTimeException e) {}

FinishLoopRunTimeException 是 RuntimeException 的简单特化。

虽然这是刷新显示消息的有效方法,但在 Android 10 中 Activity 状态发生变化时不得运行 Looper.loop ()。对于我的应用,情况一直如此,因为主要 Activity 一直在中间此代码运行时启动。如果您这样做, Activity 线程状态将被搞砸,并且稍后启动另一个 Activity 会崩溃。

因此解决方案是确保在 Android 10 执行内部循环时 Activity 处于稳定状态。旧的 Android 版本没有显示此问题。

虽然这可以被视为 Android 10 错误(在 Looper 文档中未提及 Activity 状态不得更改)并且应该在未来的版本中得到修复以使其更加健壮,但可以通过使用 Looper 代码来解决此问题。

关于android - 在 Android 10 中启动 Activity 时崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58232799/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com