【问题标题】:Android fragment lifecycle issueAndroid片段生命周期问题
【发布时间】:2020-07-14 12:54:03
【问题描述】:

我在我的第一个活动的 onCreate() 中实例化我的片段。在这种情况下可以看到以下应用流程:

  • MainActivity : onCreate()
  • Fragment1 : onAttach() : 在那里我得到一个监听器来从 Activity 中获取数据
  • Fragment1:onCreateView()
  • Fragment2:onAttach()
  • Fragment2:onCreateView()
  • Fragment3:onAttach()
  • Fragment3:onCreateView()
  • ...

我的应用程序运行良好,除非我执行以下步骤: 1 - 打开应用程序 2 - 按主页按钮 3 - 使用内置优化器应用程序强制终止应用程序 4 - 再次打开应用程序

在这种情况下,应用程序是:

  • Fragment1:onAttach()
  • MainActivity : onCreate()
  • Fragment1:onCreateView()
  • ...

因此,我在 onAttach() 方法中获得的侦听器无效,并在我使用接口时导致 NullPointerException !我不明白我该如何解决它。我试图在 onCreatedActivity() 中获取回调,但这会导致我遇到其他问题。

我该如何解决?

公共类 ForecastFragment 扩展 Fragment 实现 OnNewDataSolcastListener、Animation.AnimationListener、OnFailGetDataSolcast {

private ScaleAnimation mStartingAnimation;
private ViewGroup mBubble;
private Solcast mSolcast;
private TextView mTxtConso;
private TextView mTxtConso2;
private TextView mTxtPresentationConso;
private ImageView mImgErrorSolcast;


@Override
public void onAttach(@NonNull Context context) {
    super.onAttach(context);
    Log.e(getClass().getSimpleName(), "onAttach()");


    if(getActivity() instanceof Solcast.GetSolcastListener)
        mSolcast = ((Solcast.GetSolcastListener) getActivity()).getSolcast();
    else
        throw new RuntimeException(getClass().getSimpleName() + " have to implement " + Solcast.GetSolcastListener.class.getSimpleName());


}

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

    Log.e(getClass().getSimpleName(), "onCreateView()");

    final View rootView = inflater.inflate(R.layout.content_main, container, false);


    //init la GUI pour les fonctions qui auront besoin de ces View
    mTxtConso = rootView.findViewById(R.id.txtValeurProduction);
    mTxtConso2 = rootView.findViewById(R.id.txtValeurProduction2);
    mTxtPresentationConso = rootView.findViewById(R.id.txtPresentationProduction);
    mBubble = rootView.findViewById(R.id.bubbleMain);
    mImgErrorSolcast = rootView.findViewById(R.id.imgErrorSolcast);
    mImgErrorSolcast.setVisibility(View.GONE);



    //some stuff...


    //FAIL HERE : mSolcast null
    mSolcast.setSearchDates(start, end);


    return rootView;
}

}

感谢您的帮助

编辑 1

按照 Luis Cardoza Bird 的建议,我将代码放在 onViewCreated() 中。但是我面临另一个问题,我在原帖中很快提到了这个问题。我在 onViewCreated() 的末尾开始了一系列动画。首先,在启动时,会出现一个气泡,然后在后台线程下载 JSON 文件时开始第二个动画(由 mStartingAnimation 表示),在最后一个动画结束时,我想停止onNewDataSolcast() 回调中的 mStartingAnimation。但是我在这个函数中得到了一个 NullPointerException 。我不明白,因为我之前已经开始了,所以我怎么可能得到 NullPointerException ? 正常打开应用没有这个问题。

这是新代码:

public class ForecastFragment extends Fragment implements OnNewDataSolcastListener, Animation.AnimationListener, OnFailGetDataSolcast{



private ScaleAnimation mStartingAnimation;
private ViewGroup mBubble;
private Solcast mSolcast;
private TextView mTxtConso;
private TextView mTxtConso2;
private TextView mTxtPresentationConso;
private ImageView mImgErrorSolcast;


@Override
public void onAttach(@NonNull Context context) {
    super.onAttach(context);
    Log.e(getClass().getSimpleName(), "onAttach()");

}


@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

    Log.e(getClass().getSimpleName(), "onCreateView()");

    return inflater.inflate(R.layout.content_main, container, false);
}


