4

我將盡可能簡短地解釋我的問題。爲什麼片段的onResume方法在關閉從片段啓動的DialogFragment後從未觸發?

我有一個名爲FragmentA片段,點擊特定按鈕之後顯示一個DialogFragment。

public class FragmentA extends Fragment implements OnClickListener { 

    ... 

    @Override 
    public void OnClick(View v) { 
     if (v == dialogButton) { 
      showDialog(); 
     } 
    } 

    public void showDialog() { 
     String diagName = getResources().getString(R.string.dialog_title); 
     MyDialog myDialog = MyDialog.newInstance(getFragmentAValue()); 
     myDialog.show(getFragmentManager(), diagName); 
    } 
} 

public class MyDialog extends DialogFragment implements OnClickListener { 
    ... 
    @Override 
    public void onClick(View view) { 
     if (view == acceptButton) { 
      ... 
     } 
     else if (view == cancelButton) { 
      ... 
     } 
    } 
} 

該對話框顯示沒有任何問題。但是我的問題在於myDialog解散後,FragmentA中的onResume()方法永遠不會被調用,並顯示FragmentA,您可以與它進行交互而沒有任何問題。

public class FragmentA extends Fragment implements OnClickListener { 

    ... 

    @Override 
    public void onResume() { 
     super.onResume(); 
     resumeFragmentA(); 
    } 
} 

所以,我爲了解決這個問題所做的是在onActivityCreated()方法結束複製FragmentA的一個實例,並調用該方法resumeFragmentA()當用戶關閉對話框。

public class FragmentA extends Fragment implements OnClickListener { 

    FragmentA fragmentA = null; 

    ... 

    @Override 
    public void onResume() { 
     super.onResume(); 
     resumeFragmentA(); 
    } 

    @Override 
    public void onActivityCreated(Bundle savedInstanceState) { 

     ... 

     fragmentA = this; 
    } 

    ... 
} 

public class MyDialog extends DialogFragment implements OnClickListener { 
    ... 
    @Override 
    public void onClick(View view) { 
     if (view == acceptButton) { 
      storeData(); 
      dismissDialog(); 
     } 
     else if (view == cancelButton) { 
      dismissDialog(); 
     } 
    } 

    public void dismissDialog() { 
     FragmentA.fragmentA.resumeFragmentA(); 
     dismiss(); 
    } 

} 

我知道這個解決方案很棘手,但我不知道要以更輝煌的方式解決。你知道嗎?任何想法? 在此先感謝!

對於我的代碼更好的閱讀,在這裏你有我全碼:

public class FragmentA extends Fragment implements OnClickListener { 

    ... 

    FragmentA fragmentA = null; 

    ... 

    @Override 
    public void OnClick(View v) { 
     if (v == dialogButton) { 
      showDialog(); 
     } 
    } 

    public void showDialog() { 
     String diagName = getResources().getString(R.string.dialog_title); 
     MyDialog myDialog = MyDialog.newInstance(getFragmentAValue()); 
     myDialog.show(getFragmentManager(), diagName); 
    } 

    @Override 
    public void onResume() { 
     super.onResume(); 
     resumeFragmentA(); 
    } 

    @Override 
    public void onActivityCreated(Bundle savedInstanceState) { 

     ... 

     fragmentA = this; 
    } 

    ... 
} 


public class MyDialog extends DialogFragment implements OnClickListener { 

    ... 

    static MyDialog newInstance(int value) { 
     MyDialog fragment = new MyDialog(); 
     Bundle args = new Bundle(); 
     args.putInt("value", value); 
     fragment.setArguments(args); 
     return fragment; 
    } 

    @Override 
    public void onClick(View view) { 
     if (view == acceptButton) { 
      storeData(); 
      dismissDialog(); 
     } 
     else if (view == cancelButton) { 
      dismissDialog(); 
     } 
    } 

    public void dismissDialog() { 
     FragmentA.fragmentA.resumeFragmentA(); 
     dismiss(); 
    } 

    ... 

} 

回答

0

現在,谷歌已經發布的Android架構組件庫,最好的辦法是兩個片段之間使用共享視圖模型與您的活動作爲實現LifecycleRegistryOwner之一。

這樣做,我們將避免清爽UI調用的onResume,我們不需要任何代碼棘手的解決方案。

一個解決方案可以是下列之一:

public MyActivity extends AppCompatActivity { 

    ... 

} 

public class FragmentA extends Fragment implements OnClickListener { 

    ... 

    private SharedViewModel mSharedViewModel; 

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

     mSharedViewModel = ViewModelProviders.of(getActivity()).get(SharedViewModel.class); 

     mSharedViewModel.getData().observe(this, value -> { 
      updateUIValue(value); 
     }); 

    } 

    @Override 
    public void OnClick(View v) { 
     if (v == dialogButton) { 
      showDialog(); 
     } 
    } 

    @Override 
    public void OnClick(View v) { 
     if (v == dialogButton) { 
      showDialog(); 
     } 
    } 

    public void showDialog() { 
     String diagName = getResources().getString(R.string.dialog_title); 
     MyDialog myDialog = MyDialog.newInstance(getFragmentAValue()); 
     myDialog.show(getFragmentManager(), diagName); 
    } 
} 

public class MyDialog extends DialogFragment implements OnClickListener { 

    ... 

    private SharedViewModel mSharedViewModel; 

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

     mSharedViewModel = ViewModelProviders.of(getActivity()).get(SharedViewModel.class); 

     mSharedViewModel.getData().observe(this, value -> { 
      updateUIValue(value); 
     }); 

    } 

    @Override 
    public void onClick(View view) { 
     if (view == acceptButton) { 
      ... 

      mSharedViewModel.setValue(newValue); 
     } 
     else if (view == cancelButton) { 
      dismiss(); 
     } 
    } 
} 


public class SharedViewModel extends ViewModel { 

    final MutableLiveData<Resource<Value>> data = new MutableLiveData<>(); 

    public MutableLiveData<Value> getData() { 
     return data; 
    } 

    public void setValue(Value newValue) { 
     this.data.setValue(newValue) 
    } 
} 
2

如果你只是想調用的onResume FragmentA的,讓你的DialogFragment裏面startActivityForResult一個電話,並啓動FragmentActivity。這將調用onResume。

public void dismissDialog() { 
    getActivity().startActivityForResult(getActivity().getIntent(), 10); 
    dismiss() 
} 
+0

我不知道這是否是最好的方式,但它爲我工作。你能解釋爲什麼嗎?它強制活動的onResume(和所包含片段的onResumed)被調用? –

+0

這會創建一個新的Activity,它不能解決我們的問題! –

0

另一種方法是通過實現一個接口。創建一個接口並讓活動/片段(您需要的一個)實現它,然後將其本身作爲接口對象傳遞給您的DialogFragment

CustomDialogFragment df = new CustomDialogFragment(); 
Bundle b = new Bundle(); 
b.putSerializable(KEY, this); // current activity/fragment that implements the interface 
df.setArguments(b); 
df.show(getFragmentManager(), TAG); 

然後在你DialogFragment得到監聽器,並調用監聽器的方法,當你需要(在這種情況下,後/你叫dismiss()之前)。