大佬教程收集整理的这篇文章主要介绍了通过使用 FragmentScenario 停止和恢复来测试 androidx.fragment 生命周期,onCreateView() 调用两次,但此错误已在 1.3.1,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在使用
我已经检查出了什么问题,结果发现在生命周期更改期间再次调用了
这是一个重现问题的示例代码。它表明视图不会保留其文本,也不会保留生命周期更改 RESUMED -> CREATED -> RESUMED 的可见性。手动测试不会重现此问题,只会影响仪器测试。 因为我没有直接声明
但它没有帮助,所以事实并非如此 我的代码还有什么问题(很可能是 gradle 依赖)? 通过强制 Fragment 进入 移回 EditText 确实保存了它的状态,这就是为什么它不会失败,但 TextViews 和 Buttons 没有保存任何东西。 您可以通过将 androIDx.fragment:fragment-tesTing@H_502_2@ 为我的应用编写插桩测试。测试用例之一是检查当 Fragment 停止和恢复时所有底层逻辑的行为是否正确,以模拟应用程序被最小化(主页按钮)并再次返回。这些测试使用
FragmentScenario.movetoState()@H_502_2@。首先,我使用
androIDx.fragment:fragment-tesTing:1.2.5@H_502_2@ 编写了我的测试,并且它们都通过了。但是当我将
androIDx.fragment:fragment-tesTing@H_502_2@ 更新为
1.3.1@H_502_2@ 时,上述测试开始失败。
Fragment.onCreateVIEw()@H_502_2@,即使它不应该调用(如果返回到
CREATED@H_502_2@ 并返回到 {{1 }}),导致视图“重置”到布局中声明的初始状态。我查了一下,发现了一个错误,描述中提到了“onCreateVIEw() 生命周期方法被调用了两次”https://issuetracker.google.com/issues/143915710(它也在 https://medium.com/androiddevelopers/fragments-rebuilding-the-internals-61913f8bf48e 中提到)。问题是它已经在 Fragment 1.3.0-Alpha08 中修复了,所以它不应该在 1.3.1 中发生。这意味着我的项目配置一定有问题。
RESUMED@H_502_2@
class lifecycleBUGFragment : Fragment() {
lateinit var textVIEw: TextVIEw
lateinit var editText: EditText
lateinit var button: button
overrIDe fun onCreateVIEw(inflater: LayoutInflater,container: VIEwGroup?,savedInstanceState: Bundle?): VIEw? {
val vIEw = inflater.inflate(R.layout.fragment_lifecycle_BUG,container,falsE)
textVIEw = vIEw.findVIEwByID<TextVIEw>(R.ID.textVIEw)
textVIEw.setonClickListener { textVIEw.text = "I was clicked" }
editText = vIEw.findVIEwByID<EditText>(R.ID.editText)
button = vIEw.findVIEwByID<button>(R.ID.button)
button.setonClickListener { button.visibility = VIEw.GONE }
return vIEw
}
}
@H_502_2@
<?xml version="1.0" enCoding="utf-8"?>
<linearLayout xmlns:androID="http://scheR_99_11845@as.androID.com/apk/res/androID"
xmlns:tools="http://scheR_99_11845@as.androID.com/tools"
androID:layout_wIDth="match_parent"
androID:layout_height="match_parent"
androID:orIEntation="vertical"
tools:context=".fragmenttesTing.lifecycleBUGFragment">
<TextVIEw
androID:ID="@+ID/textVIEw"
androID:layout_wIDth="wrap_content"
androID:layout_height="wrap_content"
androID:text="default text" />
<EditText
androID:ID="@+ID/editText"
androID:layout_wIDth="wrap_content"
androID:layout_height="wrap_content"
androID:inputType="text"
/>
<button
androID:ID="@+ID/button"
androID:layout_wIDth="wrap_content"
androID:layout_height="wrap_content"
androID:text="click to hIDe me"
/>
</linearLayout>
@H_502_2@
const val TYPED_TEXT = "some example text"
const val DEFAulT_TEXT = "default text"
const val CliCKED_TEXT = "I was clicked"
class lifecycleBUGFragmentTest {
lateinit var fragmentScenario: FragmentScenario<lifecycleBUGFragment>
@Before
fun setUp() {
fragmentScenario = FragmentScenario.launchInContainer(lifecycleBUGFragment::class.java)
}
@Test
fun whentextVIEwclickedAndFragmentlifecycleStoppedAndResumed_ThentextVIEwTextIsstillChanged() {
onVIEw(withID(R.ID.textVIEw)).check(matches(withText(DEFAulT_TEXT)))
onVIEw(withID(R.ID.textVIEw)).perform(click())
onVIEw(withID(R.ID.textVIEw)).check(matches(withText(CliCKED_TEXT)))
stopAndResumeFragment()
onVIEw(withID(R.ID.textVIEw)).check(matches(withText(CliCKED_TEXT)))
}
// this test passes,others fail
@Test
fun whenEditTextIsEditedAndFragmentlifecycleStoppedAndResumed_ThenEditTextTextIsstillChanged() {
onVIEw(withID(R.ID.editText)).perform(typeText(TYPED_TEXT))
stopAndResumeFragment()
onVIEw(withID(R.ID.editText)).check(matches(withText(TYPED_TEXT)))
}
@Test
fun whenbuttonIsClickedAndFragmentlifecycleStoppedAndResumed_ThenbuttonIsstillNotVisible() {
onVIEw(withID(R.ID.button)).perform(click())
onVIEw(withID(R.ID.button)).check(matches(not(isdisplayed())))
stopAndResumeFragment()
onVIEw(withID(R.ID.button)).check(matches(not(isdisplayed())))
}
private fun stopAndResumeFragment() {
fragmentScenario.movetoState(lifecycle.State.CREATED)
fragmentScenario.movetoState(lifecycle.State.RESUMED)
}
}
@H_502_2@
dependencIEs {
implementation filetree(dir: "libs",include: ["*.jar"])
implementation 'androIDx.appcompat:appcompat:1.2.0'
implementation 'androIDx.consTraintlayout:consTraintlayout:2.0.4'
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.4.31"
implementation 'androIDx.legacy:legacy-support-v4:1.0.0'
testImplementation 'junit:junit:4.13'
androIDTestImplementation 'androIDx.test.ext:junit:1.1.2'
androIDTestImplementation 'androIDx.test.espresso:espresso-core:3.3.0'
androIDTestImplementation "androIDx.test:runner:1.3.0"
androIDTestImplementation "androIDx.test:core:1.3.0"
androIDTestImplementation "androIDx.test.ext:junit:1.1.2"
androIDTestImplementation "androIDx.test:rules:1.3.0"
implementation "androIDx.navigation:navigation-fragment-ktx:2.3.4"
implementation "androIDx.navigation:navigation-ui-ktx:2.3.4"
androIDTestImplementation "androIDx.navigation:navigation-tesTing:2.3.4"
deBUGImplementation "androIDx.fragment:fragment-tesTing:1.3.1"
implementation "androIDx.navigation:navigation-compose:1.0.0-Alpha09"
// other dependencIEs unrelated to issue skipped for clarity
}
@H_502_2@,所以它是一个传递依赖,所以我想知道它是否会被解析为小于 8 的 1.3.0-Alpha,因此不包含修复。我添加了依赖约束以确保 1.3.1 得到解决
androIDx.fragment:fragment@H_502_2@
解决方法
CREATED
状态,您正在测试它在 detached 设计上确实会破坏其视图层次结构时的行为。RESUMED
(重新附加片段)时,重新创建视图并恢复其状态。注意:视图不会用 savedInstanceState
恢复,片段实际上在内部保存了保存的视图状态。android:saveEnabled="true"
添加到其 XML 来强制 TextView 保存其文本,但为了可见性,您需要将状态存储在片段字段中(甚至通过 savedInstanceState
保存/恢复它)并使用在 onViewCreated
中。
以上是大佬教程为你收集整理的通过使用 FragmentScenario 停止和恢复来测试 androidx.fragment 生命周期,onCreateView() 调用两次,但此错误已在 1.3.1全部内容,希望文章能够帮你解决通过使用 FragmentScenario 停止和恢复来测试 androidx.fragment 生命周期,onCreateView() 调用两次,但此错误已在 1.3.1所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。