12

Tôi gặp vấn đề rất lạ với các đoạn. Tôi sử dụng thư viện hỗ trợ mới nhất. Tôi cũng sử dụng mã tương tự như được Google sử dụng trong IOSCHED projectAndroid: Nhân bản các đoạn mã khi sử dụng Trình quản lý hỗ trợ Fragment

Nhưng tôi gặp sự cố khi tạo lại hoạt động sau khi xoay. Sau khi một hoạt động bị hủy và được tạo lại, tôi gọi các phương thức để quản lý giao dịch phân đoạn (trong phương thức onStart). Dòng này chỉ được gọi một lần, nhưng nó tạo ra đoạn TWICE!

Đây là phương pháp của tôi hoạt động:

public abstract class SinglePaneActivity extends FragmentActivity 
{ 
    @Override 
    protected void onStart() 
    { 
     super.onStart(); 

     if(mFragment == null) 
     { 
      mFragment = onCreatePane();  
      mFragment.setArguments(Utils.intentToFragmentArguments(getIntent())); 

      Log.w(TAG, "Fragment creation counter = " + createCounter); 
      createCounter++; 

      getSupportFragmentManager() 
      .beginTransaction() 
      .add(R.id.root_container,mFragment) 
      .commit(); 
     } 
    } 

    @Override 
    protected void onStop() 
    { 
     Log.i(TAG, "onStop"); 
     if(mFragment != null) 
     { 
      getSupportFragmentManager() 
      .beginTransaction() 
      .remove(mFragment) 
      .commit(); 

      mFragment = null; 
     } 
     super.onStop(); 
    } 
} 

và các bản ghi của tôi:

--Start of application-- 
11-18 13:26:37.050: I/SinglePaneActivity(19040): onCreate 
11-18 13:26:37.050: I/SinglePaneActivity(19040): onStart 
11-18 13:26:37.055: W/SinglePaneActivity(19040): replacing fragment, counter = 1 
11-18 13:26:37.075: I/MyFragment(19040): onCreate 
11-18 13:26:37.110: I/MyFragment(19040): onActivityCreated 
--Rotating the device-- 
11-18 13:26:39.600: I/SinglePaneActivity(19040): onStop 
11-18 13:26:39.600: I/SinglePaneActivity(19040): onDestroy 
11-18 13:26:39.605: I/MyFragment(19040): onDestroy 
11-18 13:26:39.755: I/MyFragment(19040): onCreate 
11-18 13:26:39.755: I/SinglePaneActivity(19040): onCreate 
11-18 13:26:39.790: I/MyFragment(19040): onActivityCreated 
11-18 13:26:39.800: I/SinglePaneActivity(19040): onStart 
11-18 13:26:39.800: W/SinglePaneActivity(19040): replacing fragment, counter = 2 
11-18 13:26:39.810: I/MyFragment(19040): onCreate 
11-18 13:26:39.815: I/MyFragment(19040): onActivityCreated 
--Rotating the device back-- 
11-18 13:36:47.060: I/SinglePaneActivity(19040): onStop 
11-18 13:36:47.060: I/SinglePaneActivity(19040): onDestroy 
11-18 13:36:47.060: I/MyFragment(19040): onDestroy 
11-18 13:36:47.065: I/MyFragment(19040): onDestroy 
11-18 13:36:47.130: I/MyFragment(19040): onCreate 
11-18 13:36:47.130: I/MyFragment(19040): onCreate 
11-18 13:36:47.130: I/SinglePaneActivity(19040): onCreate 
11-18 13:36:47.140: I/MyFragment(19040): onActivityCreated 
11-18 13:36:47.150: I/MyFragment(19040): onActivityCreated 
11-18 13:36:47.150: I/SinglePaneActivity(19040): onStart 
11-18 13:36:47.150: W/SinglePaneActivity(19040): replacing fragment, counter = 3 
11-18 13:36:47.160: I/MyFragment(19040): onCreate 
11-18 13:36:47.160: I/MyFragment(19040): onActivityCreated 
--Exiting the app-- 
11-18 13:36:48.880: I/SinglePaneActivity(19040): onStop 
11-18 13:36:48.885: I/SinglePaneActivity(19040): onDestroy 
11-18 13:36:48.885: I/MyFragment(19040): onDestroy 
11-18 13:36:48.890: I/MyFragment(19040): onDestroy 
11-18 13:36:48.890: I/MyFragment(19040): onDestroy 

Vì vậy, số lượng các mảnh vỡ được phát triển sau mỗi lần quay.

