当用户单击关闭按钮关闭 DialogFragment 时出现 IllegalStateException

Posted

技术标签:

【中文标题】当用户单击关闭按钮关闭 DialogFragment 时出现 IllegalStateException【英文标题】:IllegalStateException when the user clicks the Close button to dismiss a DialogFragment 【发布时间】:2016-11-15 19:36:51 【问题描述】:

我从我的一些用户那里得到了这个例外:

java.lang.IllegalStateException: 之后无法执行此操作 onSaveInstanceState 在 android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManagerImpl.java:1500) 在 android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManagerImpl.java:1518) 在 android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:634) 在 android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:613) 在 android.support.v4.app.DialogFragment.dismissInternal(DialogFragment.java:201) 在 android.support.v4.app.DialogFragment.dismiss(DialogFragment.java:167) 在 com.myapp.myapp.HelpDialog$2.onClick(HelpDialog.java:228) 在 android.view.View.performClick(View.java:5201) 在 android.view.View$PerformClick.run(View.java:21163) 在 android.os.Handler.handleCallback(Handler.java:746) 在 android.os.Handler.dispatchMessage(Handler.java:95) 在 android.os.Looper.loop(Looper.java:148) 在 android.app.ActivityThread.main(ActivityThread.java:5443) 在 java.lang.reflect.Method.invoke(Method.java) 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728) 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)

导致此异常的调用位于 DialogFragment onCreateView() 方法中:

...
Button  btn;
btn = (Button)v.findViewById( R.id.close_btn );        
btn.setOnClickListener( new View.OnClickListener() 


@Override
public void onClick( View view ) 
       
    dismiss();

);

dismiss 导致状态丢失,因为该操作是在 onSaveInstanceState() 之后完成的。调用 onSaveInstanceState() 后,用户如何点击关闭按钮?

编辑。 DialogFragment 里面有一个viewpager。我将只发布 dialogfragment 的代码,而不是 viewpager 适配器或 fragmenttabs 的代码:

/**
 * 
 */
