8

Tôi đã gặp phải một chút rào cản. Tôi có một kịch bản RẤT tương tự như mô tả tại: DialogFragment - retaining listener after screen rotationLàm cách nào để giữ chân người nghe trên hộp thoại tùy chỉnh được mở từ đoạn?

Giải pháp được đề xuất hoạt động tốt cho tác giả vì hộp thoại của anh đang được gọi từ một hoạt động. Trường hợp của tôi là chính xác, nhưng Hộp thoại Tuỳ chỉnh của tôi được gọi từ một Fragment thay vì một Activity. (Hoạt động IE-> Fragment-> Dialog)

Tôi đã triển khai cùng một giải pháp (thiết lập trình lắng nghe trong onResume từ phân đoạn gọi) nhưng nó không hoạt động trong trường hợp này.

Điều có vẻ đang xảy ra là khi màn hình được xoay, Android sẽ giết Hộp thoại và Phân đoạn. Sau đó tạo lại chúng TRONG THỨ TỰ ĐẶT HÀNG. Vì vậy, khi onCreateDialog của tôi được gọi trên hộp thoại tùy chỉnh của tôi, Fragment chứa vẫn chưa được tạo lại, do đó, nó có null cho trình nghe để thiết lập cho các nút tích cực và tiêu cực.

Có ai biết cách này không?

Tôi có thể đăng mã nếu có ai đó nghĩ rằng nó sẽ cần thiết, nhưng nó khá giống với mã trên chuỗi được liên kết.

CẬP NHẬT VỚI Mã sản phẩm:

public class RecipeDetailEditFragment extends SherlockFragment implements DialogInterface.OnClickListener { 
    private EditStepFragmentDialog stepDialog; 
    private Recipe newRecipe; //main data object implements parcelable 
    ... 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     ... 
     stepDialog = EditStepFragmentDialog.newInstance(newRecipe); 
     //I've also tried passing 'this' into the newInstance constructor and 
     //setting the listener there, but that doesn't work either 
    } 

    public void onResume() { 
     stepDialog.setListener(this); 
     super.onResume(); 
    } 
    ... 
} 


public class EditStepFragmentDialog extends DialogFragment { 
    private DialogInterface.OnClickListener ocl; 
    private static final String ARG_RECIPE = "recipe"; 
    private Recipe recipe; 

    public EditStepFragmentDialog() {} 

    public static EditStepFragmentDialog newInstance(Recipe rec) { //(Recipe rec, DialogInterface.OnClickListener oc) as mentioned doesn't work. 
     EditStepFragmentDialog dia = new EditStepFragmentDialog(); 
     Bundle args = new Bundle(); 
     args.putParcelable(ARG_RECIPE, rec); 

     //dia.setListener(oc); 
     return dia; 
    } 

    public Dialog onCreateDialog(Bundle savedInstanceState) { 
     AlertDialog.Builder adb = new AlertDialog.Builder(getActivity()); 

     if (getArguments().containsKey(ARG_RECIPE)) { 
      recipe = (Recipe) getArguments().getParcelable(ARG_RECIPE); 
     } 
     ... 

     adb.setPositiveButton("Done", ocl); 
     adb.setNegativeButton("Cancel", ocl); 

     ... 

     return adb.create(); 
    } 

    public void setListener(DialogInterface.OnClickListener cl) { 
     ocl = cl; 
    } 
} 
+0

Bạn sẽ phải đăng mã – Atomix

Trả lời

3

Tôi đã chạy qua tất cả các tùy chọn trên các liên kết được thảo luận và không có giải pháp nào kết thúc với tôi. Tôi cũng đã thử một số tùy chọn bổ sung sau khi thêm googling như get/setTargetFragment và FragmentManager.put/getFragment. Những thứ này cũng không hiệu quả với tôi. Sau đó, tôi mất một cái nhìn tại địa chỉ:

http://developer.android.com/training/basics/fragments/communicating.html

đâu họ đặc biệt nói "Hai mảnh vỡ không bao giờ nên trao đổi trực tiếp". Tôi nghĩ đây là một trong những trường hợp thực sự được chứng minh là đúng.

tôi đã kết thúc việc thực hiện các cơ chế gọi lại đề nghị được cung cấp ở đó và đã kết thúc với điều này:

Trong DialogFragment:

public interface OnEditStepDialogListener { 
    public void onEditStepDialogPositive(int pos, String description); 
} 

@Override 
public void onAttach(Activity activity) { 
    super.onAttach(activity); 

    try { 
     mCallback = (OnEditStepDialogListener) activity; 
    } catch (ClassCastException e) { 
     throw new ClassCastException(activity.toString() + " must implement OnEditStepDialogListener"); 
    } 
} 

