在旋转时出现“无法销毁活动...无法在onSaveInstanceState之后执行此操作”

3

您好,感谢您的帮助。

我正在配置我的代码来处理旋转,但是目前只实现了 onDestroy() 方法,还没有实现 onSaveInstanceState() 或 onRetainNonConfigurationInstance(),因为我正在确定哪些内容在被销毁并重新创建后不会出现问题,哪些需要保存。

在我的应用程序中,我使用一个运行 AsyncTask 的 Service,并使用 3 个片段,在用户按下按钮时进行切换。

我使用兼容性库来管理这些片段。

我怀疑我遇到的错误与片段有关;

具体而言,我希望在旋转时销毁并重新创建片段,而不是保留它们(因为我希望这样可以使我的代码更简单...)

当我旋转模拟器时,标题中会出现错误。

这是主要活动的代码:

public class Quotes extends FragmentActivity {

    private String url2;
    //public String responseBody;
    public static ArrayList<Stock> lt;
    public static ArrayList<Stock> best;
    public static ArrayList<Stock> worst;
    public static ArrayList<Stock> fav;// =new ArrayList<Stock>();
    public static LocalService mService;
    boolean mBound;// = false;
    public MyAdapter myAdap;
    public Messenger messenger;
    public Messenger messenger2;
    public Grab g;
    public static Handler handler;
    public static  Handler handler2;
    public Intent intent;
    public ListView lv;
    public dettagliofragment fragment;
    public listafragment fragmentlista ;
    public static boolean tablet;//=true;
    public static WorstBest worstbest;
    public static favouritesFragment fragmentfavourites;
    public static FragmentActivity fragmentActivity;
    public static int stack;
    public static ArrayList<Integer> stackArray; // stackArray =new ArrayList<Integer>();

    @Override
      public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
        stackArray =new ArrayList<Integer>();
        fav =new ArrayList<Stock>();
        tablet=true;
        mBound = false;
        fragmentActivity = this;
        setContentView(R.layout.splash);
        url2=getString(R.string.url2);
        g = new Grab(url2);
        String s = g.vai();
        //Log.e("", s);
        Log.e("", "passo oltre l'invocazione al grab");
        lt = new MyParser(s).parseResp();
        fragmentlista = new listafragment();
        fragmentfavourites= new favouritesFragment() ;
        worstbest = new WorstBest();
        /////////////////primo message handler
        handler=new Handler() {
            @Override
            public void handleMessage(Message msg) {
            Message mess=msg;   
            Log.e("","MESSAGGIO RICEVUTO");
            lt = mService.ritira();
            Log.e("what?", Integer.toString(mess.what));
            if( mess.what==0){

                worst=mService.ritiraWorst();
                best=mService.ritiraBest();
                fav=mService.ritiraFav();
                setContentView(R.layout.main);
                 View view1=(View)findViewById(R.id.view1);
                View view2=(View)findViewById(R.id.view2);
                if(view2==null) {tablet=false;};
                FragmentManager fragmentManager = getSupportFragmentManager();
                FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();       
                fragmentTransaction.add(R.id.view1, fragmentlista);
                if(tablet){fragmentTransaction.add(R.id.view2, worstbest);}
                fragmentTransaction.commit();
                g.fermaGrab(); 
                Log.e("", "fermograb");
                    };

            }
        };
        messenger = new Messenger(handler); 

        intent = new Intent(this, LocalService.class);
         intent.putExtra("messenger", messenger);       

