Reputation: 305
I am new to developing android applications, so please pardon any stupid mistakes that I may have made. On to the question: I am making an application which has its main activity layout screen containing some stuff and have a navigation drawer wired in. Now I am trying to use the entries in the navigation drawer to call up various fragments and display them over my main activity. However when I run my piece of code, I am getting an Activity Destroyed error I have attached my code below for reference. I think the problem is with what I have done with the container. To make the fragment cover the whole screen of my main activity, I gave the fragment container as the root layout as I was unsure how to go about this.
Code which handles item clicks from navigation drawer
class DrawerItemClickListener extends FragmentActivity implements ListView.OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
selectItem(position);
}
private void selectItem(int position) {
Fragment mFragment = null;
switch(position) {
case 0:
mFragment = new AnnouncementFragment();
Bundle args = new Bundle();
args.putInt(null, position);
break;
case 1:
break;
case 2:
break;
case 3:
break;
default:
break;
}
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction().replace(R.id.drawer_layout, mFragment);
transaction.commit();
transaction.addToBackStack(null);
}
Code for fragment
public class AnnouncementFragment extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_announcement, container, false);
}
XML layout of main activity
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id = "@+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/screen_login"
android:gravity="center"
android:textColor="@android:color/holo_blue_light"
android:id="@+id/login_tv"
android:layout_alignParentTop="true"
android:layout_marginTop="105dp"
android:layout_alignParentEnd="true"
android:layout_alignParentStart="true"
android:textSize="40sp" />
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/username_et"
android:layout_below="@id/login_tv"
android:layout_alignParentStart="true"
android:layout_marginTop="45dp"
android:layout_alignParentEnd="true"
android:hint="@string/username"/>
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="textPassword"
android:ems="10"
android:id="@+id/editText2"
android:layout_below="@id/username_et"
android:layout_alignParentStart="true"
android:layout_marginTop="30dp"
android:layout_alignParentEnd="true"
android:hint="@string/password" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/login"
android:id="@+id/login_btn"
android:layout_below="@+id/editText2"
android:layout_centerHorizontal="true"
android:layout_marginTop="25dp" />
</RelativeLayout>
<ListView
android:id="@+id/drawer_list"
android:layout_width="200dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#ffeeeeee"/>
Error
java.lang.IllegalStateException: Activity has been destroyed
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1399)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:637)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:616)
at com.it.learnera.DrawerItemClickListener.selectItem(DrawerItemClickListener.java:40)
at com.it.learnera.DrawerItemClickListener.onItemClick(DrawerItemClickListener.java:19)
I am wondering how I can make the fragment draw over the main activity layout without causing a mess
Cheers and Thanks in advance
Upvotes: 2
Views: 9427
Reputation: 7474
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction()
.replace(R.id.drawer_layout, mFragment); // < - first problem ( see ad. 1)
.commit() // <- third problem (see ad. 3)
// second problem ( see ad. 2)
mFragment = new AnnouncementFragment();
Bundle args = new Bundle();
args.putInt(null, position);
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- The main content view -->
<FrameLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- The navigation drawer -->
<ListView android:id="@+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="@android:color/transparent"
android:dividerHeight="0dp"
android:background="#111"/>
drawer_layou - this is a view which holds:
FrameLayout / with id - >content_frame
( container capable to hold "only" one element: fragment / view)
ListView / with id - > left_drawer
( list view for example with menu entries )
so you need replace content_frame
ps to better see purpose of transaction you should call it in one statement - in "chain / sequence "
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction()
.replace(R.id.frame_layout, mFragment)
.addToBackStack(null) // add to manager " will remember this fragment - for navigation purpose"
.commit() // commit mean do everything from top to bottom on next pass
mFragment = new AnnouncementFragment();
Bundle args = new Bundle();
args.putInt(null, position);
mFragment.setArguments(args)
Note: A fragment transaction can only be created/committed prior to an activity saving its state.
If you try to commit a transaction after:
and prior to a following
you will get an error. This is because the framework takes care of saving your current fragments in the state, and if changes are made after the state is saved then they will be lost.
After FragmentTransaction is committed with FragmentTransaction.commit() is scheduled to be executed asynchronously on the process's main thread.
If you want to immediately executing any such pending operations, you can call this function (only from the main thread) to do so. Note that all callbacks and other related behavior will be done from within this call, so be careful about where this is called from.
boolean executePendingTransactions();
btw look at this docs which refers to extending an FragmentActivity:
https://developer.android.com/reference/android/support/v4/app/FragmentActivity.html
i don't know which api you target but you may also check this bug:
http://johnfeng.github.io/blog/2015/05/31/fragment-activity-has-been-destoryed-problem/
( problem with child fragment which state is not being reset )
Hi, appreciate the detailed explanation but it doesnt work – Prejith P
and this article about state loss which is i think related to your problem
http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html
so you can try call instead of commit() (but this is not solution):
commitAllowingStateLoss()
Hi, I fixed it myself just now. I changed the implementation of my navigation drawer a bit and it just started working. I have no idea how it got fixed, which is why I haven't posted an answer here – Prejith P
YES - the problem was your implementation you have tried to call commit() after an activity instance was destroyed what is indicating by stack trace
java.lang.IllegalStateException: Activity has been destroyed
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1399)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:637)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:616)
at com.it.learnera.DrawerItemClickListener.selectItem(DrawerItemClickListener.java:40)
at com.it.learnera.DrawerItemClickListener.onItemClick(DrawerItemClickListener.java:19)
`
Upvotes: 3
Reputation: 1
u need a fragment to fragment communication
class DetailActivity extends
AppCompatActivity implements BioDetailClickView {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setNavigationIcon(R.drawable.navigation);
setSupportActionBar(toolbar);
FragmentManager fm = getSupportFragmentManager();
Fragment fragment = fm.findFragmentById(R.id.fragment_container);
if (fragment == null) {
fragment = new Fragment1();
fm.beginTransaction()
.add(R.id.fragment_container, fragment)
.commit();
}
}
public void fragment_transaction(Fragment fragment){
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.fragment_container, fragment);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
@Override
public void onClickFragmentQuick() {
Fragment frag= new Fragment1();
fragment_transaction(frag);
}
@Override
public void onClickFragment2() {
Fragment fragment =new Fragment2();
fragment_transaction(fragment);
}
@Override
public void onClickFragment3() {
Fragment fragment =new Fragment3();
fragment_transaction(fragment);
}
public interface BioDetailClickView {
void onClickFragment1();
void onClickFragment2();
void onClickFragment3();
}
Upvotes: 0
Reputation: 2407
The problem is that you're calling transaction.addToBackStack(null);
after you commit the replacement. I suggest you to do as follow:
getSupportFragmentManager().beginTransaction()
.replace(R.id.drawer_layout, mFragment).addToBackStack(null).apply();
Upvotes: 0