Trong Hoạt động lưu trữ:

public class MyActivity extends SherlockFragmentActivity implements EditStepFragmentDialog.OnEditStepDialogListener { 

... 

@Override 
public void onEditStepDialogPositive(int pos, String desc) { 
    FragmentManager fm = getSupportFragmentManager(); 
    RecipeDetailEditFragment ef = (RecipeDetailEditFragment)fm.findFragmentByTag(RecipeDetailEditFragment.TAG); 

    ef.applyStepEdit(pos, desc); 
} 

Trong Fragment mà tắt đám cháy the FragmentDialog:

public static final String TAG = "tag1"; 

public void applyStepEdit(int pos, String description) { 
    ... 
} 

Điều này hoạt động hoàn hảo, nếu mở thì thay đổi định hướng và chỉnh sửa được hoàn thành, nó thực sự kích hoạt chức năng cuối cùng tôi cần chạy trong Fragment gọi thay vì bị rơi hoặc không làm gì (null listener).

+0

Tuyệt vời bạn tìm thấy một giải pháp! Chỉ cần một chú thích nhỏ, điều này làm cho bạn có thể mở rộng đoạn để lấy một đối số khác về tạo, một OnEditStepDialogListener để xử lý gọi lại, chỉ trong trường hợp bạn không thích xử lý mọi cuộc gọi lại trong lớp Activity của bạn. – cYrixmorten

0

Nó sẽ là một thảm họa để báo cáo lại cho hoạt động của bạn và làm cho điều đó tạo ra hộp thoại?

Tôi vừa xem lại mã của mình để xem tôi đang làm gì vì tôi chưa gặp sự cố này. Đưa tôi về nó là một cái gì đó như thế này:

- MyActivity 
    | 
    ---- MapsFragmet (for example) 
    | 
    ---- DirectionsModule (simple class that is handed Context) 
    | 
    ---- PointsOfInterestModule (simple class that is handed Context) 

Như vậy với xây dựng này hoạt động sử dụng các đoạn thuần túy để hiển thị bản đồ nhưng có thể sử dụng nó cho cả purpos của hướng, hoặc điểm đáng chú ý, tùy thuộc vào mô-đun Được gọi.

Bây giờ khi mô-đun gặp sự cố hoặc cần tương tác với người dùng, nó báo cáo lại thành MyActivity, ví dụ sau đó sẽ hiển thị Hộp thoại.

Muốn đưa ra câu trả lời đúng hơn, vì tôi không hiểu tại sao bạn không thể gọi một DialogFragment từ bên trong một Fragment khác và mong đợi một hành vi tốt đẹp.

Chỉ trong trường hợp, bạn đã đặt setRetainInstance (true) trên bạn Fragment chưa?

Edit:

Ok, vì vậy tôi chỉ xem xét mã mới được cam kết của mình, đây là ý tưởng mới của tôi:

Mở rộng các đối số của hộp thoại của bạn để có một bối cảnh như vậy u có thể gọi nó như thế này :

stepDialog = EditStepFragmentDialog.newInstance(getActivity(), newRecipe); 

Tiếp theo sử dụng bối cảnh thêm thay vì getActivity() trong hộp thoại của bạn:

AlertDialog.Builder adb = new AlertDialog.Builder(context); 

Tôi nghi ngờ (không chắc chắn về điều này) mà SherlockFragment được tính là một thể hiện của Hoạt động, vì vậy khi bạn gọi hàm getActivity() trong hộp thoại của bạn, nó được gắn với đoạn của bạn.

+0

Nó sẽ không phải là một thảm họa, nhưng tôi muốn một giải pháp cho phép một Fragment để đáp ứng với một hộp thoại nó kích hoạt tự của nó. Nếu không có ai khác có một lựa chọn tốt hơn, tôi sẽ xem đây là câu trả lời tốt nhất. Tôi đã thử setRetainInstance trên mảnh vỡ, và nó dường như không giúp được gì. – user2229491

+0

chỉ cần thực hiện một chỉnh sửa mới (bạn có được tự động thông báo về điều này không?) – cYrixmorten

+0

Tôi vừa thử làm theo cách đó (ngữ cảnh nội bộ và hàm setContext được gọi trong hàm tạo getInstance để đặt nó) và bây giờ nó bị treo nếu bạn xoay sau khi bật lên được hiển thị . Tôi khá chắc chắn đó là lý do tương tự như vấn đề với Listener ... Hộp thoại được tái tạo trước khi Fragment như vậy, khi nó lần đầu tiên chạy onCreateDialog đối tượng bối cảnh nội bộ chưa được thiết lập ... – user2229491