        /////////////////secondo message handler
        handler2=new Handler() {
            @Override
            public void handleMessage(Message msg) {

            Message mess=msg;   
            Log.e("","SECONDO MESSAGGIO RICEVUTO");
            lt = mService.ritira();
            worst=mService.ritiraWorst();
            best=mService.ritiraBest();
            fav=mService.ritiraFav();
            if(lt==null){Log.e("","lt è nullo");};
            if(fragmentlista==null){Log.e("","fragmentlista è nullo");};

            fragmentlista.prendiLista(lt);
            worstbest.prendiListaWorst(worst);
            worstbest.prendiListaBest(best);
            if(fav.size()>0)fragmentfavourites.prendiLista(fav);
            };
            };
        messenger2 = new Messenger(handler2);  
        intent.putExtra("messenger2", messenger2);

        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
    } 

    public static void layoutSchermo(int conf){

    if(conf==1){    
        FragmentManager fragmentManager = fragmentActivity.getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right);
        if(!tablet){fragmentTransaction.replace(R.id.view1, fragmentfavourites);}
        if(tablet){fragmentTransaction.replace(R.id.view2, fragmentfavourites);}
        fragmentTransaction.addToBackStack(null);
        stack=fragmentTransaction.commit();
        stackArray.add(stack);
        Log.e("","stack = "+ Integer.toString(stack));
        }
    if(conf==2){    
        FragmentManager fragmentManager = fragmentActivity.getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right);
        if(!tablet){fragmentTransaction.replace(R.id.view1, worstbest);}
        if(tablet){fragmentTransaction.replace(R.id.view2, worstbest);}
        fragmentTransaction.addToBackStack(null);   
        stack= fragmentTransaction.commit();
        stackArray.add(stack);
        Log.e("","stack = "+ Integer.toString(stack));
        }

    }

    @Override
    public void onBackPressed(){
        FragmentManager fragmentManager = fragmentActivity.getSupportFragmentManager();
        if(stackArray.size()>0)
            {for(int i=1;i<stackArray.size();i++){
                fragmentManager.popBackStackImmediate(stackArray.get(i),     FragmentManager.POP_BACK_STACK_INCLUSIVE);}
            }

        super.onBackPressed(); 
    }   


     protected void onStop() {
            Log.e("onstop","passo per onstop");   

            mService.stop();
            g.fermaGrab();
            super.onStop();    
            }
     protected void onPause() {
            Log.e("onpause","passo per onpause");   
            mService.stop();
            g.fermaGrab();
            super.onPause();       
        }


     protected void onDestroy() {
        Log.e("ondestroy","passo per ondestroy"); 
        mService.stop();
        g.fermaGrab();
        //handler.removeMessages(333); 
        stopService(intent);
        //g=null;
        FragmentManager fragmentManager = fragmentActivity.getSupportFragmentManager();
        if(stackArray.size()>0)
            {for(int i=1;i<stackArray.size();i++){
                fragmentManager.popBackStackImmediate(stackArray.get(i),     FragmentManager.POP_BACK_STACK_INCLUSIVE);}
            }

         super.onDestroy();   

        }

     @Override
     protected void onSaveInstanceState(Bundle outState) {  }  


    public static ArrayList<Stock> dammi(){
        return lt;
    }  

    public void inizia()
    {   
        Log.e("","il serlizio è bound ? "+ mBound);
        mService.prendi(lt);
        mService.getNumber();


    }           

       private ServiceConnection mConnection = new ServiceConnection() {

            //@Override
            public void onServiceConnected(ComponentName className,
                    IBinder service) {
                Log.e("", "sono in ServiceConnection");
                // We've bound to LocalService, cast the IBinder and get LocalService instance
                LocalBinder binder = (LocalBinder) service;
                mService = binder.getService();
                mBound = true;
                //inizia();
                mService.prendi(lt);
                mService.getNumber();

            }

            //@Override
            public void onServiceDisconnected(ComponentName arg0) {
                mBound = false;
                mService = null;
            }
        };