Sau khi xoay, nó khôi phục phân đoạn trước khi nó đi đến phương thức onStart của tôi và phương thức onStart của tôi tạo ra cùng một đoạn thứ hai trong cùng một thùng chứa Bố cục khung. Nhưng ở đâu nó phục hồi mảnh đầu tiên? Tôi muốn bỏ qua nó. Hoặc tôi nên thay đổi "if" của tôi để kiểm tra xem nó đã được tạo chưa? Nhưng tôi không biết làm thế nào để xác định nó. Có vẻ như kiểm tra null là vô ích.

Tôi cũng đã thực hiện giải pháp thay thế nhỏ bằng cách thay thế phương thức add() theo replace(). Sau đó, số lượng các mảnh không phát triển và mỗi đoạn bị phá hủy trước khi phân đoạn mới được tạo theo phương pháp onStart. Nhưng điều này làm cho vấn đề nghiêm trọng trong một số mảnh mà tôi bắt đầu một số quy trình nền trong của họ trên phương pháp ... Phương pháp ...

Hãy giúp tôi ... Tôi thực sự không biết phải làm gì với nó. Cảm ơn bạn rất nhiều vì lời khuyên hay ý kiến!

Trả lời

23

Tôi đã tìm được giải pháp. Tôi đã phải di chuyển mã với trình quản lý phân đoạn từ onStart sang onCreate và kiểm tra null giá trị của savedInstanceState. Tôi cũng không biết rằng nó được lưu và khôi phục từ savedInstanceState một cách tự động. Tốt để biết!

EDIT: Và để làm điều đó hoàn toàn đúng, tức là khôi phục đoạn khi savedInstanceState không phải là null, cần có:

if(savedInstanceState == null) 
    { 
     mFragment = onCreatePane();  
     mFragment.setArguments(Utils.intentToFragmentArguments(getIntent())); 

     getSupportFragmentManager() 
     .beginTransaction() 
     .add(R.id.root_container,mFragment) 
     .commit(); 
    } 
    else 
    { 
     mFragment = getSupportFragmentManager().findFragmentById(R.id.root_container); 
    } 
+0

Có! Cảm ơn bạn. Tôi đã đấu tranh với cùng một vấn đề. kiểm tra cho một lưu savedInstanceState trong hoạt động của tôi trước khi tải mảnh của tôi đã làm các trick – Chiatar

-1

Hoặc nếu mảnh của bạn không trong ngăn xếp trở lại: setRetainInstance(true);

+1

Điều này không được khuyến khích. Nếu mảnh chứa bất kỳ tham chiếu đến một thể hiện của hoạt động; trực tiếp hoặc thông qua một thành viên như một cái nhìn, điều này sẽ gây ra rò rỉ bộ nhớ. – frostymarvelous

1

Tôi đã có một vấn đề tương tự, nhưng tôi đã thêm một mảnh con từ một đoạn cha và nhìn thấy một mảnh con trùng lặp. Tôi đã cố gắng thêm nó vào onStart của đoạn phụ huynh để tôi có thể truy cập chế độ xem gốc, không có sẵn trong onCreate. Vì vậy, thay vì di chuyển mã đến onCreate, tôi đã chuyển mã đó sang onActivityCreated; phương thức đó có quyền truy cập vào chế độ xem gốc và cũng có quyền truy cập vào biến số savedInstanceState để kiểm tra xem phân đoạn đó đã được thêm tự động chưa. Đây không phải là vấn đề khi thêm một đoạn từ hoạt động vì chế độ xem của hoạt động có sẵn trong onCreate.


Nếu vì một số lý do bạn cần phải thêm một đoạn trong onStart này hay cách khác nơi savedInstanceState không có sẵn, đây là một sự thay thế. Sử dụng mã onStart gốc từ câu hỏi ...

if(mFragment == null) 
    { 
     mFragment = onCreatePane();  
     mFragment.setArguments(Utils.intentToFragmentArguments(getIntent())); 

     Log.w(TAG, "Fragment creation counter = " + createCounter); 
     createCounter++; 

     getSupportFragmentManager() 
     .beginTransaction() 
     .add(R.id.root_container,mFragment) 
     .commit(); 
    } 

...bạn có thể replace hơn add đoạn:

if(mFragment == null) 
    { 
     mFragment = onCreatePane();  
     mFragment.setArguments(Utils.intentToFragmentArguments(getIntent())); 

     Log.w(TAG, "Fragment creation counter = " + createCounter); 
     createCounter++; 
    } 

    getSupportFragmentManager() 
    .beginTransaction() 
    .replace(R.id.root_container,mFragment) 
    .commit(); 

Sau đó, nếu các mảnh đã được tự động thêm vào đoạn mới của bạn sẽ chỉ thay thế nó trong giao diện.

Các vấn đề liên quan