我是开发 Android 应用程序的新手,所以请原谅我可能犯的任何愚蠢的错误。关于问题: 我正在制作一个应用程序,其主 Activity 布局屏幕包含一些内容,并连接了一个抽屉导航。现在我尝试使用抽屉导航中的条目来调用各种 fragment 并将它们显示在我的主要 Activity 上。但是,当我运行我的代码时,我收到 Activity 被破坏错误,我已在下面附上我的代码以供引用。我认为问题出在我对容器所做的事情上。为了使 fragment 覆盖我的主要 Activity 的整个屏幕,我将 fragment 容器作为根布局,因为我不确定如何进行此操作。
处理抽屉导航中的项目点击的代码
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);
}
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);
}
主要 Activity 的 XML 布局
<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"/>
错误
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)
我想知道如何使 fragment 绘制在主 Activity 布局上而不造成困惑
提前干杯并表示感谢
最佳答案
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);
广告 1. 替换 DrawerLayout 而不是它的容器
<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 - 这是一个包含以下内容的 View :
FrameLayout/带 id ->content_frame
( container capable to hold "only" one element: fragment / view)
ListView/带id->left_drawer
( list view for example with menu entries )
所以你需要替换 content_frame
ps 为了更好地了解交易的目的,您应该在一个语句中调用它 - 在“链/序列”中
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
ad 2.您还需要将参数放入 fragment 中:
mFragment = new AnnouncementFragment();
Bundle args = new Bundle();
args.putInt(null, position);
mFragment.setArguments(args)
ad 3. 当 Activity 在 onSaveInstanceState 之后调用 commit
Note: A fragment transaction can only be created/committed prior to an activity saving its state.
如果您尝试在以下时间后提交事务:
- Activity.onSaveInstanceState()
以及在以下内容之前
- Activity.onStart()
- Activity.onResume()
你会得到一个错误。这是因为框架负责保存状态中当前的 fragment ,如果在保存状态后进行更改,那么它们将会丢失。
使用 FragmentTransaction.commit() 提交 FragmentTransaction 后,计划在进程的主线程上异步执行。
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.
bool 值executePendingTransactions();
- 如果有任何待执行的交易,则返回 true。
顺便看看这个文档,它指的是扩展 FragmentActivity:
https://developer.android.com/reference/android/support/v4/app/FragmentActivity.html
我不知道您的目标是哪个 api,但您也可以检查此错误:
http://johnfeng.github.io/blog/2015/05/31/fragment-activity-has-been-destoryed-problem/
(子 fragment 的问题,其状态没有被重置)
Hi, appreciate the detailed explanation but it doesnt work – Prejith P
这篇关于状态损失的文章我认为与您的问题有关
http://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html
所以你可以尝试调用而不是commit()(但这不是解决方案):
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
是 - 问题是您在 Activity 实例被销毁后尝试调用 commit() 的实现,堆栈跟踪表明了这一点
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)
`
当您调用 commit() 时您应该确保:
- Activity 已附加
- Activity 可见(在 onSaveInstanceState 之前)
关于android - 在主要 Activity 上绘制 fragment ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37992311/