Android. Fragment getActivity() sometimes returns null Android. Fragment getActivity() sometimes returns null android android

Android. Fragment getActivity() sometimes returns null


It seems that I found a solution to my problem.Very good explanations are given here and here.Here is my example:

pulic class MyActivity extends FragmentActivity{private ViewPager pager; private TitlePageIndicator indicator;private TabsAdapter adapter;private Bundle savedInstanceState; @Overridepublic void onCreate(Bundle savedInstanceState) {    ....     this.savedInstanceState = savedInstanceState;    pager = (ViewPager) findViewById(R.id.pager);;    indicator = (TitlePageIndicator) findViewById(R.id.indicator);    adapter = new TabsAdapter(getSupportFragmentManager(), false);    if (savedInstanceState == null){            adapter.addFragment(new FirstFragment());        adapter.addFragment(new SecondFragment());    }else{        Integer  count  = savedInstanceState.getInt("tabsCount");        String[] titles = savedInstanceState.getStringArray("titles");        for (int i = 0; i < count; i++){            adapter.addFragment(getFragment(i), titles[i]);        }    }    indicator.notifyDataSetChanged();    adapter.notifyDataSetChanged();    // push first task    FirstTask firstTask = new FirstTask(MyActivity.this);    // set first fragment as listener    firstTask.setTaskListener((TaskListener) getFragment(0));    firstTask.execute();}private Fragment getFragment(int position){     return savedInstanceState == null ? adapter.getItem(position) : getSupportFragmentManager().findFragmentByTag(getFragmentTag(position));}private String getFragmentTag(int position) {    return "android:switcher:" + R.id.pager + ":" + position;} @Overrideprotected void onSaveInstanceState(Bundle outState) {    super.onSaveInstanceState(outState);    outState.putInt("tabsCount",      adapter.getCount());    outState.putStringArray("titles", adapter.getTitles().toArray(new String[0]));} indicator.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {        @Override        public void onPageSelected(int position) {            Fragment currentFragment = adapter.getItem(position);            ((Taskable) currentFragment).executeTask();        }        @Override        public void onPageScrolled(int i, float v, int i1) {}        @Override        public void onPageScrollStateChanged(int i) {} });

The main idea in this code is that, while running your application normally, you create new fragments and pass them to the adapter. When you are resuming your application fragment manager already has this fragment's instance and you need to get it from fragment manager and pass it to the adapter.

UPDATE

Also, it is a good practice when using fragments to check isAdded before getActivity() is called. This helps avoid a null pointer exception when the fragment is detached from the activity. For example, an activity could contain a fragment that pushes an async task. When the task is finished, the onTaskComplete listener is called.

@Overridepublic void onTaskComplete(List<Feed> result) {    progress.setVisibility(View.GONE);    progress.setIndeterminate(false);    list.setVisibility(View.VISIBLE);    if (isAdded()) {        adapter = new FeedAdapter(getActivity(), R.layout.feed_item, result);        list.setAdapter(adapter);        adapter.notifyDataSetChanged();    }}

If we open the fragment, push a task, and then quickly press back to return to a previous activity, when the task is finished, it will try to access the activity in onPostExecute() by calling the getActivity() method. If the activity is already detached and this check is not there:

if (isAdded()) 

then the application crashes.


Ok, I know that this question is actually solved but I decided to share my solution for this. I've created abstract parent class for my Fragment:

public abstract class ABaseFragment extends Fragment{    protected IActivityEnabledListener aeListener;    protected interface IActivityEnabledListener{        void onActivityEnabled(FragmentActivity activity);    }    protected void getAvailableActivity(IActivityEnabledListener listener){        if (getActivity() == null){            aeListener = listener;        } else {            listener.onActivityEnabled(getActivity());        }    }    @Override    public void onAttach(Activity activity) {        super.onAttach(activity);        if (aeListener != null){            aeListener.onActivityEnabled((FragmentActivity) activity);            aeListener = null;        }    }    @Override    public void onAttach(Context context) {        super.onAttach(context);        if (aeListener != null){            aeListener.onActivityEnabled((FragmentActivity) context);            aeListener = null;        }    }}

As you can see, I've added a listener so, whenever I'll need to get Fragments Activity instead of standard getActivity(), I'll need to call

 getAvailableActivity(new IActivityEnabledListener() {        @Override        public void onActivityEnabled(FragmentActivity activity) {            // Do manipulations with your activity        }    });


The best to get rid of this is to keep activity reference when onAttach is called and use the activity reference wherever needed, for e.g.

@Overridepublic void onAttach(Context context) {    super.onAttach(context);    mContext = context;}@Overridepublic void onDetach() {    super.onDetach();    mContext = null;}

Edited, since onAttach(Activity) is depreciated & now onAttach(Context) is being used