I have this problem when working on communicating from the main activity to fragment. The Monitor keeps saying:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.example.mick.myApplication.FragmentCal.readfiles(java.util.LinkedList)' on a null object reference
at com.example.mick.myApplication.main.onCreate(main.java:101)
at android.app.Activity.performCreate(Activity.java:6289)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2646)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2758)
at android.app.ActivityThread.access$900(ActivityThread.java:177)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1448)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:5942)
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)
This is the code for fragment transaction and sending the message:
fragmentinfo = new FragmentInfo();
fragmentcal = new FragmentCal();
fragmentrep = new FragmentRep();
fragmentdicn = new FragmentDicn();
fragmentManager = getSupportFragmentManager();
if (!fragmentcal.isAdded()) {
if (currentFragment == null) {
fragmentManager.beginTransaction().add(R.id.fragmentlayout, fragmentcal).commit();
} else {
fragmentManager.beginTransaction().hide(currentFragment).add(R.id.fragmentlayout, fragmentcal).commit();
}
FragmentCal fragmentCal = (FragmentCal) getSupportFragmentManager().findFragmentById(R.id.fragmentlayout);
fragmentCal.readfiles(nameList);
} else {
fragmentManager.beginTransaction().hide(currentFragment).show(fragmentcal).commit();
}
currentFragment = fragmentcal;
And for that, I import android.support.v4.app.Fragment for all activities and fragments.
You can't perform a findFragmentById before adding the fragment to your activity. When you make a setContentView the Activity inflates the layout and adds its views to the current window. In the case of having a Fragment in this layout, it is added with the given Id or Tag provided in the xml to the FragmentManager. Only in this moment you can find it there. So what you have to do is move the findFragmentById below the setContentView.
Source: NullpointerException when findFragmentById
Hope it helps! Good luck!
Related
When I click the show more button a new fragment opens. However if I rotate the device and then click it I get an error.
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.rekijan.initiativetrackersecondedition, PID: 4673
java.lang.IllegalStateException: FragmentManager has been destroyed
at androidx.fragment.app.FragmentManager.enqueueAction(FragmentManager.java:1878)
at androidx.fragment.app.BackStackRecord.commitInternal(BackStackRecord.java:329)
at androidx.fragment.app.BackStackRecord.commit(BackStackRecord.java:294)
at com.rekijan.initiativetrackersecondedition.ui.activities.MainActivity.replaceCharacterDetailFragment(MainActivity.java:207)
at com.rekijan.initiativetrackersecondedition.character.adapter.CharacterAdapter$2.onClick(CharacterAdapter.java:305)
at android.view.View.performClick(View.java:7448)
at android.view.View.performClickInternal(View.java:7425)
at android.view.View.access$3600(View.java:810)
at android.view.View$PerformClick.run(View.java:28305)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
So the code is in a RecyclerViewAdapter
holder.showCharacterDetailButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
((MainActivity)context).replaceCharacterDetailFragment(holder.getAdapterPosition());
}
});
And then in MainActivity
public void replaceCharacterDetailFragment(int position) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
if (getResources().getBoolean(R.bool.isTablet)) {
transaction.replace(R.id.second_fragment_container, CharacterDetailFragment.newInstance(position));
transaction.commit();
} else {
transaction.replace(R.id.main_fragment_container, CharacterDetailFragment.newInstance(position));
transaction.addToBackStack(null);
transaction.commit();
//Enable the back button in action bar
if (getSupportActionBar() != null) getSupportActionBar().setDisplayHomeAsUpEnabled(true);
AppExtension app = (AppExtension) this.getApplicationContext();
app.setShowBackNavigation(true);
}
}
More code can be found in github becuase open source yay https://github.com/ej-krielen/pf2initiativetracker
A common given 'solution' is to use isDestroyed or isFinishing. Sure the app doesn't crash if I use that but then the fragment is also not being made.
So to reiterate:
Fragment goes fine initially but not after rotation.
FragmentManager has been destroyed? How to get it back/properly use it?
Right sometimes when updating an old project you forget your own logic. The problem was that in my adapter I use a reference to context. The adapter however is created in the AppExtension so on a recreate of the Activity this wasn't being set again. So now when the Activity gets recreated I pass the context to the adapter again and it all works fine.
I am getting this crash from multiple users when trying to get fragment manager. Any idea why the crash?
#Override
public void onNoInternetError() {
Log.i("base", "no internet error!");
final FragmentTransaction ft = getFragmentManager().beginTransaction();
final NoInternetFragment fragment = new NoInternetFragment();
ft.replace(R.id.content_frame, fragment, "noInternetFragment");
ft.addToBackStack(null);
ft.commit();
Error
Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'android.support.v4.app.p android.support.v4.app.k.a()' on a null object reference
at com.abc.abc.fragments.ABCFragmentBase$1.onNoInternetError(ABCFragmentBase.java:112)
at com.abc.abc.ui.components.NoInternetListener.showNoInternetFragment(NoInternetListener.java:14)
at com.abc.abc.ServerManager.handleFailure(ServerManager.java:1875)
at com.abc.abc.ServerManager.access$100(ServerManager.java:54)
at com.abc.abc.ServerManager$33.onFailure(ServerManager.java:1220)
at com.abc.sdk.JsonObjectRequest.deliverError(JsonObjectRequest.java:70)
at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:108)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6944)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:327)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1374)
from your code it seems like the getFragmentManager() call is returning null which probably means your fragment hasn't gone through onAttach() yet
you can add a flag for connection error and then after onAttach() display the relevant information
I have a single Activity with fragments and two simple methods inside the activity for managing fragments: pushFragmentImmediate() and popFragmentImmediate().
public void pushFragmentImmediate(Fragment fragment) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, fragment)
.addToBackStack(null)
.commitNow();
}
public void popFragmentImmediate() {
getSupportFragmentManager().popBackStackImmediate();
}
These transactions must execute immediately because of legacy code which depend on the back stack being up to date at all times.
Now I have a Fragment which pops off during onResume if some condition is satisfied:
#Override
public void onResume() {
super.onResume();
if (condition) {
((Main) getActivity()).popFragment();
}
}
This gives an error.
Can this error be avoided without changing popStackImmediate() to popBackStack()? Or can I move popBackStackImmediate() to some other phase when it will not return an error? Or am I thinking about this in the wrong way?
Full trace:
java.lang.RuntimeException: Unable to resume activity {se.esillen.testproject/se.esillen.testproject.Main}: java.lang.IllegalStateException: FragmentManager is already executing transactions
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3433)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3473)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2736)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1481)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:179)
at android.app.ActivityThread.main(ActivityThread.java:6152)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
Caused by: java.lang.IllegalStateException: FragmentManager is already executing transactions
at android.support.v4.app.FragmentManagerImpl.ensureExecReady(FragmentManager.java:2167)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2223)
at android.support.v4.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:834)
at android.support.v4.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:794)
at se.esillen.testproject.Main.popFragment(Main.java:25)
at se.esillen.testproject.TestFragment.onResume(TestFragment.java:26)
at android.support.v4.app.Fragment.performResume(Fragment.java:2401)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1465)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1740)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1809)
at android.support.v4.app.FragmentManagerImpl.dispatchStateChange(FragmentManager.java:3217)
at android.support.v4.app.FragmentManagerImpl.dispatchResume(FragmentManager.java:3181)
at android.support.v4.app.FragmentController.dispatchResume(FragmentController.java:214)
at android.support.v4.app.FragmentActivity.onResumeFragments(FragmentActivity.java:470)
at android.support.v4.app.FragmentActivity.onPostResume(FragmentActivity.java:459)
at android.support.v7.app.AppCompatActivity.onPostResume(AppCompatActivity.java:171)
at android.app.Activity.performResume(Activity.java:6856)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:3410)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:3473)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2736)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1481)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:179)
at android.app.ActivityThread.main(ActivityThread.java:6152)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
2 Fragments & 1 Activity are involved. Here is the flow wherein I am able to reproduce the issue, along with relevant code snippets.
#1. From Frag1, open Frag2
Frag2 fragment = Frag2.newInstance(pos);
BaseFragment.addToBackStack(getContext(), fragment);
Here is BaseFragment.addToBackStack()
BaseFragment
public static void addToBackStack(Context context, BaseFragment fragment) {
FragmentManager fragmentManager = ((BaseActivity) context).getSupportFragmentManager();
android.support.v4.app.FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.replace(BaseActivity.getContainerIdForCurrentActivity(context), fragment);
transaction.addToBackStack(null).commit();
}
#2. Press Back to open Frag1 again.
#3. Open Activity A1 with startActivityForResult() from an Adapter in Frag1.
Intent intent = new Intent(context, Act1.class);
intent.putExtra(..);
intent.putExtra(..);
((BaseActivity) context).startActivityForResult(intent, Frag1.REQ_CODE_ISSUE_DONE);
#4. Go back to Frag1, either by pressing Back or finishing A1 with
setResult()
#5. onActivityResult() of Frag1 is called. But inside it, both getContext() and getActivity() are NULL.
Frag1
if (resultCode == Ac1.RESULT_CODE_OPEN_LANDING_SCREEN) {
if (getActivity() instanceof MainActivity) {
BaseFragment.replaceStack(getContext(), landingFrag.newInstance());
} else {
Intent intent1 = new Intent(getContext(), MainActivity.class);
intent1.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent1);
}
}
If A1 is opened directly from Frag1, then getContext() is NOT null inside startActivityForResult() and works perfectly.
Logcat:
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=792, result=135, data=null} to activity {in.shadowfax.gandalf/in.shadowfax.gandalf.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
at android.app.ActivityThread.deliverResults(ActivityThread.java:3699)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:3742)
at android.app.ActivityThread.-wrap16(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1393)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
at android.content.ComponentName.<init>(ComponentName.java:128)
at android.content.Intent.<init>(Intent.java:4449)
at in.shadowfax.gandalf.help.issues.IssuesFrag.onActivityResult(IssuesFrag.java:153)
at in.shadowfax.gandalf.help.HelpPresenter.triggerIssuesFragOnActivityResult(HelpPresenter.java:72)
at in.shadowfax.gandalf.help.HelpFrag.onActivityResult(HelpFrag.java:100)
at in.shadowfax.gandalf.MainActivity.onActivityResult(MainActivity.java:901)
at android.app.Activity.dispatchActivityResult(Activity.java:6428)
at android.app.ActivityThread.deliverResults(ActivityThread.java:3695)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:3742)
at android.app.ActivityThread.-wrap16(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1393)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
Instead of
((BaseActivity) context).startActivityForResult(intent, Frag1.REQ_CODE_ISSUE_DONE);
using
fragment.startActivityForResult(intent, Frag1.REQ_CODE_ISSUE_DONE);
solved the issue.
onActivityResult() inside Nested Fragments is now called in support lib 23.2. So no need to reroute the onActivityResult() from Actvity to frag manually as I was doing in my case.
Ref: https://inthecheesefactory.com/blog/onactivityresult-nested-fragment-support-library-v23.2/en
I'm trying to start a Fragment inside my RecycleAdapter but when cast my Context with the AppCompatActivity the App crashed and inside logcat I got the message that android.app.Application cannot be cast to android.support.v7.app.AppCompatActivity.
here is my onClickListener inside RecycleAdapter.
holder.ItemClickButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
FragmentTransaction fragmentTransaction;
Toast.makeText(CTX,"Row Clicked id : "+homeCycleDataProvider.getId(),Toast.LENGTH_SHORT).show();
ItemsFragment fragobj = new ItemsFragment();
FragmentManager manager = ((AppCompatActivity) CTX).getSupportFragmentManager();
fragmentTransaction = manager.beginTransaction()
fragmentTransaction.replace(R.id.main_container, fragobj);
fragmentTransaction.commit();
}
});
here is my Adapter Initialization where I pass the context.
adapter = new ItemsRecycleAdapter(arrayList,getContext());
LOGCAT.
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.a1appstudio.sabirhossain.xpresdelivery, PID: 3109
java.lang.ClassCastException: android.app.Application cannot be cast to android.support.v7.app.AppCompatActivity
at com.a1appstudio.sabirhossain.xpresdelivery.ItemsListViewPackage.ItemsRecycleAdapter$1.onClick(ItemsRecycleAdapter.java:66)
at android.view.View.performClick(View.java:5198)
at android.view.View$PerformClick.run(View.java:21147)
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:5417)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
A context is not always an Activity, even when you're in an Activity. It could be an Application, or a wrapper around another context. It's almost always wrong to cast a Context to an Activity. If you absolutely need one, you should pass in an Activity as a parameter, rather than a Context. Or better yet, pass in the support fragment manager directly rather than the activity, since that's all you need it for.
adapter = new ItemsRecycleAdapter(arrayList,getActivity());
you can try this
if (context instanceof MainActivity ) {
MainActivity myActivity = (MainActivity)context;
myActivity.getSupportFragmentManager();
}