I have a Activity with ViewPager, In ViewPager Adapter I provide Fragment for each position.
An example Fragment is DebugFragment. I have written the source code below.
public class DebugFragment extends android.support.v4.app.Fragment {
private OnFragmentInteractionListener mListener;
public interface OnFragmentInteractionListener {
void onFragmentInteraction(int someValue);
}
public static DebugFragment newInstance() {
DebugFragment fragment = new DebugFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
mListener.onFragmentInteraction(0);
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LocalBroadcastManager.getInstance(getContext()).registerReceiver(mMessageReceiver,
new IntentFilter("com.android.example.INITIAL_REQUEST"));
}
@Override
public void onDestroy() {
LocalBroadcastManager.getInstance(getContext()).unregisterReceiver(mMessageReceiver);
super.onDestroy();
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof OnFragmentInteractionListener) {
mListener = (OnFragmentInteractionListener) context;
} else {
throw new RuntimeException(context.toString()
+ " must implement OnFragmentInteractionListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
@Override
public void onResume() {
super.onResume();
getUserData();
}
public void getUserData() {
// Inside Background Thread
if (getActivity() == null) {
return;
}
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
mListener.onFragmentInteraction(0); // This line throws NPE
}
});
}
My Activity implementation below.
public class DebugActivity extends AppCompatActivity implements
DebugFragment.OnFragmentInteractionListener {
// Other Activity Callback
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
DebugFragment debugFragment = ((DebugFragment) mViewPagerAdapter.getRegisteredFragment(2));
if (debugFragment != null) {
debugFragment.getUserData();
}
}
}
}
}
I call getUserData of my DebugFragment from onResume of Fragment, BroadcastReceiver, OnActivityResult of Activity.
Sometime I get NullPointerException in getUserData while trying to access FragmentListener i.e mListener. I want to know Why?
As i am already checking for Activity null. Isn't this enough. Do i have to check for null of mListener also? It would be great if somebody will explain me the case where activity will not be null but my mListener will be null. I have kept my activity in Portrait mode only.
Edit
My Adapter code
public abstract class TabPagerAdapter extends FragmentPagerAdapter {
public TabPagerAdapter(FragmentManager fm) {
super(fm);
}
public abstract View getTabView(int position);
}
public class SecondaryPagerAdapter extends TabPagerAdapter {
private static final int NUM_PAGES = 5;
private String tabTitles[] = new String[] { "Today", "New", "Calendar", "In-progress", "Invoices" };
private int[] imageResId = { R.drawable.ic_tab_hired_pro, R.drawable.ic_tab_history,
R.drawable.ic_tab_today, R.drawable.ic_tab_inprogress, R.drawable.ic_tab_invoices };
SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();
public SecondaryPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
case 1:
case 3:
return ServiceRequestFragment.newInstance(tabTitles[position]);
case 2:
return DebugFragment.newInstance();
case 4:
return InvoicesFragment.newInstance();
default:
throw new RuntimeException("No fragment for this position");
}
}
@Override
public int getCount() {
return NUM_PAGES;
}
@Override
public View getTabView(int position) {
CustomTab customTab = new CustomTab(DashBoardActivity.this);
customTab.bindWith(imageResId[position], tabTitles[position]);
return customTab;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
return fragment;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
super.destroyItem(container, position, object);
}
public Fragment getRegisteredFragment(int position) {
return registeredFragments.get(position);
}
}
From my Activity i call it like
mSecondaryPagerAdapter = new SecondaryPagerAdapter(getSupportFragmentManager());
mSecondaryPager = (ViewPager) findViewById(R.id.dashboard_pager);
mSecondaryPager.setOffscreenPageLimit(4);
mSecondaryPager.setAdapter(mSecondaryPagerAdapter);