[英]onClickListener not working (properly) after ConfigurationChange in fragments
嗯,这是一个艰难的 。 至少, 我想是这样......要清理:
在搜索互联网(使用谷歌)后,我没有找到任何问题的答案。
我发现的一切都是关于人们为他们的View
错误设置onClickListener
的。 我想在我的情况下这是同样的问题,但没有其他问题与我的相符。
这似乎是同样的问题......它没有答案。
我在AppCompatActivity
设置了三个Fragment
和一个ViewPager
。
viewPager = (ViewPager) findViewById(R.id.main_view_pager);
viewPager.setAdapter(new SectionsPagerAdapter(getSupportFragmentManager()));
由SectionsPagerAdapter
处理。
public class SectionsPagerAdapter extends FragmentPagerAdapter {
SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return MainTextHolder.newInstance(tabIndicatorOnClick);
case 1:
return PostWriter.newInstance(tabIndicatorOnClick);
case 2:
return TopPage.newInstance(tabIndicatorOnClick);
default:
return Error.newInstance();
}
}
@Override
public int getCount() {
return 3;
}
// ... more methods
}
在每个Fragment
我都有一些内容和一个自定义的TabIndicator
。
(以下xml
文件是我的View
for the indicator)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<View
android:id="@+id/fragment_divider_one"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:tag="one" />
<View
android:id="@+id/fragment_divider_two"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:tag="two" />
<View
android:id="@+id/fragment_divider_three"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:tag="three" />
</LinearLayout>
然后我在Fragment
的onCreateView(LayoutInflater inflater, ViewGroup Bundle savedInstanceState)
方法中为每个View
(分隔OnClickListener
设置一个OnClickListener
。 OnClickListener
已经在我的Activity
中准备好了,我还实例化了我的ViewPager
以便我可以更改当前的Item
( Fragment
/ tab)。
private final View.OnClickListener tabIndicatorOnClick = new View.OnClickListener() {
@Override
public void onClick(View view) {
if (view.getTag().toString().equals("one"))
viewPager.setCurrentItem(0, true); // second argument for smooth transition
else if (view.getTag().toString().equals("two"))
viewPager.setCurrentItem(1, true);
else if (view.getTag().toString().equals("three"))
viewPager.setCurrentItem(2, true);
}
};
我通过将OnClickListener
放入我的newInstance(View.OnClickListener tabIndicatorOnClick)
方法将其传递给Fragment
。
这是其中一个片段。 对其他人来说是完全相同的!
public static MainTextHolder newInstance(View.OnClickListener tabIndicatorOnClick) {
MainTextHolder fragment = new MainTextHolder();
Bundle args = new Bundle();
fragment.putIndicatorTabIndicatorOnClick(tabIndicatorOnClick);
fragment.setArguments(args);
fragment.setRetainInstance(true);
return fragment;
}
我的putIndicatorTabIndicatorOnClick(View.OnClickListener tabIndicatorOnClick)
方法是一个Interface
的Void
。 它只是将OnClickListener
应用于Class
( Fragment
)。
@Override
public void putIndicatorTabIndicatorOnClick(View.OnClickListener tabIndicatorOnClick) {
this.tabIndicatorOnClick = tabIndicatorOnClick;
}
是的确如此 。 它工作得很好......直到ConfigurationChange
发生。 在我的情况下,我通过改变方向测试它。
在ConfigurationChange
之后会发生一切正常的事情。 OnClickListener
应用于所有 Fragment
的所有 View
, 但 tabIndicatorOnClick
OnClickListener
是第二个和第三个Fragment
中的空对象引用 。
因此,在PostWriter和首页上 ,竟然没有一个真正的OnClickListener
上View
的对什么都原因。 但它变得更好:在MainTextHolder
Fragment
, tabIndicatorOnClick
不是null object reference
,但它不再更改ViewPager
的Item
。 它运行代码,但不会滚动Tab
。
当打开“不要保持活动”而不是设备的开发者选项并离开应用程序时,所有OnClickListener
都是null object references
。 甚至是MainTextHolder
那些。
在ConfigurationChange
之后, OnClickListener
被传递到我的第一个Fragment
,但是它没有正常工作,并且在剩下的Fragment
它甚至没有传递/ null object reference
。
可以通过销毁Activity
然后重新加载来复制该问题。
......我不知道出了什么问题。 我希望我能正确地构建我的问题。
minSdkVersion : 14
targetSdkVersion : 25
我的ViewPager上已经有一个ViewPager
。 这没有OnClickListener
所以我添加了自己的“重叠”指标,它们具有所需的OnClick
功能。 我也喜欢它的外观,但如果你能为我的TabIndicator
提供更好的解决方案,我也很乐意将它作为答案。
我遇到了将方法多次放入xml
:onClick
属性的解决方案,但为此,我需要为每个Fragment
创建相同的OnClickListener
,这不是很好的方式,它也没有解决我的问题,但是绕过它。 - 我需要将ViewPager
传递给我的Fragment
,然后从xml
调用该方法,正如我所说,这只是另一种方式,而不是我喜欢的方式。 我也不知道它是否有效。 我很可能会测试它。
Fragment
中的其他OnClickListener
仍能正常工作。 所以正如我所说,问题在于OnClickListener
本身不能正常工作/是一个null object reference
。
首先,为编写问题的详细描述做得很好。 StackOverflow上的许多提问者都可以从这个问题的能力中学习表达问题。
这个错误似乎来自于不考虑Fragment生命周期的变化。 在ViewPager中,Fragments将通过各种状态,包括隐藏和显示在临时屏幕外时,如果它们在屏幕外并且系统释放内存,则暂停和恢复,如果Android系统决定保存实例状态,则最终创建和销毁您的活动(例如来自配置更改)。 在后一种情况下,Android将尝试从ViewPager中保存的实例状态恢复Fragments的状态。 由于您的Fragments无法保存View.OnClickedListener
因此它们在参数中传递,它们在恢复时最终会返回一个null
指针,这会导致您的错误。
要修复错误,我建议您不要将View.OnClickedListener
作为参数传递给Fragments。 相反,通过Activity中的公共方法将OnClickListener
暴露给OnClickListener
,让Fragments在onResume()
中自己获取它。 这样,您可以保证Fragments在处于恢复状态时将具有对View.OnClickedListener
的引用。 所以你的onResume()
可能看起来像这样:
@Override
public void onResume() {
OnClickListener onClickListener = ((MyActivity) getActivity).getOnClickListener();
putIndicatorTabIndicatorOnClick(onClickListener);
}
由于您已在onResume()
设置它,因此应在onPause()
中将其删除:
@Override
public void onPause() {
//set the onClickListener to null to free up the resource
}
使用像这样的onResume()
和onPause()
来从监听器中释放资源是开发人员指南中推荐的方法。
当然,您必须通过检查onCreate(Bundle savedInstanceState)
保存状态并相应地恢复它来确保您的Activity也处理自己的生命周期。
请注意,可以通过多种方式触发保存实例状态和恢复:
您将能够使用这些方法之一来确定您是否正确处理了活动和碎片的生命周期。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.