1

我在使應用程序持續存在困難。當我旋轉手機時,屏幕上的數據不會改變。但是當我點擊一個按鈕來檢索一個新的片段後,我得到一個錯誤,說「在onSaveInstanceState之後不能執行這個動作」。我搜索了一下,發現了類似的問題,但我仍然不知道如何解決這個問題。如何在手機方向上保存我的數據?

我有一個活動類,一個控制器類和兩個片段類。 活動類有一個帶有2個按鈕的瀏覽查看器,可以觸發片段交易。也就是說,在每個按鈕上單擊它將用當前按鈕偵聽器中設置的片段替換當前片段。我的控制器類創建系統,碎片就是UI。

我的活動類

public class LoggedInActivity extends AppCompatActivity { 
    private final String TAG = "LoggedInActivity: "; 
    private Controller controller; 
    private TextView navName; 
    private NavigationView navigationView; 


    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     Log.v(TAG, "onCreate"); 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_logged_in); 
     if(savedInstanceState == null) { 
      Log.v(TAG, "savedInstanceState == null"); 
      initComponents(); 
      setNavName(); 
      initListener(); 
      initializeSystem(); 
     } else { 
      Log.v(TAG, "savedInstanceState != null"); 
      initComponents(); 
      setNavName(); 
      initListener(); 
      this.controller = (Controller)savedInstanceState.getSerializable("controller"); 
     } 
    } 


    private void initComponents() { 
     navigationView = (NavigationView) findViewById(R.id.navigation_view); 
     View headerView = navigationView.getHeaderView(0); 
     navName = (TextView) headerView.findViewById(R.id.tv_name_surname); 

    } 

    private void initListener() { 
     navigationView.setNavigationItemSelectedListener(new MyNavigationItemListener()); 
    } 

    private void initializeSystem() { 
     Log.v(TAG, "new controller"); 
     controller = new Controller(this, null); 
    } 

    public void setFragment(Fragment fragment) { 
      FragmentManager fragmentManager = getFragmentManager(); 
      FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); 
      fragmentTransaction.replace(R.id.fragment_container_logged_in, fragment).commit(); 
    } 



    private class MyNavigationItemListener implements NavigationView.OnNavigationItemSelectedListener { 
     @Override 
     public boolean onNavigationItemSelected(@NonNull MenuItem item) { 
      switch(item.getItemId()) { 

       case R.id.drawer_summary: 
        controller.setFragmentSummary(); 
        break; 

       case R.id.drawer_income: 
        controller.setFragmentIncome(); 
        break; 
      } 
      return false; 
     } 
    } 


    @Override 
    protected void onSaveInstanceState(Bundle outState) { 
     outState.putSerializable("controller", controller); 
     super.onSaveInstanceState(outState); 
     Log.v(TAG, "onSaveInstanceState, saving the controller"); 
    } 

} 

我的控制器類

public class Controller implements Serializable { 
    private final String TAG = "Controller: "; 

    /********************** Fragments ***********************/ 
    private Fragment_Income fragment_income; 
    private Fragment_Summary fragment_summary; 
    /********************************************************/ 

    /********************** Activities **********************/ 
    private LoggedInActivity logged_in_activity; 
    /********************************************************/ 


    public Controller(LoggedInActivity logged_in_activity) { 
     this.logged_in_activity = logged_in_activity; 
     initLoggedInFragments(); 
     setFragmentSummary(); 

     } 
    } 



    /* Initializes fragments that are connected to LoggedInActivity */ 
    private void initLoggedInFragments() { 
     fragment_income = new Fragment_Income(); 
     fragment_income.setController(this); 
     fragment_summary = new Fragment_Summary(); 
     fragment_summary.setController(this); 
    } 



    /* use to replace current fragment with the given one */ 
    private void replaceFragmentWith(Fragment fragment) { 
     logged_in_activity.setFragment(fragment); 
    } 



    /*********************************************************** 
    *   METHODS REGARDING FRAGMENT INCOME    * 
    **********************************************************/ 

    public void setFragmentIncome() { 
     replaceFragmentWith(fragment_income); 
    } 


    /* Summary fragment is started at first */ 
    public void setFragmentSummary() { 
     replaceFragmentWith(fragment_summary); 
    } 

} 

Fragment_Income

public class Fragment_Income extends Fragment implements Serializable{ 
    private final String TAG = "Fragment_Income: "; 
    private Controller controller; 
    private FloatingActionButton fab_income; 
    private ListView lv_income; 
    private ArrayList<LvData> incomeData; 
    private LvAdapterIncome lvAdapterIncome; 

