繁体   English   中英

在片段中的ConfigurationChange之后,onClickListener无法正常工作

[英]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>

然后我在FragmentonCreateView(LayoutInflater inflater, ViewGroup Bundle savedInstanceState)方法中为每个View (分隔OnClickListener设置一个OnClickListener OnClickListener已经在我的Activity中准备好了,我还实例化了我的ViewPager以便我可以更改当前的ItemFragment / 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)方法是一个InterfaceVoid 它只是将OnClickListener应用于ClassFragment )。

@Override
public void putIndicatorTabIndicatorOnClick(View.OnClickListener tabIndicatorOnClick) {
    this.tabIndicatorOnClick = tabIndicatorOnClick;
}

它有用吗

的确如此 它工作得很好......直到ConfigurationChange发生。 在我的情况下,我通过改变方向测试它。

问题

ConfigurationChange之后会发生一切正常的事情。 OnClickListener应用于所有 Fragment所有 View tabIndicatorOnClick OnClickListener是第二个和第三个Fragment中的空对象引用

因此,在PostWriter首页上 ,竟然没有一个真正的OnClickListenerView的对什么都原因。 但它变得更好:在MainTextHolder FragmenttabIndicatorOnClick不是null object reference ,但它不再更改ViewPagerItem 它运行代码,但不会滚动Tab

当打开“不要保持活动”而不是设备的开发者选项并离开应用程序时,所有OnClickListener都是null object references 甚至是MainTextHolder那些。

摘要

ConfigurationChange之后, OnClickListener被传递到我的第一个Fragment ,但是它没有正常工作,并且在剩下的Fragment它甚至没有传递/ null object reference

可以通过销毁Activity然后重新加载复制该问题。

到底...

......我不知道出了什么问题。 我希望我能正确地构建我的问题。

可能有意义

minSdkVersion14

targetSdkVersion25

我的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也处理自己的生命周期。

请注意,可以通过多种方式触发保存实例状态和恢复:

  1. 配置状态更改(例如旋转手机并使活动以横向而非纵向显示
  2. 设备内存不足(例如,如果最近的应用程序中有大量活动)
  3. 启用开发人员选项/不要保留活动并使用主页将您的应用程序放在最近的应用程序中,然后导航回您的应用程序。

您将能够使用这些方法之一来确定您是否正确处理了活动和碎片的生命周期。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM