GVKun编程网logo

是否需要在分离时将Fragment接口侦听器设置为null?

15

此处将为大家介绍关于是否需要在分离时将Fragment接口侦听器设置为null?的详细内容,此外,我们还将为您介绍关于AndroidFragmentgetArguments()返回null、andro

此处将为大家介绍关于是否需要在分离时将Fragment接口侦听器设置为null?的详细内容,此外,我们还将为您介绍关于Android Fragment getArguments()返回null、android – FragmentManager.getFragment()NullPointerException、android – FragmentStatePagerAdapter with ChildFragmentManager – FragmentManagerImpl.getFragment导、android – GetFragmentManager.findFragmentByTag()返回null的有用信息。

本文目录一览:

是否需要在分离时将Fragment接口侦听器设置为null?

是否需要在分离时将Fragment接口侦听器设置为null?

在涉及回调的Fragment示例中,通常它们在onAttach方法中分配侦听器,然后在onDetach方法中将侦听器设置为null。

这最后一部分是必要的吗?片段被分离/销毁时,监听器是否不会自动设置为null?还是在某些情况下,您可能会分离该片段并将其重新附加到其他位置,并且您不希望回调指向特定的内容,直到它重新附加至某个内容?

答案1

小编典典

我从来没有明确地将监听器引用设置为null,因为在大多数情况下它不会有所作为。

以下是您其他问题的一些说明:

  • 片段被分离/销毁时,监听器是否不会自动设置为null?并不是的。onDetach()onDestroy()反映组件的生命周期,而不反映对象的生命周期。那里什么也不会自动发生。当片段实例被垃圾回收时,对监听器的引用将被破坏。如果这是对您的侦听器的唯一引用,则也可以进行垃圾回收。
  • 还是在某些情况下,您可能会分离该片段,然后将其重新连接到其他位置,并且您不希望回调指向特定的内容,除非它重新连接至某个内容?我会说这不太可能。在正常使用情况下,您必须在中分配侦听器onAttach(),以确保可以正确委派事件。之后onDetach(),您将不会收到任何需要委派的事件,直到您重新附加该片段为止。而且,如果您重新连接它,那么您将拥有正确的侦听器实例,因为您已经在中进行了处理onAttach()

Android Fragment getArguments()返回null

Android Fragment getArguments()返回null

正如标题所示.
我从这里下载了片段代码,http://developer.android.com/shareables/training/FragmentBasics.zip.
这是来自Android官方开发者网站的片段示例. http://developer.android.com/training/basics/fragments/fragment-ui.html

这是MainActivity.java的onCreate():

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.news_articles);

    // Check whether the activity is using the layout version with
    // the fragment_container FrameLayout. If so, we must add the first fragment
    if (findViewById(R.id.fragment_container) != null) {

        // However, if we're being restored from a prevIoUs state,
        // then we don't need to do anything and should return or else
        // we Could end up with overlapping fragments.
        if (savedInstanceState != null) {
            return;
        }

        // Create an instance of ExampleFragment
        HeadlinesFragment fragment = new HeadlinesFragment();

        // In case this activity was started with special instructions from an Intent,
        // pass the Intent's extras to the fragment as arguments
        //fragment.setArguments(getIntent().getExtras());
        Bundle args= new Bundle();
        args.putString("category", "clothes");
        args.putString("item", "shirts");
        fragment.setArguments(args);

        // Add the fragment to the 'fragment_container' FrameLayout
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.fragment_container, fragment).commit();
    }
}

和HeadlinesFragment.java的onCreate():

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // We need to use a different list item layout for devices older than Honeycomb
    int layout = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ?
            android.R.layout.simple_list_item_activated_1 : android.R.layout.simple_list_item_1;

    Bundle args = getArguments();
    if (args == null) {
        Toast.makeText(getActivity(), "arguments is null " , Toast.LENGTH_LONG).show();
    } else {
        Toast.makeText(getActivity(), "text " + args , Toast.LENGTH_LONG).show();
    }        

    // Create an array adapter for the list view, using the Ipsum headlines array
    setlistadapter(new ArrayAdapter<String>(getActivity(), layout, Ipsum.Headlines));

}

我在这里读了几个QA,比如这个@L_301_2@,以及与setArguments()和getArguments()相关的许多其他QA,但我仍然被卡住了.

我已经将Bundle和Toast代码移动到onAttach()和onCreateView(),但没有用.我的代码有什么问题?我想我错过了什么,但不知道它是什么.
请帮忙!谢谢.

编辑:
我会更清楚地表明我的意图.在我下载的FragmentBasic中,有MainActivity.java,HeadlinesFragment.java和ArticlesFragment.java.从MainActivity.java到ArticlesFragment.java的“通信”不是问题.我想要的是将数据从MainActivity.java发送到HeadlinesFragment.java.他们的联系是这样的:

--------------------------------------
| MainActivity <-> HeadlinesFragment |
|      |                             |
|      |>> ArticlesFragment          |
--------------------------------------

HeadlinesFragment正在运行时运行.

*当使用带有<的Android小工具时,这些代码可以正常工作600px宽度.但是在平板电脑上使用时不起作用(> = 600px),正如下面@ Tesla1984所证明的那样.但我想要的是小工具< 600px和小工具> 600px的.

解决方法:

@tonny

我下载了FragmentBasics.zip.我只更改参数名称.代码和结果图片.

主要活动

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.news_articles);

    // Check whether the activity is using the layout version with
    // the fragment_container FrameLayout. If so, we must add the first fragment
    if (findViewById(R.id.fragment_container) != null) {

        // However, if we're being restored from a prevIoUs state,
        // then we don't need to do anything and should return or else
        // we Could end up with overlapping fragments.
        if (savedInstanceState != null) {
            return;
        }

        // Create an instance of ExampleFragment
        HeadlinesFragment fragment = new HeadlinesFragment();

        // In case this activity was started with special instructions from an Intent,
        // pass the Intent's extras to the fragment as arguments
//            firstFragment.setArguments(getIntent().getExtras());
        //test
        Bundle args= new Bundle();
        args.putString("category", "clothes");
        args.putString("item", "shirts");
        fragment.setArguments(args);

        // Add the fragment to the 'fragment_container' FrameLayout
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.fragment_container, fragment).commit();
    }
}

HeadlinesFragment

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // We need to use a different list item layout for devices older than Honeycomb
    int layout = Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB ?
            android.R.layout.simple_list_item_activated_1 : android.R.layout.simple_list_item_1;

    Bundle args = getArguments();
    if (args == null) {
        Toast.makeText(getActivity(), "arguments is null " , Toast.LENGTH_LONG).show();
    } else {
        Toast.makeText(getActivity(), "text " + args , Toast.LENGTH_LONG).show();
    }    

    // Create an array adapter for the list view, using the Ipsum headlines array
    setlistadapter(new ArrayAdapter<String>(getActivity(), layout, Ipsum.Headlines));
}

这是结果

android – FragmentManager.getFragment()NullPointerException

android – FragmentManager.getFragment()NullPointerException

我正在使用支持库v4并且无法保存片段的状态.

@Override
protected void onSaveInstanceState(Bundle outState)
{
    ...
    if(mFragment != null)
        getSupportFragmentManager().putFragment(outState,"frag",mFragment);
    ...
}
@Override
protected void onCreate(Bundle savedInstanceState)
{
    ...
    if(savedInstanceState != null)
    {
        //Here I get NullPointerException
        getSupportFragmentManager().getFragment(savedInstanceState,"frag");
    }
    ...
}

当我调用getFragment()时抛出NullPointerException(savedInstanceState包含带有“frag”的条目).

这是logcat输出的一部分:

