java.lang.NullPointerException: (Fragment) - java

I'm trying to create a Navigation Menu + Tabs, the code for this is fine.
Now I've implemented some code I had as an Activity in a Fragment in order to add it to the Tabs viewer.
When I run the code the app works just fine..
Until I swipe right to the other Tab and then the App crashed and I get this from the logcat:
java.lang.NullPointerException: Attempt to write to field 'android.support.v4.app.FragmentManagerImpl android.support.v4.app.Fragment.mFragmentManager' on a null object reference
I'm leaving you my Main Activity, 'cause I think there's the issue, if you think you might need some Fragments like the Tabs, please just ask!
CODE: http://pastebin.com/TTcJMR77

You have to add default case on your switch in getItem(int position) method:
default:
return new Fragment();
Instead of
return null;
Like this:
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new YourFragment();
default:
return new Fragment();
}
}

Related

Fragment Pager Adapter only displaying last fragment created

I have a similar problem to the one described here: ViewPager only displaying last fragment, but after attempting the solution there I'm still having the same issue.
I have an app with a TabLayout, which displays 3 fragments. The 3 fragments have the same layout, but the content (text, etc...) of said layouts change depending on the position in the TabLayout. Tab 1 displays one thing, tab 2 another, etc. I do this by passing one class or another to the fragment to be displayed depending on the position passed to getItem() in the pager adapter.
What I'm seeing is that no matter what fragments I attempt to load, my tab layout will always display 3 instances of the same fragment, in this case the last one that gets instantiated. I've stepped through the code and sure enough 3 different fragments get instantiated and returned in getItem() the 3 times its called, but only the one that is returned last is set onto the TabLayout, 3 times.
How can I get it to display the 3 distinct fragments, and not the same one 3 times?
Code used:
#Override
public Fragment getItem(int position) {
MyFragment fragment = new MyFragment();
if (position == 0) {
fragment = MyFragment.newInstance(MyClass1, position); // this gets returned first
} else if (position == 1){
fragment = MyFragment.newInstance(MyClass2, position); // this gets returned second
} else if (position == 2){
fragment = MyFragment.newInstance(MyClass3, position); // this gets returned third and is the only fragment displayed in the 3 tabs
}
return fragment;
}
I believe the issue must be somewhere there, but tell me if I need to share/change other parts of code
EDIT: This is my newInstance() function in my fragment class
public static MarkStudentFragment newInstance(MyClass inputClass, int inputPosition) {
MyFragment fragment = new MyFragment();
dataClass = inputClass;
position = inputPosition;
return fragment;
}
dataClass then gets used to set up the layout of the fragment, etc
public static MarkStudentFragment newInstance(MyClass inputClass, int inputPosition) {
MyFragment fragment = new MyFragment();
dataClass = inputClass;
position = inputPosition
return fragment;
}
If this actually compiles, it is because you have declared dataClass and position as static. So, each time you call newInstance(), you overwrite the previous dataClass and position values. And each of your fragments will use the one-and-only value of dataClass and position.
To fix this, get rid of the dataClass and position fields, and use the arguments Bundle. Note that you will need to switch from passing an instance of MyClass to passing some identifier that will allow the fragment to get the proper data (e.g., an enum).
We have a method in fragment called getUsetVisibleHint().. by using this when the fragment is visible we can call the api or fetch details and attach to layout..
you can put code like this
public Fragment getItem(int i)
{
switch (i)
{
case 0:
Fragment fragment1=new Fragment();
return fragment1;
case 1:
Fragment fragment2=new Fragment();
return fragment2;
case 2:
Fragment fragment3=new Fragment();
return fragment3;
default:
return null;
}
}

Restarting Activity on Specific Fragment, when Using a Separate FragmentPagerAdapter

