Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What causes a fragment to get detached from an Activity?

I have a SignupActivity which will go through several fragments as users go through a signup process. On the last fragment, I'm calling

getActivity().setResult(Activity.RESULT_OK) 

since SingupActivity intent was started for result. Some users are crashing at this point, because getActivity() is producing a NPE. I'm not able to figure out what is causing this. Screen rotation is disabled, so there is no reason that I know of for the fragment to detach from the Activity.

Any insight as to what may be causing this, and how I can resolve it?

public class SignupConfirmationFragment extends Fragment {
    public static final String TAG = SignupConfirmationFragment.class.getSimpleName();
    private User mNewUser;
    private myAppClient mmyAppClient;

    private Animation rotateAnimation;
    private ImageView avatar;

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

        mNewUser = ((SignUpActivity) getActivity()).getNewUser();
        mmyAppClient = ((SignUpActivity) getActivity()).getmyAppClient();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        final View v = inflater.inflate(R.layout.fragment_signup_confirmation, null);

        ((TextView) v.findViewById(R.id.username_textView)).setText(((SignUpActivity) getActivity()).getNewUser().getName());
        avatar = (ImageView) v.findViewById(R.id.avatar);

        if (mNewUser.getAvatarImage() != null) {
            avatar.setImageBitmap(mNewUser.getAvatarImage());
        }


        rotateAnimation = AnimationUtils.loadAnimation(getActivity(), R.anim.progress_rotate);
        v.findViewById(R.id.progress_loading).startAnimation(rotateAnimation);

        if (mNewUser.getAvatarImage() != null) {
            startAvatarUpload();
        } else if (mNewUser.getNewsletter()) {
            setNewsletterStatus();
        } else {
            pauseForOneSecond();
        }

        return v;
    }

    private void startAvatarUpload() {
        mmyAppClient.uploadUserAvatar(mNewUser.getAvatarImage(), new FutureCallback<JsonObject>() {
                    @Override
                    public void onCompleted(Exception e, JsonObject result) {
                        if (mNewUser.getNewsletter()) {
                            setNewsletterStatus();
                        } else {
                            updateFragment();
                        }
                    }
                },
                null,
                null);
    }

    private void setNewsletterStatus() {
        mmyAppClient.setNewsletter(mNewUser.getEmail(), mNewUser.getFirstName(), mNewUser.getLastName(), new FutureCallback<String>() {
            @Override
            public void onCompleted(Exception e, String result) {
                //Log.d(TAG, "Result: " + result);
                updateFragment();
            }
        });
    }

    private void pauseForOneSecond() {
        final Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                updateFragment();
            }
        }, 1000);
    }

    private void updateFragment() {
        rotateAnimation.cancel();
        if (isAdded()) {
            getActivity().setResult(Activity.RESULT_OK);
            AnalyticsManager.logUIEvent("sign up completed");
            getActivity().finish();
        } else {
            AnalyticsManager.logUIEvent("sign up failed");
        }

    }
}
like image 881
Shahbaz Sheikh Avatar asked Nov 16 '15 19:11

Shahbaz Sheikh


People also ask

What is called when the fragment is detached from the activity?

You'll notice that when a Fragment is detached, its onPause, onStop and onDestroyView methods are called only (in that order). On the other hand, when a Fragment is removed, its onPause, onStop, onDestroyView, onDestroy and onDetach methods are called (in that order).

Are fragments independent from activities?

A fragment is a reusable class implementing a portion of an activity. A Fragment typically defines a part of a user interface. Fragments must be embedded in activities; they cannot run independently of activities.

Can a fragment without a layout can be attached to an activity?

A fragment is not required to be a part of the Activity layout ; you may also use a fragment without its own UI as an invisible worker for the Activity but it needs to be attached to an Activity in order to appear on the screen.

What happens to fragment when activity is stopped?

The fragment is no longer active and can no longer be retrieved using findFragmentById() . onDetach() is always called after any Lifecycle state changes. Note that these callbacks are unrelated to the FragmentTransaction methods attach() and detach() . For more information on these methods, see Fragment transactions.


1 Answers

According to Fragment lifecycle in Android OS, you cannot get the Activity associated with the fragment in the onCreateView, because the Activity with which the Fragment is associated will not be created at that stage.

See the figure below:

enter image description here

Also, refer to this link, http://developer.android.com/guide/components/fragments.html

As you can see the Activity is created in onActivityCreated which is after onCreateView, hence you'll get null if you try to call the Activity in the onCreateView. Try to call it in onActivityCreated or in onStart that should solve your problem.

I hope this helps.

like image 176
Dania Avatar answered Oct 20 '22 23:10

Dania