04-18 00:10:56.719: E/AndroidRuntime(14644): Caused by: java.lang.NullPointerException
04-18 00:10:56.719: E/AndroidRuntime(14644):    at android.support.v4.app.FragmentManagerImpl.getFragment(FragmentManager.java:569)

我也尝试调用返回null的getFragments().这在我看来很奇怪.

我将不胜感激任何帮助!

解:

我忘了使用super.onSaveInstanceState(outState);在onCreate方法中.

最佳答案
感谢@Fllo.问题是我忘了调用父活动的onSaveInstanceState().

@Override
protected void onSaveInstanceState(Bundle outState)
{
    //Added this and the problem was solved
    super.onSaveInstanceState(outState);
    ...
}

android – FragmentStatePagerAdapter with ChildFragmentManager – FragmentManagerImpl.getFragment导

android – FragmentStatePagerAdapter with ChildFragmentManager – FragmentManagerImpl.getFragment导

编辑2

我现在设法通过使用来自这里https://code.google.com/p/android/issues/detail?id=42601#c10的技巧摆脱了错误,这就是为什么我的最后一次编辑放在我的问题之上的原因.

但这导致了下一个错误:

java.lang.NullPointerException
at android.support.v4.app.FragmentManagerImpl.getFragment(FragmentManager.java:569)
at android.support.v4.app.FragmentStatePagerAdapter.restoreState(FragmentStatePagerAdapter.java:211)
at android.support.v4.view.ViewPager.onRestoreInstanceState(ViewPager.java:1281)
at android.view.View.dispatchRestoreInstanceState(View.java:12043)
at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:2688)
at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:2694)
at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:2694)
at android.view.View.restoreHierarchyState(View.java:12021)
at android.support.v4.app.Fragment.restoreViewState(Fragment.java:425)
at android.support.v4.app.FragmentManagerImpl.movetoState(FragmentManager.java:949)
at android.support.v4.app.FragmentManagerImpl.movetoState(FragmentManager.java:1104)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1460)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:440)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4800)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:798)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:565)
at dalvik.system.NativeStart.main(Native Method)

现在我不知道从哪里继续……

编辑0 – 第一个问题

我得到以下异常:

java.lang.IllegalStateException: No activity
at android.support.v4.app.FragmentManagerImpl.movetoState(FragmentManager.java:1091)
at android.support.v4.app.FragmentManagerImpl.movetoState(FragmentManager.java:1086)
at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1877)
at android.support.v4.app.Fragment.performActivityCreated(Fragment.java:1492)
at android.support.v4.app._HoloFragment.performActivityCreated(_HoloFragment.java:251)
at android.support.v4.app.FragmentManagerImpl.movetoState(FragmentManager.java:947)
at android.support.v4.app.FragmentManagerImpl.movetoState(FragmentManager.java:1104)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1460)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:440)
at android.os.Handler.handleCallback(Handler.java:615)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4800)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:798)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:565)
at dalvik.system.NativeStart.main(Native Method)

我不知道从哪里开始.我正在使用最新的支持库(v4,rev18).

一切正常,直到我添加一个Fragment,它将ViewPager与FragmentStatePagerAdapter结合在一起.

我到处都在使用支持库,我尝试了https://code.google.com/p/android/issues/detail?id=42601的解决方案……

但还没有任何效果……

我不知道从哪里开始,有人有提示吗?

编辑1:背景和代码

1)在我的MainActivity中,我使用以下内容:

第三页有viewpager …

