I have loader fragment and I am calling another fragment from the loader fragment.Everything is working fine but suddenly my fragment loader is giving me an error.In the loader fragment I am displaying progress bar for 5sec and after that another fragment will display.
Here is my code:-
loader fragment.java
package com.example.user.attendance;
public class Loader_fragment extends Fragment {
AVLoadingIndicatorView Loader;
Runnable runnable;
Handler handler;
FragmentManager fragmentManager;
FragmentTransaction fragmentTransaction;
Timer timer;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View loadder_fragment=inflater.inflate(R.layout.fragment_loader_fragment, container, false);
Loader=(AVLoadingIndicatorView)loadder_fragment.findViewById(R.id.loder_login);
handler=new Handler();
runnable=new Runnable() {
#Override
public void run() {
Loader.setVisibility(View.INVISIBLE);
timer.cancel();
fragmentManager=getFragmentManager();
fragmentTransaction=fragmentManager.beginTransaction();
fragmentTransaction.setCustomAnimations(R.animator.slide_in_left,R.animator
.slide_out_left,R.animator.slide_in_right,R.animator.slide_out_right);
Home_Screen home_screen=new Home_Screen();
fragmentTransaction.replace(R.id.Home_screen_fragment,home_screen);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
};
timer=new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
handler.post(runnable);
}
}, 5000,5000);
/* if(Loader.setVisibility(View.INVISIBLE)==1){
}*/
return loadder_fragment;
}
}
Logcat is showing an error:-
Process: com.example.user.attendance, PID: 1200
java.lang.NullPointerException: Attempt to invoke virtual method 'android.app.FragmentTransaction android.app.FragmentManager.beginTransaction()' on a null object reference
at com.example.user.attendance.Loader_fragment$1.run(Loader_fragment.java:44)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:7402)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Why it is showing null object reference in the fragment.
Don't perform View manipulation in onCreateView. Instead, move it to onViewCreated method. Reason: your fragment has not yet setup the views.
Besides, replace:
fragmentManager = getFragmentManager();
with the following:
fragmentManager = getChildFragmentManager();
Try this
FragmentTransaction fragmentTransaction = getActivity()
.getFragmentManager().beginTransaction();
fragmentTransaction.setCustomAnimations(R.animator.slide_in_left,
R.animator.slide_out_left,
R.animator.slide_in_right,
R.animator.slide_out_right);
fragmentTransaction.replace(R.id.Home_screen_fragment, home_screen);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
Related
I want to refresh fragment by clicking retry button in onCreateView.
If my internet is disconnected it must return fragment_no_internet_error layout. There is a button to reload fragment.
It gives me the error:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: ir.hamedanmelk.hamedanmelk, PID: 21310
java.lang.NullPointerException: Attempt to read from field 'androidx.fragment.app.FragmentManager androidx.fragment.app.Fragment.mFragmentManager' on a null object reference
at androidx.fragment.app.BackStackRecord.detach(BackStackRecord.java:220)
my OnCreateView:
#SuppressLint("SetJavaScriptEnabled")
#Override
public View onCreateView(LayoutInflater inflater, final ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v;
CheckConnectivity checkConnectivity=new CheckConnectivity();
if(!checkConnectivity.isNetworkAvailable(getActivity())) {
v=inflater.inflate(R.layout.fragment_no_internet_error, container, false);
Button retrybutton = (Button)v.findViewById(R.id.no_internet_fragment_button_retry);
retrybutton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Fragment frg = getActivity().getSupportFragmentManager().findFragmentById(R.id.HelpFragment);
final FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
ft.detach(frg);
ft.attach(frg);
ft.commit();
}
});
return v;
}
v=inflater.inflate(R.layout.fragment_f_a_q, container, false);
mwebview = (WebView) v.findViewById(R.id.webview_f_a_q);
WebSettings webSettings=mwebview.getSettings();
webSettings.setJavaScriptEnabled(true);
final ProgressDialog progressDialog = new ProgressDialog(getActivity());
//TODO Change FontFace https://stackoverflow.com/questions/3900658/how-to-change-font-face-of-webview-in-android
mwebview.setWebViewClient(new WebViewClient(){
return v;
}
}
Try to use this code. Becuase I think the issue is with API level
FragmentTransaction transaction = mActivity.getFragmentManager()
.beginTransaction();
if (Build.VERSION.SDK_INT >= 26) {
transaction.setReorderingAllowed(false);
}
transaction.detach(this).attach
(this).commit();
try this.
in your fragment
((MainActivity)getActivity()).reload()
in your MainActivity
void reload(){
final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
// R.id.fragment_layout is your fragment container view
ft.replace(R.id.fragment_layout, instanceFragment);
ft.commit()
}
I want to reach fragment item in Activity method but i get a null pointer error.
Fragment Class
Button button;
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.fragment, container, false);
button= view.findViewById(R.id.button);
return view;
}
public Button getButton(){
return button;
}
MainActivity
FragmentManager fm = getSupportFragmentManager();
Fragment fragment = (Fragment)fm.findFragmentById(R.id.Framelayout);
fragment.getButton().setText("Test");
LOGCAT
java.lang.NullPointerException: Attempt to invoke virtual method
'android.widget.Button com.example.android.fragment.Fragment.getButton()'
on a null object reference
at
com.example.android.MainActivity$1$1.onDataChange(MainActivity.java:141)
For adding the fragment
private void addFragment(FragmentManager manager)
{
YOURFRAGMENT fragment= new YOURFRAGMENT();
FragmentTransaction transaction=manager.beginTransaction();
transaction.add(CONTAINER-ID,fragment,YOURFRAGMENT.class.getSimpleName()).commitNow();
}
for getting the fragment
private void getFragment(FragmentManager manager,String TAG){
YOURFRAGMENT fragment= (YOURFRAGMENT) manager.findFragmentByTag(TAG);
if(fragment!=null){
//access button here
}
}
to get yours
getFragment(fragmentManager, YOURFRAGMENT.class.getSimpleName())k
Add the Fragment using TAG
String TAG="YourTAG";
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.fragment_container, mFragment, TAG)
.commit();
You can invoke a method from your activity like this
Fragment fragment = getSupportFragmentManager().findFragmentByTag(TAG);
if (fragment instanceof YourFragmentClass ) {
fragment.getButton().setText("Test");
}
Hope it helps you.
try with getFragmentManager() instead of getSupportFragmentManager()
I have a MainActivity inside I create ViewPager withFragments. I am using savedInstanceState to store values to set TextView after orientation changed. I also want to change value e.g. using button in MainActivity. Button works properly, but if I change the orientation then Button cannot set TextView in Fragment because TextView is now null.
MyFragment
public class MyFragment extends Fragment {
private TextView textView;
private String info;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.item_weather, container, false);
textView = view.findViewById(R.id.text_view);
Bundle bundle = getArguments();
info = bundle.getString("info");
setInfo(info);
return view;
}
public void setInfo(String info) {
this.info = info;
textView.setText(info); //here is the error
}
}
In MainActivity.java in OnCreate
myFragment = new MyFragment();
viewPager = findViewById(R.id.viewpager);
viewPager.setOffscreenPageLimit(10);
List<Fragment> fragments = new ArrayList<>();
fragments.add(myFragment);
pagerAdapter = new MyPageAdapter(getSupportFragmentManager(), fragments);
viewPager.setAdapter(pagerAdapter);
MyPagerAdapter looks like this:
public class MyPageAdapter extends FragmentStatePagerAdapter {
private List<Fragment> fragments;
public MyPageAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
this.fragments = fragments;
}
#Override
public Fragment getItem(int position) {
return fragments.get(position);
}
#Override
public int getCount() {
return fragments.size();
}
}
As I said everything works, but after orientation chage if I use Button I got an error:
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
Any ideas how to solve this?
edit:
full error
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.app.myapp, PID: 15400
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference
at com.example.app.myapp.fragments.myFragment.setInfo(myFragment.java:53)
at com.example.app.myapp.MainActivity.onOptionsItemSelected(MainActivity.java:195)
at android.app.Activity.onMenuItemSelected(Activity.java:3543)
at android.support.v4.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:407)
at android.support.v7.app.AppCompatActivity.onMenuItemSelected(AppCompatActivity.java:195)
at android.support.v7.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:108)
at android.support.v7.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:108)
at android.support.v7.app.ToolbarActionBar$2.onMenuItemClick(ToolbarActionBar.java:63)
at android.support.v7.widget.Toolbar$1.onMenuItemClick(Toolbar.java:203)
at android.support.v7.widget.ActionMenuView$MenuBuilderCallback.onMenuItemSelected(ActionMenuView.java:780)
at android.support.v7.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:822)
at android.support.v7.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:171)
at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:973)
at android.support.v7.view.menu.MenuPopup.onItemClick(MenuPopup.java:127)
at android.widget.AdapterView.performItemClick(AdapterView.java:318)
at android.widget.AbsListView.performItemClick(AbsListView.java:1159)
at android.widget.AbsListView$PerformClick.run(AbsListView.java:3136)
at android.widget.AbsListView$3.run(AbsListView.java:4052)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Into the fragment try to initialize the textView in the on the onViewCreated method:
#Override
public View onViewCreated(view: View, savedInstanceState: Bundle) {
// Your initialization code here
}
Solution:
Ok, EpicPandaForce thanks for hints.
To solve this i used in MainActivity
#Override
protected void onResume() {
super.onResume();
viewPager.setAdapter(pagerAdapter);
}
#Override
protected void onPause() {
super.onPause();
viewPager.setAdapter(null);
}
MainActivity.java
btn_search.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentOne fragment = new FragmentOne();
fragmentTransaction.add(R.id.layoutFragmentContainer, fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
});
...
FragmentOne.java
public class FragmentOne extends Fragment {
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.list,container,false);
}
}
When I click the button search , the fragment appears , but when I click it again the application crashes.Can someone help , I am new in android and I can't solve this problem.
....
log:
Process: com.example.user1.volleyballmanager, PID: 26892
java.lang.IllegalStateException: commit already called
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:625)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:617)
at com.example.user1.volleyballmanager.MainActivity$2.onClick(MainActivity.java:52)---
line 52 : fragmentTransaction.commit();
at android.view.View.performClick(View.java:5156)
at android.view.View$PerformClick.run(View.java:20755)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:5832)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
Put this method into your main activity
//FRAGMENT BACK STACK
public void getFragmentWithTag(Fragment fragment, String tag) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.addToBackStack(null);
transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
transaction.replace(R.id.activityFrame, fragment, tag).commit();
}
You can call it from your fragment like this..
activity.getFragmentWithTag(Fragment, FragmentTag)
you cannot have multiple transaction commits.
So you need to begin and close the transaction. So when you click one, it works. Then you click again, and it give you error which says one transaction<--> one commit.
I am using a ViewPager fragment which has two fragments as children. This works great, however when I replace the ViewPager fragment by another fragment and replace this fragment by the ViewPager fragment my application crashes with the following NullPointerException:
java.lang.NullPointerException: Attempt to invoke virtual method 'int java.util.ArrayList.size()' on a null object reference
at android.support.v4.app.FragmentManagerImpl.getFragment(FragmentManager.java:667)
at android.support.v4.app.FragmentStatePagerAdapter.restoreState(FragmentStatePagerAdapter.java:211)
at android.support.v4.view.ViewPager.onRestoreInstanceState(ViewPager.java:1319)
at android.view.View.dispatchRestoreInstanceState(View.java:13756)
at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:2888)
at android.view.View.restoreHierarchyState(View.java:13734)
at android.support.v4.app.Fragment.restoreViewState(Fragment.java:468)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1094)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1248)
at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:738)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1613)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:517)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5294)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:904)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)
My ViewPager fragment consists of the following source code instanciating the two child fragments in case they are null. Furthermore, the ViewPagerAdapter implementation is instanciated and assigned to the ViewPager.
public class ConnectionPasswordViewPagerFragment extends Fragment
{
private ViewPager vpConnectionPassword;
private ConnectionPasswordViewPagerAdapter paConnectionPassword;
private ConnectionPasswordGeneratorMACAddress passwordGeneratorMACAddress;
private ConnectionPasswordGeneratorSerialNumber passwordGeneratorSerialNumber;
public ConnectionPasswordViewPagerFragment()
{
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if ((this.passwordGeneratorSerialNumber == null) && (this.passwordGeneratorMACAddress == null))
{
this.passwordGeneratorMACAddress = new ConnectionPasswordGeneratorMACAddress();
this.passwordGeneratorSerialNumber = new ConnectionPasswordGeneratorSerialNumber();
}
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState)
{
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_connection_password_view_pager, container, false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
/*if (this.paConnectionPassword == null)
{*/
this.paConnectionPassword = new ConnectionPasswordViewPagerAdapter(this.getChildFragmentManager(), this.getActivity(), this.passwordGeneratorMACAddress, this.passwordGeneratorSerialNumber);
//}
this.vpConnectionPassword = (ViewPager) this.getActivity().findViewById(R.id.vpConnectionPassword);
this.vpConnectionPassword.setAdapter(this.paConnectionPassword);
}
}
The ViewPagerAdapter shown below implementation keeps the reference to the child fragments in an ArrayList and implements the metods getItem(), getCount() as well as getPageTitle(). The class ViewPagerFragment simply extends the support Fragment class and provides the abstract method getPageTitleStringID() implemented by the child fragments.
public class ConnectionPasswordViewPagerAdapter extends FragmentStatePagerAdapter
{
private static final byte NUMBER_OF_FRAGMENTS = (byte) 2;
private ArrayList<ViewPagerFragment> childFragments;
private Activity displayActivity;
public ConnectionPasswordViewPagerAdapter(FragmentManager fragmentMgm, Activity displayAct, ConnectionPasswordGeneratorMACAddress generatorMACAddress, ConnectionPasswordGeneratorSerialNumber generatorSerialNumber)
{
super(fragmentMgm);
this.childFragments = new ArrayList<>(ConnectionPasswordViewPagerAdapter.NUMBER_OF_FRAGMENTS);
this.setDisplayActivity(displayAct);
if (generatorMACAddress != null)
{
this.childFragments.add(generatorMACAddress);
}
if (generatorSerialNumber != null)
{
this.childFragments.add(generatorSerialNumber);
}
}
public Activity getDisplayActivity()
{
return this.displayActivity;
}
public void setDisplayActivity(Activity value)
{
this.displayActivity = value;
}
#Override
public Fragment getItem(int position)
{
return this.childFragments.get(position);
}
#Override
public int getCount()
{
return ConnectionPasswordViewPagerAdapter.NUMBER_OF_FRAGMENTS;
}
#Override
public CharSequence getPageTitle(int position)
{
return this.getDisplayActivity().getString(this.childFragments.get(position).getPageTitleStringID());
}
}
Thanks for your help!
I fixed the issue by simply creating the fragment containing the view pager every time I call the support fragment manager's replace method.
public void onSwitchToConnectionPasswordGenerator(View clickedView)
{
this.fragConnectionPassword = new ConnectionPasswordViewPagerFragment();
this.getSupportFragmentManager().beginTransaction().replace(R.id.flFragmentContainer, this.fragConnectionPassword).commitAllowingStateLoss();
}
I think your Viewpager is in Fragment, and this fragment have setRetainInstance set to true (i have this error too when i try to retain the parent fragment)
Better way is to you can check for FragmentManager to get Fragment if its there, if not then create a new instance as follows:
FragmentManager manager = getSupportFragmentManager();
Fragment fragment = manager.findFragmentByTag("YourFragmentName");
if(fragment == null)
fragment = new YourFragment();
FragmentTransaction fragmentTransaction = manager.beginTransaction();
fragmentTransaction.replace(Your_Fragmnet_Container_Layout_id, fragment, fragment.getClass().getSimpleName());
fragmentTransaction.commit;