这是我的LogCat:
01-06 12:20:27.869: E/AndroidRuntime(2165): FATAL EXCEPTION: main
01-06 12:20:27.869: E/AndroidRuntime(2165): java.lang.RuntimeException: Unable to destroy activity {com.example.quotes/com.example.quotes.Quotes}: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
01-06 12:20:27.869: E/AndroidRuntime(2165):     at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3273)
01-06 12:20:27.869: E/AndroidRuntime(2165):     at android.app.ActivityThread.handleDestroyActivity(ActivityThread.java:3291)
01-06 12:20:27.869: E/AndroidRuntime(2165):     at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3489)
01-06 12:20:27.869: E/AndroidRuntime(2165):     at android.app.ActivityThread.access$700(ActivityThread.java:130)
01-06 12:20:27.869: E/AndroidRuntime(2165):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1201)
01-06 12:20:27.869: E/AndroidRuntime(2165):     at android.os.Handler.dispatchMessage(Handler.java:99)
01-06 12:20:27.869: E/AndroidRuntime(2165):     at android.os.Looper.loop(Looper.java:137)
01-06 12:20:27.869: E/AndroidRuntime(2165):     at android.app.ActivityThread.main(ActivityThread.java:4745)
01-06 12:20:27.869: E/AndroidRuntime(2165):     at java.lang.reflect.Method.invokeNative(Native Method)
01-06 12:20:27.869: E/AndroidRuntime(2165):     at java.lang.reflect.Method.invoke(Method.java:511)
01-06 12:20:27.869: E/AndroidRuntime(2165):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
01-06 12:20:27.869: E/AndroidRuntime(2165):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
01-06 12:20:27.869: E/AndroidRuntime(2165):     at dalvik.system.NativeStart.main(Native Method)
01-06 12:20:27.869: E/AndroidRuntime(2165): Caused by: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
01-06 12:20:27.869: E/AndroidRuntime(2165):     at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1314)
01-06 12:20:27.869: E/AndroidRuntime(2165):     at android.support.v4.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:480)
01-06 12:20:27.869: E/AndroidRuntime(2165):     at com.example.quotes.Quotes.onDestroy(Quotes.java:201)
01-06 12:20:27.869: E/AndroidRuntime(2165):     at android.app.Activity.performDestroy(Activity.java:5172)
01-06 12:20:27.869: E/AndroidRuntime(2165):     at android.app.Instrumentation.callActivityOnDestroy(Instrumentation.java:1109)
01-06 12:20:27.869: E/AndroidRuntime(2165):     at android.app.ActivityThread.performDestroyActivity(ActivityThread.java:3260)
01-06 12:20:27.869: E/AndroidRuntime(2165):     ... 12 more

非常感谢您的任何帮助!!!

1
你能否将有问题的代码转移到onConfigurationChanged()函数中? - Changdeo Jadhav
1
我的意思是,如果在OnDestroy中不允许您弹出后退片段,则将该代码编写在onConfigurationChanged方法中,这将在方向更改时调用。 - Changdeo Jadhav
@ChangdeoJadhav,没有成功。无论如何感谢您! - Lisa Anne
2个回答

1

感谢您的信息。同时,我已经解决了这个问题。

导致问题的原因是一个服务需要在活动因旋转而被销毁时解除绑定。

据我所知,当活动被销毁时,片段并不会被销毁。然而,我很乐意听取任何意见。

因此,在活动再次创建后,我在onCreate()方法中重新初始化了片段,这不会对应用程序造成麻烦。

protected void onDestroy() {
   mService.stop();
   stopService(new Intent(this, LocalService.class));
   unbindService(mConnection);
   g.fermaGrab();
   stopService(intent);
   Log.e("ondestroy","passostopService(intent)"); 
   super.onDestroy();       
}

1

其他回答让我陷入了WeakReferences、内存泄漏和onResumeFragments的死胡同,但实际上,你只需要在一个控件失去焦点时尝试弹出对话框,并且拥有一个onFocusChangeListener,就可以导致此错误。这个错误出现在ActivityThread.handleRelaunchActivity中,所以有点难以解决。


1
这刚好帮我解决了在Android 7.1平板上启动应用程序时的一个错误,我不知道为什么会这样,但我添加了一个版本检查,现在它可以正常工作了:if (VERSION.SDK_INT >= Build.VERSION_CODES.O) 然后设置setOnFocusChangeListener。 - marcpetitvecino
1
实际上我正在进行测试,这个问题在8和8.1版本中也出现过,在Android 9(Build.VERSION_CODES.P)中已经被修复了。 - marcpetitvecino
1
StackOverflow做得好,保留这个答案已经十年了,只为了帮助第一个需要它的人!我想知道是否有相应的成就。很高兴它对你有用。 - Noumenon
1
干得好StackOverflow,保存这个答案长达十年,只为了帮助第一个人!不知道是否有类似的成就奖励。很高兴它对你有用。 - Noumenon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接