Background
I have an android app using fragments. I'm using a separate FragmentPagerAdapter (i.e. as a separate class, outside MainActivity).
MainActivity.java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.MainActivity);
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabLayout);
tabLayout.setupWithViewPager(mViewPager);
}
SectionsPagerAdapter.java
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new frag1();
case 1:
return new frag2();
case 2:
return new frag3();
case 3:
return new frag4();
case 4:
return new frag5();
default:
return null;
}
}
#Override
public int getCount() {
return 5;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "Name1";
case 1:
return "Name2";
case 2:
return "Name3";
case 3:
return "Name4";
case 4:
return "Name5";
}
return null;
}
The Issue
I need to refresh the view of, say, fragment #3 from fragment#2 (the ultimate goal is for changes the user initiates on fragment #2 to be visible as soon as the user proceeds to fragment#3. I have tried to detach/attach fragment #3 itself as soon as it is visible, like this:
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
getFragmentManager().beginTransaction().detach(this).attach(this).commit();
}
Unfortunately, a) this has a penalty in performance, as there is a "stutter" during navigation; b) it doesn't work reliably. Some things (the texts of some buttons) are not refreshed, for some reason I can't figure out.
In any case, I have discovered that the only 100% reliable method for forcing a refresh/redraw is to restart the activity (for example through an onClickListener on a Save button the user needs to press on the previous fragment, #2). But this restarts the Activity on fragment #1
My Question
How can I restart the activity on this specific fragment (#3), considering the fact I'm using a separate FragmentPagerAdapter?
I've studied several other questions/answers, for example this: https://stackoverflow.com/a/36064344
but how can I implement something like this (putting extras on the intent call) when the FragmentPagerAdapter is on a separate class? Alternatively, is there something else I can do to refresh the fragment view?
If you need extra info or code, let me know and I'd be glad to add clarification.
EDIT:
I managed to find another solution that so far seems to be working as intended. I added the following code on the onClickListener of the Save button on fragment #2
frag3 f3 = new frag3();
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.fragmentContainer, f3);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.commit();
However, I'm still interested in my original question (how to start an activity on a specific fragment when using a separate FragmentPagerAdapter), so if you have any ideas about that, I'm all ears.
Well, wasn't that simple...
this.recreate(); not only restarts the activity but it also remembers the fragment position.
Just in case someone else needs this, when you're working from fragments you need to use it this way:
First declare the activity which contains the fragment in question. E.g.
public class frag1 extends Fragment {
...
Activity mactivity;
#Override
public void onAttach(Activity MainActivity) {
super.onAttach(MainActivity);
mactivity = MainActivity;
}
Then instead of getActivity().recreate(); simply use mactivity.recreate();

Dagger 2, MVVM: Adding a third tab and going back and forth crashes the app

I've been playing with this github repo: https://github.com/patloew/countries to learn DI, mvvm, realm, and all that good stuff. When I add a third tab in MainAdapter.java:
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new AllCountriesFragment();
case 1:
return new FavoriteCountriesFragment();
//case 2:
// return new FavoriteCountriesFragment();
}
return null;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return res.getString(R.string.tab_title_all);
case 1:
return res.getString(R.string.tab_title_favorites);
//case 2:
// return res.getString(R.string.tab_title_favorites);
}
return null;
}
I get an exception in BaseFragment.java:
protected final View setAndBindContentView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState, #LayoutRes int layoutResID) {
if (viewModel == null)
throw new IllegalStateException("viewModel must already be set via injection");
java.lang.IllegalStateException: viewModel must already be set via injection
The third fragment doesn't have to be identical to the second, it's actually a completely new fragment. Commenting out the viewModel in onDestroyView
//viewModel = null;
avoids the crash but strange things happen afterwards.
Any pointers on what to do to help me understand the bigger picture and fix this? The question really is why isn't the viewModel being injected on a tab change. Thanks a lot.
Replacing FragmentPagerAdapter with FixedFragmentStatePagerAdapter from Adam's blog seemed to avoid the problem (viewModel = null). However, as you correctly pointed out, fragmentComponent().inject(this) was not being called in OnCreateView but rather in onCreate. All good now. Thank you very much for your input.

Android layout getting wrapped when keyboard appears

In my application I have two tabs, for which I am using ViewPager, two fragments are within this view pager. Sometimes when I tap on first tabs fragments EditBox keyboard pops, once I am done with the input keyboard disappears. But layout below keyboard region goes blank (White), this is happening sometimes, specially second launch of application. When application is launched from studio for first time issue doesn't appear. But when I launch it through system application by tapping on its ic_launhcher issue comes again. What are the possible causes of issue ?
The layout on launch looks like :
After I click on edit box & edit some text in address filed, when keyboard disappears, layout looks like :
I am using view pager inside another fragment & using FragmentStatePagerAdapter by passing a getChildFragmentManager()
private void setupViewPager(ViewPager viewPager) {
FragmentStatePagerAdapter fragmentStatePagerAdapter = new FragmentStatePagerAdapter(getChildFragmentManager()) {
#Override
public Fragment getItem(int position) {
Fragment fragment = null;
switch (position) {
case 0:
fragment = new GeneralInfoFragment();
Bundle bundle = new Bundle();
bundle.putString(context.getString(R.string.all_data), new Gson().toJson(profileResponse));
fragment.setArguments(bundle);
break;
case 1:
fragment = new ICEFragment();
break;
default:
return null;
}
return fragment;
}
#Override
public int getCount() {
return 2;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "General Info";
case 1:
return "ICE";
}
return "";
}
};
Note : Images are erased to protect privacy
Edit:
Put this code in your manifest file in your activity tag
android:configChanges="keyboard|keyboardHidden|orientation|
screenLayout|uiMode|screenSize|smallestScreenSize"
android:windowSoftInputMode="stateHidden|adjustPan"
Or
Try this one
setContentView(R.layout.activity_direction_3);
getWindow().getDecorView().setBackgroundColor(
android.R.color.transparent);
Or
if you have are using a custom theme then add this in your theme
<item name="android:windowBackground">Transparent color </item>
Tel me if you still get the issue.

View pager different results

I am using view pager with 3 tabs in MainActivity of my app to show grid images. I have one MovieFragment for all 3 tabs and I am using FragmentsPagerAdapter to create new instance of MovieFragment everytime tab is changed.
//FragmentsPagerAdapter method
#Override
public Fragment getItem(int position) {
switch (position){
case 0: return MoviesFragment.newInstance(buildUrl(Utility.POPULAR_URL));
case 1: return MoviesFragment.newInstance(buildUrl(Utility.RATED_URL));
case 2: return MoviesFragment.newInstance("favorite");
default: return null;
}
}
//Fragment method
public static MoviesFragment newInstance(String uri){
MoviesFragment fragment = new MoviesFragment();
Bundle bundle = new Bundle();
bundle.putString("fragment", uri);
fragment.setArguments(bundle);
return fragment;
}
Now I was getting different results in my app so I debugged this method and I found it calls methods before tab is selected i.e when I open app it creates instances for case 0 and case 1 and when I go to second tab it creates instance for case 2.
Now in my second tab when I make changes to database and try to get them in third tab changes are not reflected as it already created instance of third tab when second tab was selected.
How do I solve this problem?
#Sahil This is because in android ViewPager keeps track of previous and next pages only. So when you initialize the viewPager it automatically create first 2 page and call MoviesFragment for 1st two tab. And once you start scrolling through, it starts keeping the track of only previous and next page.
Read this

Categories