Android 导航组件无法与对话框片段一起使用
Android Navigation Component not working with Dialog Fragments
免责声明: 我已经检查了文档,因为 2.1.0
导航组件支持对话框片段。 (https://developer.android.com/jetpack/androidx/releases/navigation#2.1.0)
我遇到的错误
我在尝试从 DialogFragment
转到我的 Start Destination
:
时遇到此错误
java.lang.IllegalStateException: Fragment PostDistressDialog{829f5d1} (bbbc4926-684b-491b-9772-e0f0ffebe0af)} not associated with a fragment manager.
PostDistressDialog
是使用导航组件从 JournalEntryFragment
(可以在下面的地图中看到)调用的 DialogFragment
。 PostDistressDialog
不是 JournalEntryFragment
的内部 class。它在一个 class 中,它自己扩展 DialogFragment
我的导航图图片
函数调用 NavController
public class PostDistressDialog extends DialogFragment implements ISaveDatabase {
...
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
if (getArguments()!=null) {
...
// Set up the Alert Dialog
AlertDialog.Builder alertDialog = new AlertDialog.Builder(getContext());
alertDialog.setTitle(R.string.distressed_levels);
alertDialog.setMessage(R.string.distressed_how_feel_post);
// Inflate and set the layout for the dialog
View layout = View.inflate(getActivity(), R.layout.dialog_seekbar, null);
alertDialog.setView(layout);
....
// Add okay button
alertDialog.setPositiveButton(R.string.okay, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// Save post distress value in Journal Entry
mJournalEntry.setPostDistress(mTempDistressValue);
// Save to Journal Entry to database
// Check if journal entry empty
if(isJournalEntryEmpty(mJournalEntry)){
...
}
else{
// Give title if empty
if(mJournalEntry.getTitle().isEmpty()) {
....
// Save to database
new SaveDatabase(getContext(),PostDistressDialog.this).execute(mJournalEntry);
}
// Go to main menu
}
});
return alertDialog.create();
}
return null;
}
...
@Override
public void databaseSavingCompleted(){
NavHostFragment.findNavController(this).navigate(PostDistressDialogDirections.postDistressDialogToJournalListAction());
}
}
其中 this
是 public class PostDistressDialog extends DialogFragment
导航中的对话框XML文件
<dialog
android:id="@+id/postDistressDialog"
android:name="com.dgrullon.cbtjourney.dialogs.PostDistressDialog"
android:label="PostDistressDialog" >
<argument
android:name="postDistressDialogArguments"
app:argType="com.dgrullon.cbtjourney.pojo.JournalEntries"/>
<action
android:id="@+id/postDistressDialog_to_journalListAction"
app:destination="@id/journalList"
app:popUpTo="@id/journalList"
app:popUpToInclusive="true" />
</dialog>
当您添加到 setPositiveButton
的回调被触发时,AlertDialog 会自动关闭对话框(并因此删除您的 DialogFragment
)。因为您正在异步工作,所以在 DialogFragment 被销毁、从 FragmentManager 分离并从 NavController 中删除后调用 databaseSavingCompleted
方法 - 您正在泄漏对 DialogFragment 的引用(否则它会是垃圾已收集)。
因此,当 NavHostFragment.findNavController(this)
触发时,所有允许它访问 NavController
的挂钩都已经清除。
如果您不希望您的按钮立即关闭对话框,您需要将 null
传递给 setPositiveButton()
并在创建对话框后获取对按钮的引用调用它的 getButton()
API 并手动设置一个 OnClickListener
来启动你的 AsyncTask
(并禁用该按钮以防止它被多次点击)。
免责声明: 我已经检查了文档,因为 2.1.0
导航组件支持对话框片段。 (https://developer.android.com/jetpack/androidx/releases/navigation#2.1.0)
我遇到的错误
我在尝试从 DialogFragment
转到我的 Start Destination
:
java.lang.IllegalStateException: Fragment PostDistressDialog{829f5d1} (bbbc4926-684b-491b-9772-e0f0ffebe0af)} not associated with a fragment manager.
PostDistressDialog
是使用导航组件从 JournalEntryFragment
(可以在下面的地图中看到)调用的 DialogFragment
。 PostDistressDialog
不是 JournalEntryFragment
的内部 class。它在一个 class 中,它自己扩展 DialogFragment
我的导航图图片
函数调用 NavController
public class PostDistressDialog extends DialogFragment implements ISaveDatabase {
...
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
if (getArguments()!=null) {
...
// Set up the Alert Dialog
AlertDialog.Builder alertDialog = new AlertDialog.Builder(getContext());
alertDialog.setTitle(R.string.distressed_levels);
alertDialog.setMessage(R.string.distressed_how_feel_post);
// Inflate and set the layout for the dialog
View layout = View.inflate(getActivity(), R.layout.dialog_seekbar, null);
alertDialog.setView(layout);
....
// Add okay button
alertDialog.setPositiveButton(R.string.okay, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
// Save post distress value in Journal Entry
mJournalEntry.setPostDistress(mTempDistressValue);
// Save to Journal Entry to database
// Check if journal entry empty
if(isJournalEntryEmpty(mJournalEntry)){
...
}
else{
// Give title if empty
if(mJournalEntry.getTitle().isEmpty()) {
....
// Save to database
new SaveDatabase(getContext(),PostDistressDialog.this).execute(mJournalEntry);
}
// Go to main menu
}
});
return alertDialog.create();
}
return null;
}
...
@Override
public void databaseSavingCompleted(){
NavHostFragment.findNavController(this).navigate(PostDistressDialogDirections.postDistressDialogToJournalListAction());
}
}
其中 this
是 public class PostDistressDialog extends DialogFragment
导航中的对话框XML文件
<dialog
android:id="@+id/postDistressDialog"
android:name="com.dgrullon.cbtjourney.dialogs.PostDistressDialog"
android:label="PostDistressDialog" >
<argument
android:name="postDistressDialogArguments"
app:argType="com.dgrullon.cbtjourney.pojo.JournalEntries"/>
<action
android:id="@+id/postDistressDialog_to_journalListAction"
app:destination="@id/journalList"
app:popUpTo="@id/journalList"
app:popUpToInclusive="true" />
</dialog>
当您添加到 setPositiveButton
的回调被触发时,AlertDialog 会自动关闭对话框(并因此删除您的 DialogFragment
)。因为您正在异步工作,所以在 DialogFragment 被销毁、从 FragmentManager 分离并从 NavController 中删除后调用 databaseSavingCompleted
方法 - 您正在泄漏对 DialogFragment 的引用(否则它会是垃圾已收集)。
因此,当 NavHostFragment.findNavController(this)
触发时,所有允许它访问 NavController
的挂钩都已经清除。
如果您不希望您的按钮立即关闭对话框,您需要将 null
传递给 setPositiveButton()
并在创建对话框后获取对按钮的引用调用它的 getButton()
API 并手动设置一个 OnClickListener
来启动你的 AsyncTask
(并禁用该按钮以防止它被多次点击)。