public void setPage(int pos, boolean addToBackStack)
 {
    Fragment nextFragment = null;
    FragmentTransaction transaction = null;

    switch (pos)
    {
        case 0:
            if (mFragmentAllRoutines == null)
                mFragmentAllRoutines = new RoutinesListFragment();
            if (!mFragmentAllRoutines.isVisible())
                nextFragment = mFragmentAllRoutines;
            break;
        case 1:
            if (mFragmentRoutine == null)
                mFragmentRoutine = new RoutineFragment();
            if (!mFragmentRoutine.isVisible())
                nextFragment = mFragmentRoutine;
            break;
        case 2:
            if (mFragmentDay == null)
                mFragmentDay = new RoutineDayFragment();
            if (!mFragmentDay.isVisible())
                nextFragment = mFragmentDay;
            break;
        default:
            break;
    }

    if (nextFragment != null)
    {
        // Fragment prevFragment = getSupportFragmentManager().findFragmentById(R.id.fragment);
        transaction = getSupportFragmentManager().beginTransaction();
        // if (prevFragment != null)
        //    transaction.detach(prevFragment);
        transaction.replace(R.id.fragment, nextFragment, nextFragment.getClass().getName());
        // transaction.attach(nextFragment);
        if (addToBackStack)
            transaction.addToBackStack(null);
        transaction.commit();
    }
}

2)第三个片段:

它是一个带有ViewPager和FragmentStatePagerAdapter的简单片段. FragmentStatePagerAdapter将getChildFragmentManager()作为FragmentManager获取.在某个地方似乎存在问题.

解决方法:

我需要看到更多的代码才能知道在哪里应用这个……但是我遇到了类似的情况……我以同样的方式解决了ChildFragmentManager问题,并得到了与你一样的NullPointerException.

我确实设法解决了……我会尝试描述我的解决方案,就像你提供的代码一样,我不确定在哪里应用“修复”…这真的是一个修复…它不是一个优雅的方式解决这个问题!然而它确实对我有所帮助,一旦我离开视图寻呼机,我就不需要恢复状态,因此对我来说没有任何不利因素.

我有多个Fragments,它实现了代码的静态位和onDetach(在https://code.google.com/p/android/issues/detail?id=42601#c10上),每个片段都有一个寻呼机,onCreateView我附加了一个扩展FragmentStatePagerAdapter的适配器.

在那些适配器上,我已经覆盖了restoreState方法,什么都不做

    @Override
public void restoreState(Parcelable arg0, ClassLoader arg1) {
    //do nothing here! no call to super.restoreState(arg0, arg1);
}

再次,这不是最好的方式……但它确实解决了我的问题.

祝你好运!

android – GetFragmentManager.findFragmentByTag()返回null

android – GetFragmentManager.findFragmentByTag()返回null

getFragmentManager().beginTransaction()
                .replace(R.id.graph_fragment_holder,new GraphFragment(),"GRAPH_FRAGMENT")
                .commit();

        getFragmentManager().beginTransaction()
                .replace(R.id.list_fragment_holder,new ListFragment(),"LIST_FRAGMENT")
                .commit();

        //getFragmentManager().executePendingTransactions();

        GraphFragment graphFragment = (GraphFragment) getFragmentManager().findFragmentByTag("GRAPH_FRAGMENT");
        graphFragment.setData(data);

        ListFragment listFragment = (ListFragment) getFragmentManager().findFragmentByTag("LIST_FRAGMENT");
        listFragment.setData(data);

我提供了一个标签,所以我不知道为什么findFragmentByTag()返回null.

我从阅读其他问题中尝试过的

> this.setRetainInstance(true)在两个片段的oncreate上.
>两个片段构造函数都是空的public fragmentName(){}.
>在添加片段后尝试执行executePendingTransactions.
>尝试添加而不是替换片段(已编辑)

解决方法

我遇到同样的问题,findFragmentByTag()总是返回null.

最终我跟踪它,我在我的活动中超越了SaveInstanceState(),但没有调用超级.一旦我修复了findFragmentByTag()返回的Fragment按预期.

今天关于是否需要在分离时将Fragment接口侦听器设置为null?的讲解已经结束,谢谢您的阅读,如果想了解更多关于Android Fragment getArguments()返回null、android – FragmentManager.getFragment()NullPointerException、android – FragmentStatePagerAdapter with ChildFragmentManager – FragmentManagerImpl.getFragment导、android – GetFragmentManager.findFragmentByTag()返回null的相关知识,请在本站搜索。

本文标签: