我的应用程序有一个非常奇怪的问题,它包含一个Activity和2个Fragments(android.support.v4.app.Fragment).
问题是当我旋转平板电脑时:应用程序立即崩溃.
几天前,一切都工作正常,但我不得不更改包名称,这会产生一些错误,但我设法纠正它们.问题出现在那之后,但我只是找不到错误在哪里.这是我在应用程序被销毁,重新启动,恢复和创建后立即得到的Logcat:
10-08 17:00:14.930: D/dalvikvm(18155): GC_CONCURRENT freed 394K, 8% free 7792K/8455K, paused 1ms+4ms
10-08 17:00:14.930: D/AndroidRuntime(18155): Shutting down VM
10-08 17:00:14.930: W/dalvikvm(18155): threadid=1: thread exiting with uncaught exception (group=0x40bee1f8)
10-08 17:00:14.938: E/AndroidRuntime(18155): FATAL EXCEPTION: main
10-08 17:00:14.938: E/AndroidRuntime(18155): java.lang.IllegalStateException: No activity
10-08 17:00:14.938: E/AndroidRuntime(18155): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1070)
10-08 17:00:14.938: E/AndroidRuntime(18155): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1065)
10-08 17:00:14.938: E/AndroidRuntime(18155): at android.support.v4.app.FragmentManagerImpl.dispatchResume(FragmentManager.java:1854)
10-08 17:00:14.938: E/AndroidRuntime(18155): at android.support.v4.app.FragmentActivity.onResumeFragments(FragmentActivity.java:431)
10-08 17:00:14.938: E/AndroidRuntime(18155): at android.support.v4.app.FragmentActivity$1.handleMessage(FragmentActivity.java:90)
10-08 17:00:14.938: E/AndroidRuntime(18155): at android.os.Handler.dispatchMessage(Handler.java:99)
10-08 17:00:14.938: E/AndroidRuntime(18155): at android.os.Looper.loop(Looper.java:137)
10-08 17:00:14.938: E/AndroidRuntime(18155): …Run Code Online (Sandbox Code Playgroud) android android-lifecycle android-fragments android-support-library
因此,我正在研究从一些长期运行的网络操作中将回调接口更改为本地广播的可行性.由于Activity生命周期为需要修改UI的异步请求创建了各种复杂功能(将Activity与回调断开连接onDestroy(),不要FragmentTransaction在之后修改s onSaveInstanceState()等),我认为使用本地广播更有意义,我们可以在生命周期事件中注册/取消注册接收器.
但是,当在配置更改期间销毁并重新创建活动时,没有注册广播接收器(onPause()/onResume()例如)之间的这个小窗口时间.因此,例如,如果我们在onCreate()if中启动异步请求savedInstanceState == null(例如,对于活动的第一次启动),如果用户在操作完成之前更改其设备方向,则完成时发送的广播是否可能丢失?(即接收器在onPause()上未注册,然后操作完成,然后接收器在onResume()中重新注册)
如果是这种情况,那么它会增加我们需要添加支持的额外复杂性,而且可能不值得切换.我已经研究了其他东西,比如Otto EventBus库,但我不确定它是否有同样的问题需要担心.
我有一个非常简单的活动,只要调用其中一个生命周期方法,就会记录一条消息.
这是我的onCreate方法:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout ll = new LinearLayout(this);
TextView tv = new TextView(this);
tv.setText("HELP ME");
ll.addView(tv);
setContentView(ll);
Log.i(TAG, "CREATE");
}
Run Code Online (Sandbox Code Playgroud)
这是没有任何用户输入的结果logcat:
07-23 16:14:12.057: I/sigh(12196): CREATE
07-23 16:14:12.067: I/sigh(12196): START
07-23 16:14:12.067: I/sigh(12196): RESUME
07-23 16:14:13.657: I/sigh(12196): PAUSE
07-23 16:14:13.687: I/sigh(12196): RESUME
07-23 16:14:14.167: I/sigh(12196): PAUSE
07-23 16:14:14.177: I/sigh(12196): RESUME
为什么我的应用程序在启动后会暂停和恢复几次?
仅当我从Eclipse运行它时才会发生此行为.随后从手机本身启动应用程序不会出现异常暂停/恢复.有没有人知道发生了什么?
更新:
好像它只发生在我的手机上,一台运行4.4.4的Nexus 5.在三星GS3/5和Nexus 4上不会发生.很奇怪.
我有三个活动: - SplashActivity - MainActivity - PlayerActivity
当然应用程序以SplashActivity开头,然后启动MainActivity并关闭.MainActivity在某个时刻启动了PlayerActivity并进入了Backstack.(MainActivity还活着但是在onStop上)然后我需要打开MainActivity并将PlayerActivity设置为后台(PlayerActivity是活着的但是在onStop上).然后我需要再次打开PlayerActivity并将MainActivity设置为background.
因此,当app将一个切换到另一个并返回时,PlayerActivity和MainActivity经常在没有onDestroy的情况下获得onPause()和onStop().
每次当用户按下"home"按钮时,我需要完成所有活动并启动SplashActivity应用程序,但主页按钮与活动之间的切换(onPause()和onStop())相同.所以我无法发现杀死活动的不同之处.
请帮忙.
编辑: 不幸的是,onUserLeaveHint没有帮助,它是一样的.如果User推送HOME,则调用:
onUserInteraction,onUserLeaveHint,onPause,onStop
此活动返回上一个活动(主),没有任何用户操作.
public class PlayerActivity扩展Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_next);
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
startActivity(new Intent(PlayerActivity.this, MyActivity.class));
}
}, 5000);
}
Run Code Online (Sandbox Code Playgroud)
}
但仍然有相同的:
onUserInteraction,onUserLeaveHint,onPause,onStop
android activity-lifecycle android-lifecycle android-activity
为了在配置更改中保留我的AsyncTasks,我使用基于片段的解决方案和setRetainInstance(true),它托管每个AsyncTask并回调一个监听活动,类似于此解决方案http://www.androiddesignpatterns.com/2013/04 /retaining-objects-across-config-changes.html
最终,目的是使用Robolectric在整个配置更改中测试AsyncTask的保留功能,但我需要从正确设置实际配置更改开始.但是,似乎我无法模仿配置更改期间发生的确切参考行为.
真正的应用程序:在运行真正的应用程序时,在配置更改时,在保留Fragment时销毁并重新创建Activity,因此它似乎正在工作.我可以通过在配置更改之前和之后检查它们的引用来看到这一点(下面使用的示例引用):
真正的应用程序,之前: 活动: abc 片段: xyz
真正的应用程序,之后: 活动: bca 片段: xyz(正确保留和重新附加)
情况1:然而,当在Robolectric测试中对Activity运行recreate()时,Activity似乎没有正确地重新创建其实例(尽管文档说该方法执行所有生命周期调用):
mActivityController =
Robolectric.buildActivity(AsyncTaskTestActivity.class).attach().create().start().resume().visible();
mActivity = mActivityController.get();
mActivity.recreate();
Run Code Online (Sandbox Code Playgroud)
Robolectric与recreate(),之前: 活动: abc 片段: xyz
Robolectric with recreate(),在Activity之后 : abc Fragment: xyz
这使我相信没有正确创建新的Activity实例,因此重新附加功能没有以真实的方式发生.
案例2:如果我根据个别生命周期调用创建测试:
mActivityController = Robolectric.buildActivity(AsyncTaskTestActivity.class).attach().create().start().resume().visible();
mActivityController.pause().stop().destroy();
mActivityController = Robolectric.buildActivity(AsyncTaskTestActivity.class).attach().create().start().resume().visible();
Run Code Online (Sandbox Code Playgroud)
在这个版本中,似乎Activity从头开始完全替换,但片段也是如此:
Robolectric具有单独的生命周期调用,在Activity之前 : abc Fragment: xyz
Robolectric有独立的生命周期通话,后 活动: BCA 片段: YZX
看来我要么重用相同的Activity(案例1),要么用新实例替换所有内容,好像没有底层应用程序保留Fragment(案例2).
问题:有没有什么方法可以设置我的Robolectric测试来模仿在实际Android环境中运行应用程序时获得的参考结果(根据Real应用程序结果),或者我是否仍然坚持要么创建一个单独的测试应用程序或者使用Robotium功能测试解决?我尝试这样做/sf/answers/1852780751/,但得到了与我的情况2相同的结果.
提前致谢!
android android-lifecycle android-fragments robolectric android-testing
当Android决定从堆栈中删除应用程序以释放某些RAM应用程序时,如果正在销毁的应用程序当前在后台运行某个循环会发生什么?循环会在执行期间终止还是VM等待它完成?
在更新到新的appcompat库之后,com.android.support:appcompat-v7:25.1.0我在替换事务中的片段时获得了新的片段生命周期.
例如我有两个片段FrFirst并FrSecond用日志中onStart和onStop,并用我第一替换第一与第二,然后第二:FrFirst -> FrSecond -> FrFirst.
getActivity().getSupportFragmentManager()
.beginTransaction()
.replace(R.id.content, new FrSecond())
.commit();
Run Code Online (Sandbox Code Playgroud)
在以前的appcompat版本中,我可以读取此日志:
FrFirst:导航到第二个
FrFirst:停止
FrSecond:开始FrSecond:导航到第一个
FrSecond:停止
FrFirst:开始
在25.1.0中这个日志:
FrFirst:导航到第二个
FrSecond:开始
FrFirst:停止FrSecond:导航到第一个
FrFirst:开始
FrSecond:停止
所以现在onStart呈现onStop当前之前调用的片段.
为什么方法顺序改变了,它是支持库中的错误吗?
android android-appcompat android-lifecycle android-fragments fragment-lifecycle
希望有人能帮我理解这个:
我正在使用单活动应用程序和许多在同一容器中替换的Fragments,我正在一个真实设备中测试我的应用程序并启用了"不要保持活动"选项
当添加新片段(使用FragmentTransaction replace()方法)时,我使用该setArguments()方法将信息传递给新片段.它按预期工作,我可以getArguments()在片段内获取该信息.到目前为止一切都还不错......
在此之后,我将我的应用程序发送到后台.我看到堆栈中的所有碎片都被破坏了,再次如预期的那样
我把我的应用程序带到前台,在getArguments()方法中我得到一个空Bundle(不是空,只是一个空对象),而不是我在#2中使用的数据
根据Android文档,提供的参数setArguments()将在片段销毁和创建中保留...所以,我的问题是:
"将在片段销毁和创建中保留"是否包括我描述的场景?
是否"不保留活动"选项可以乱用getArguments()/ setArguments()如果启用?
除了"不要保持活动"选项之外,有没有办法测试正确的片段创建/销毁?
正确保持片段参数"活着"的更好方法是什么?我可以将它们保存在onSaveInstanceState()方法中,但是想知道除此之外是否还有更多选项.
我知道看起来像是一些愚蠢的错误,但我找不到它。在我的项目中,我可以LifecycleOwner从片段访问,而不能从活动访问。
这是我的 build.gradle
implementation project(':domain')
implementation project(':data')
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.1.1'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.1'
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.core:core-ktx:1.1.0-alpha05'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
// Koin for Android
implementation "org.koin:koin-android:$koin_version"
implementation "org.koin:koin-androidx-viewmodel:$koin_version"
// Anko
implementation "org.jetbrains.anko:anko-commons:$anko_version"
implementation "org.jetbrains.anko:anko-sdk15-listeners:$anko_version"
//Architecture components
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
Run Code Online (Sandbox Code Playgroud)