    public Fragment_Income() { 

    } 


    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     Log.v(TAG, "onCreateView"); 
     View view = inflater.inflate(R.layout.fragment_income, container, false); // Inflate the layout for this fragment 
     if(savedInstanceState != null) { 
      this.controller = (Controller) savedInstanceState.getSerializable("controller"); 
     } 
     initComponents(view); 
     initListener(); 
     setupListView(); 
     return view; 
    } 

    private void initComponents(View view) { 
     fab_income = (FloatingActionButton) view.findViewById(R.id.fab_income); 
     lv_income = (ListView) view.findViewById(R.id.lv_income); 
    } 


    private void initListener() { 
     ButtonListener buttonListener = new ButtonListener(); 
     fab_income.setOnClickListener(buttonListener); 
    } 

    private void setupListView() { 
     if (incomeData == null) { // checks if incomeData have been initalized before, if so do not change array to defualt 
      incomeData = new ArrayList<>(); 
      lvAdapterIncome = new LvAdapterIncome(getContext(), incomeData); 
     } 
     lv_income.setAdapter(lvAdapterIncome); 

    } 


    public void setController(Controller controller) { 
     this.controller = controller; 
    } 


    @Override 
    public void onSaveInstanceState(Bundle outState) { 
     Log.v(TAG, "onSaveInstanceState, saving the controller"); 
     outState.putSerializable("controller", this.controller); 
     super.onSaveInstanceState(outState); 
    } 

} 

Fragment_Summary

public class Fragment_Summary extends Fragment implements Serializable { 
    private static final String TAG = "Fragment_Summary: "; 
    private Controller controller; 
    private TextView tv_user; 
    private TextView tv_total_revenue; 
    private TextView tv_total_expenditure; 
    private TextView tv_balance; 
    private float totalRevenue; 
    private float totalExpenditure; 
    private float balance; 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     View view = inflater.inflate(R.layout.fragment_summary, container, false);// Inflate the layout for this fragment 
     initComponents(view); 
     setUserName(); 
     if(savedInstanceState == null) { 
      //DO SOMETHING 
     } 
     return view; 
    } 

    private void addData() { 
     totalRevenue = controller.getTotalRevenue(); 
     totalExpenditure = controller.getTotalExpenditure(); 
     balance = totalRevenue - totalExpenditure; 

     tv_total_revenue.setText(String.valueOf(totalRevenue)); 
     tv_total_expenditure.setText(String.valueOf(totalExpenditure)); 
     tv_balance.setText(String.valueOf(balance)); 
    } 

    private void initComponents(View view) { 
     tv_user = (TextView)view.findViewById(R.id.tv_user); 
     tv_total_revenue = (TextView)view.findViewById(R.id.tv_revenue); 
     tv_total_expenditure = (TextView)view.findViewById(R.id.tv_sum_exp); 
     tv_balance = (TextView)view.findViewById(R.id.tv_balance); 
    } 


    @Override 
    public void onSaveInstanceState(Bundle outState) { 
     outState.putString("revenue", String.valueOf(balance)); 
     outState.putString("totalExpenditure", String.valueOf(balance)); 
     outState.putString("balance", String.valueOf(balance)); 
     super.onSaveInstanceState(outState); 
    } 


    public void setController(Controller controller) { 
     this.controller = controller; 
    } 

} 

我從我的課監守我因子評分,他們不適合此問題,取消了所有的頭文件和一些方法。

以下是錯誤日誌

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState 
    at android.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1434) 
    at android.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1452) 
    at android.app.BackStackRecord.commitInternal(BackStackRecord.java:708) 
    at android.app.BackStackRecord.commit(BackStackRecord.java:672) 
    at com.example.user.my_app.LoggedInActivity.setFragment(LoggedInActivity.java:85) 
    at com.example.user.my_app.Controller.replaceFragmentWith(Controller.java:89) 
    at com.example.user.my_app.Controller.setFragmentIncome(Controller.java:99) 
    at com.example.user.my_app.LoggedInActivity$MyNavigationItemListener.onNavigationItemSelected(LoggedInActivity.java:127) 
    at android.support.design.widget.NavigationView$1.onMenuItemSelected(NavigationView.java:156) 
    at android.support.v7.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:822) 
    at android.support.v7.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:156) 
    at android.support.v7.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:969) 
    at android.support.design.internal.NavigationMenuPresenter$1.onClick(NavigationMenuPresenter.java:342) 
    at android.view.View.performClick(View.java:5637) 
    at android.view.View$PerformClick.run(View.java:22429) 
    at android.os.Handler.handleCallback(Handler.java:751) 
    at android.os.Handler.dispatchMessage(Handler.java:95) 
    at android.os.Looper.loop(Looper.java:154) 
    at android.app.ActivityThread.main(ActivityThread.java:6119) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) 
+0

嘗試使用'getSupportFragmentManager()'而不是'getFragmentManager()'因爲您使用'AppCompatActivity' – ono

+0

沒有幫助,謝謝你的答案。我發現奇怪的是,當我將commit()更改爲commitAllowingStateLoss()時,代碼給了我以下錯誤「IllegalStateException:Activity已被銷燬」。但是,如果它已經在onCreate方法中創建,它怎麼會被銷燬呢? – Pakash

回答

1

這看起來像一個活動狀態的損失。請參閱Alex Lockwood的優秀文章,標題爲"Fragment Transactions & Activity State Loss"。我一遍又一遍地提到它。

引述介紹到發帖:

因爲蜂窩的初始版本有史以來以下堆棧跟蹤和異常消息困擾的StackOverflow:

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1341) 
    at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1352) 
    at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595) 
    at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:574) 

這篇文章將解釋爲什麼並且當拋出這個異常時,最後會有幾條建議,這將有助於確保它不會再次崩潰您的應用程序。

相關問題