Android - Fragment Transition issue - android

I currently am working on a newsfeed module where i have this issue of fragment transition.
Transition Example :
Newsfeed >a> Profile >b> Detail >c> Profile.
Newsfeed >a> Detail >b> Profile >c> Detail.
Every time i visit a page twice and tries to back again at "a". My app crashed giving nullpointerexception on
getActivity().onBackPressed();
in fragment. Each stack is poped in MainActivity in override onBackPressed. All flows are fine when there are no 2 of the same fragment transition in the backstack.
PopBackStack Example :
getSupportFragmentManager().popBackStack("profile", FragmentManager.POP_BACK_STACK_INCLUSIVE);
Let me know if you need more codes to help.
Any help would be appreciated.
Thank you!
Edit:
Logcat Error :
09-19 02:15:02.399 29778-29778/com.dbs.alive E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.dbs.alive, PID: 29778
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v4.app.FragmentActivity.onBackPressed()' on a null object reference
at com.dbs.alive.ProfileFragment$1.onClick(ProfileFragment.java:171)
at android.view.View.performClick(View.java:5210)
at android.view.View$PerformClick.run(View.java:21328)
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:5551)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
Main Activity (onBackPressed)
#Override
public void onBackPressed() {
if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
//this.finish();
super.onBackPressed();
} else {
for (int i = getSupportFragmentManager().getBackStackEntryCount(); i > 0; i--) {
String ide = getSupportFragmentManager().getBackStackEntryAt(i - 1).getName();
if (ide != null) {
//1. FROM NEWSFEED
if (ide.equals("newsfeed")) {
getSupportFragmentManager().popBackStack("newsfeed", FragmentManager.POP_BACK_STACK_INCLUSIVE);
break;
} else if (ide.equals("profile")) {
getSupportFragmentManager().popBackStack("profile", FragmentManager.POP_BACK_STACK_INCLUSIVE);
break;
}
Fragment AddBackStack
Fragment fragment = ProfileFragment.newInstance("", "");
Bundle mBundle = new Bundle();
mBundle.putString("profileid", postOwnerId);
mBundle.putString("profilename", postOwnerName);
mBundle.putString("profileicon", RealmHelper.getUserProfileUrl(postOwnerId));
fragment.setArguments(mBundle);
FragmentTransaction transaction = ((AppCompatActivity) activity).getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.newsfeed_layout, fragment);
transaction.addToBackStack("profile");
transaction.commit();

Related

How to prevent FragmentManager from being destroyed after rotation

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.

How to fix 'Attempt to invoke virtual method 'android.support.v4.app.p android.support.v4.app.k.a()' on a null object reference'

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

what could be the reason even if check isFinishing() it still gets IllegalStateException: Can not perform this action after onSaveInstanceState

getting IllegalStateException: Can not perform this action after onSaveInstanceState in activity when adding a fragment. It works most of the time but saw there are some time this IllegalStateException happening.
the add fragment is done after checking the activity is still there by:
if ((!mInSaveInstanceState) && !isFinishing())
any explanation why the "IllegalStateException: Can not perform this action after onSaveInstanceState" could still happen?
code snippet is blow.
in activity:
#Override
protected void onSaveInstanceState(Bundle outState) {
mInSaveInstanceState = true;
… …
super.onSaveInstanceState(outState);
}
snippet displaying a new fragment:
void addNewFragment () {
if ((!mInSaveInstanceState) && !isFinishing()) {
FragmentManager fm = getSupportFragmentManager();
String fragmentName = "NEW_ADDED_FRAGMENT";
int holderId = R.id.new_fragment_holder;
NewFragment theNewFrgmt = new NewFragment();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(holderId, theNewFrgmt, fragmentName);
ft.addToBackStack(fragmentName);
ft.setCustomAnimations(R.anim.hold, 0, R.anim.slide_left_in, 0);
ft.show(theNewFrgmt);
ft.commit(); //<=== it throws at here
}
}
the crash
Fatal Exception: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1832)
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1850)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:643)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:603)
at com.zone.ui.MainActivity.addNewFragment(MainActivity.java:4522)
at com.zone.ui.MainActivity.access$000(MainActivity.java:262)
at com.zone.ui.MainActivity$8.onEvent(MainActivity.java:591)
at com.zone.ui.MainActivity$8.onEvent(MainActivity.java:587)
at com.zone.dataModel.EventManager.dispatchEvent(EventManager.java:96)
at com.zone.ui.tasklist.TaskListFragment$8.run(TaskListFragment.java:422)
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:5343)
at java.lang.reflect.Method.invoke(Method.java)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:905)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:700)
After onSaveInstanceState you can't commit transaction, so use StateLoss commit.
ft.commitAllowingStateLoss();

getContext() is NULL for a certain fragment flow

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

How to call Fragment method from parent activity/Fragment2? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I simply want to call a method declared in fragment through parent activity and it gives me the error " Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference"` Please suggest something.
Fragment Method:
public void loadSpinnerData() {
Toast.makeText(mActivity, "HELLO", Toast.LENGTH_SHORT).show();
}
Calling method from parent actvity:
private void displayView(int position) {
// update the main content by replacing fragments
Fragment fragment = null;
switch (position) {
case 0:
fragment = new NoticeBoard();
break;
case 1:
fragment = new Quotes();
if (fragment instanceof Quotes)
((Quotes) fragment).loadSpinnerData();
break;
default:
break;
}
if (fragment != null) {
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.frame_container, fragment).commit();
// update selected item and title, then close the drawer
} else {
// error in creating fragment
Log.e("MainActivity", "Error in creating fragment");
}
}
my logcat is as follows
Logcat error : java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference 05-25 08:46:59.740: E/AndroidRuntime(6152): at app.redalkemi.edublaze.Quotes.loadSpinnerData(Quotes.java:210)
try changing your code a little bit
public void loadSpinnerData(Context contxt) {
Toast.makeText(contxt, "HELLO", Toast.LENGTH_SHORT).show();
}
in parent activity
if (fragment instanceof Quotes)
((Quotes) fragment).loadSpinnerData(youractivityname.this);

Categories

Resources