@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    if(getActivity() instanceof Solcast.GetSolcastListener)
        mSolcast = ((Solcast.GetSolcastListener) getActivity()).getSolcast();
    else
        throw new RuntimeException(getClass().getSimpleName() + " have to implement " + Solcast.GetSolcastListener.class.getSimpleName());



    View rootView = getView();
    assert rootView != null;

    //init la GUI pour les fonctions qui auront besoin de ces View
    mTxtConso = rootView.findViewById(R.id.txtValeurProduction);
    mTxtConso2 = rootView.findViewById(R.id.txtValeurProduction2);
    mTxtPresentationConso = rootView.findViewById(R.id.txtPresentationProduction);
    mBubble = rootView.findViewById(R.id.bubbleMain);
    mImgErrorSolcast = rootView.findViewById(R.id.imgErrorSolcast);
    mImgErrorSolcast.setVisibility(View.GONE);



    //on prépare la future animation pour la bulle qui respire
    mStartingAnimation = new ScaleAnimation(1.05f, 1f, 1.05f, 1f, ScaleAnimation.RELATIVE_TO_SELF, 0.5f, ScaleAnimation.RELATIVE_TO_SELF, 0.5f);
    mStartingAnimation.setDuration(1200);
    mStartingAnimation.setInterpolator(new OvershootInterpolator());
    mStartingAnimation.setRepeatCount(Animation.INFINITE);


    //some stuff


    mSolcast.setSearchDates(start, end);


    final ScaleAnimation anim = new ScaleAnimation(0f, 1f, 0, 1f, ScaleAnimation.RELATIVE_TO_SELF, 0.5f, ScaleAnimation.RELATIVE_TO_SELF, 0.5f);
    anim.setDuration(500);
    anim.setInterpolator(new LinearInterpolator());
    anim.setAnimationListener(this);
    mBubble.startAnimation(anim);

}

/*
            Appelée lorsque les données JSON ont été reçues puis traitées.
            Renvoi la liste des énergies @listEnergy associées à leur date dans @listeDate
         */
@Override
public void onNewDataSolcast(ArrayList<Solcast.SolcastData> solcastData) {

    //Les données JSON ont été traitées, triées, etc... On renvoi le résultat vers la GUI


    Log.e("ForecastFragment:onNewDataSolcast", "New data");



    //mStartingAnimation is null : NullPointerException here !
    **mStartingAnimation.cancel();**
    mBubble.clearAnimation();



}







//animation callbacks
@Override
public void onAnimationStart(Animation animation) {

}

@Override
public void onAnimationEnd(Animation animation) {

    //Lorsque la bulle, au démarrage, a fini de grossir on démarre le téléchargement JSON. Cela peut prendre quelques secondes,
    //donc on fait l'animation de la bulle qui "respire" en boucle jusqu'à réception des données

    //on fait apparaitre le texte "consomation estimée..."
    ObjectAnimator anim2 = ObjectAnimator.ofFloat(mTxtPresentationConso, "alpha", 0.0f, 1.0f);
    anim2.setInterpolator(new LinearInterpolator());
    anim2.setDuration(2000);

    anim2.addListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animator) {

        }

        @Override
        public void onAnimationEnd(Animator animator) {


            //start animation - works well
            mBubble.startAnimation(mStartingAnimation);


            //will call onNewDataSolcast() callback at the end of the operations
            mSolcast.readJSON();

        }

        @Override
        public void onAnimationCancel(Animator animator) {

        }

        @Override
        public void onAnimationRepeat(Animator animator) {

        }
    });


    anim2.start();
}

@Override
public void onAnimationRepeat(Animation animation) {

}

}

【问题讨论】:

  • 也附上你的崩溃报告,它会让你的问题更容易理解。

标签: java android android-fragments android-lifecycle


【解决方案1】:

基本上,片段第一次被调用时会调用 onCreate,但是为了解决您的问题,最好的建议是使用 onViewCreated,因为此时片段将已经创建所需的上下文。

public class ForecastFragment extends Fragment implements OnNewDataSolcastListener, Animation.AnimationListener, OnFailGetDataSolcast {

private ScaleAnimation mStartingAnimation;
private ViewGroup mBubble;
private Solcast mSolcast;
private TextView mTxtConso;
private TextView mTxtConso2;
private TextView mTxtPresentationConso;
private ImageView mImgErrorSolcast;    
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

    Log.e(getClass().getSimpleName(), "onCreateView()");

    final View rootView = inflater.inflate(R.layout.content_main, container, false);
    //init la GUI pour les fonctions qui auront besoin de ces View    
    return rootView;
}

@Override
public View onViewCreated(){
if(getActivity() instanceof Solcast.GetSolcastListener)
        mSolcast = ((Solcast.GetSolcastListener) getActivity()).getSolcast();
    else
        throw new RuntimeException(getClass().getSimpleName() + " have to implement " + Solcast.GetSolcastListener.class.getSimpleName());    

        mTxtConso = rootView.findViewById(R.id.txtValeurProduction);
    mTxtConso2 = rootView.findViewById(R.id.txtValeurProduction2);
    mTxtPresentationConso = rootView.findViewById(R.id.txtPresentationProduction);
    mBubble = rootView.findViewById(R.id.bubbleMain);
    mImgErrorSolcast = rootView.findViewById(R.id.imgErrorSolcast);
    mImgErrorSolcast.setVisibility(View.GONE);



    //some stuff...


    //FAIL HERE : mSolcast null
    mSolcast.setSearchDates(start, end);

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多