public class HelpDialog extends DialogFragment


    final   static  String  DIALOG_TAG = "help_dialog";

    ViewPager   mPager = null;

    /**
     * 
     */
    public  HelpDialog() 
    
        CLog.i( "HelpDialog.HelpDialog()", "Constructor called" );
       

     /**
     * Create a new instance of WelcomeDialog.
     */
    static HelpDialog newInstance()
    
        HelpDialog d = new HelpDialog();    
        return d;
       


    /**
     * 
     */
    static  boolean showNewInstance( FragmentActivity   activity )
    
        HelpDialog  d = HelpDialog.newInstance();
        if ( d != null )
        
            FragmentTransaction ft = activity.getSupportFragmentManager().beginTransaction();
            Fragment prev = activity.getSupportFragmentManager().findFragmentByTag( HelpDialog.DIALOG_TAG );
            if (prev != null) 
            
                ft.remove( prev );
            


            // Create and show the dialog.
            d.show( ft, HelpDialog.DIALOG_TAG );            
            return  true;
        
        return  false;
    




    @Override
    public void onCreate( Bundle savedInstanceState ) 
           
        super.onCreate(savedInstanceState);

        CLog.i("HelpDialog.onCreate()", "" );

        int style = DialogFragment.STYLE_NO_TITLE;
        int theme = getTheme();
        setStyle( style, theme );
    


    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) 
    
        CLog.i("HelpDialog.onCreateDialog()", "" );
        return  super.onCreateDialog( savedInstanceState );
    


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) 
    
        CLog.i("HelpDialog.onCreateView()", "" );

        final View v = inflater.inflate( R.layout.help_dialog, container, false );

        DisplayMetrics displaymetrics = new DisplayMetrics();
        getActivity().getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
        int screenWidth = displaymetrics.widthPixels;
        int screenHeight = displaymetrics.heightPixels;
        int     min_width = (displaymetrics.widthPixels * 70) / 100;        
        int     min_height = (displaymetrics.heightPixels * 70) / 100;
        v.setMinimumWidth( min_width );
        //v.setMinimumHeight(min_height);
        CLog.i( "HelpDialog.onCreateView()", "screenWidth " + screenWidth + " min_width " + min_width );



        // Locate ViewPager in activity_main.xml
        mPager = (ViewPager) v.findViewById( R.id.help_dlg_pager );

        // Activate Fragment Manager
        FragmentManager fm = this.getChildFragmentManager();//getActivity().getSupportFragmentManager();


        // Capture ViewPager page swipes
        ViewPager.SimpleOnPageChangeListener viewPagerListener = new ViewPager.SimpleOnPageChangeListener() 
        
            @Override
            public void onPageSelected(int position) 
            
                super.onPageSelected(position);
            
        ;

        mPager.setOnPageChangeListener( viewPagerListener );
        // Locate the adapter class called ViewPagerAdapter.java
        HelpDlgViewPagerAdapter viewpageradapter = new HelpDlgViewPagerAdapter(fm);
        // Set the View Pager Adapter into ViewPager
        mPager.setAdapter(viewpageradapter);
        //mPager.setPageTransformer( true, new DepthPageTransformer() );
        mPager.setPageTransformer( true, new ZoomOutPageTransformer() );

        //Bind the title indicator to the adapter
        CirclePageIndicator mIndicator = (CirclePageIndicator)v.findViewById( R.id.help_dlg_indicator );
        mIndicator.setViewPager( mPager );          

        Button  btn;
        btn = (Button)v.findViewById( R.id.close_btn );        
        btn.setOnClickListener( new View.OnClickListener() 
        

            @Override
            public void onClick( View view ) 
                   
                CLog.i( "HelpDialog", "onClick() - dismissing" );
                dismissAllowingStateLoss();
            
        );





        getDialog().getWindow().setBackgroundDrawableResource( R.color.transparent );//translucent_black );
        getDialog().getWindow().clearFlags( WindowManager.LayoutParams.FLAG_DIM_BEHIND );
        getDialog().setCanceledOnTouchOutside( false );
        return v;
       



    ////



    @Override
    public void onAttach ( Activity activity )
    
        super.onAttach( activity );
        CLog.i("HelpDialog.onAttach()", "" );
    


    @Override
    public void onActivityCreated (Bundle savedInstanceState)
    
        super.onActivityCreated( savedInstanceState );
        CLog.i("HelpDialog.onActivityCreated()", "" );      
    

    @Override
    public void onViewStateRestored (Bundle savedInstanceState)
    
        super.onViewStateRestored(savedInstanceState);
        CLog.i("HelpDialog.onViewStateRestored()", "" );
    


    @Override
    public void onStart ()
    
        super.onStart();
        CLog.i("HelpDialog.onStart()", "" );
    

    @Override
    public void onStop ()
    
        super.onStop();
        CLog.i("HelpDialog.onStop()", "" );
    


    @Override
    public void onResume()
    
        super.onResume();
        CLog.i("HelpDialog.onResume()", "" );
    

    @Override
    public void onPause()
    
        super.onPause();
        CLog.i("HelpDialog.onPause()", "" );
    


    @Override
    public void onDestroyView()
    
        super.onDestroyView();
        CLog.i("HelpDialog.onDestroyView()", "" );
    

    @Override
    public void onDestroy ()
    
        super.onDestroy();
        CLog.i("HelpDialog.onDestroy()", "" );
    

    @Override
    public void onDetach ()
    
        super.onDetach();
        CLog.i("HelpDialog.onDetach()", "" );       
    



【问题讨论】:

尽可能发布完整代码。 请看这可能对你有帮助:androiddesignpatterns.com/2013/08/… 查看此链接:hrupin.com/2013/05/… 我前段时间读过第一篇,我会再读一遍。当用户从应用程序菜单中选择“帮助”项时,将显示“帮助”对话框。当用户单击关闭按钮时,对话框关闭。我不明白为什么调用 onSaveInstanceState() 后对话框仍然存在(当对话框不应该存在时,用户可以单击关闭按钮)! 【参考方案1】:
static  boolean showNewInstance( FragmentActivity   activity )

    HelpDialog  d = HelpDialog.newInstance();
    if ( d != null )
    
        FragmentTransaction ft = activity.getSupportFragmentManager().beginTransaction();
        Fragment prev = activity.getSupportFragmentManager().findFragmentByTag( HelpDialog.DIALOG_TAG );
        if (prev != null) 
        
            ft.remove( prev );
        


        // Create and show the dialog.
        d.show( ft, HelpDialog.DIALOG_TAG );            
        return  true;
    
    return  false;

您忘记提交事务。在ft.remove( prev );之后添加这个:ft.commit();

【讨论】:

以上是关于当用户单击关闭按钮关闭 DialogFragment 时出现 IllegalStateException的主要内容,如果未能解决你的问题,请参考以下文章

iPhone:当用户单击主页按钮时,是不是可以关闭应用程序而不是在后台运行?

如何在按钮单击时关闭 uwp 中的吐司

当用户在菜单外单击时,如何关闭 Bootstrap 导航栏下拉菜单?

QLineEdit 单击时清除文本并从按钮读取文本[关闭]

c#单击关闭按钮事件

如何关闭表格