點擊 ListView 項目彈出 DialogFragment 編輯數據,確認後數據已保存,但 ListView 未即時刷新;再次點擊同一項目時才顯示更新後的值。
// 錯誤代碼片段
LoginDialogFragment dialog = new LoginDialogFragment();
dialog.show(getFragmentManager(), "loginDialog"); // 非阻塞,立即返回
pp.setHeight(height); // 此時 height 仍是舊值!
mAdapter.notifyDataSetChanged(); // 刷新了舊數據
dialog.show() 是異步非阻塞的:它只負責排程顯示對話框,隨後代碼立即繼續執行,而非等待用戶操作完成。
public interface LoginInputListener {
void onLoginInputComplete(String username);
}
.setPositiveButton("Sign in", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
LoginInputListener listener = (LoginInputListener) getActivity();
listener.onLoginInputComplete(mUsername.getText().toString());
}
})
public class MainActivity extends Activity implements LoginInputListener {
// ...
@Override
public void onLoginInputComplete(String username) {
// 此處執行於用戶點擊「確定」後
Person pp = (Person) mAdapter.getItem(selectedPosition); // 需記錄 position
pp.setHeight(username);
mAdapter.notifyDataSetChanged(); // 刷新最新數據
}
}
// 方案一:通過 Bundle
Bundle args = new Bundle();
args.putInt("position", position);
dialog.setArguments(args);
// 方案二:構造方法/Setter
dialog.setTargetPosition(position);
| 錯誤做法 | 正確做法 |
|---|---|
| show() 後立即刷新 | 在 onLoginInputComplete 回調中刷新 |
| 使用全局變量 height | 直接在回調參數中獲取新值 |
| 未記錄編輯項目 position | 通過 Bundle/Setter 傳遞 position |
更規範的 Fragment 通信方式:
// 調用方
dialog.setTargetFragment(this, REQUEST_CODE);
dialog.show(getFragmentManager(), "tag");
// Dialog 內部
getTargetFragment().onActivityResult(REQUEST_CODE, RESULT_OK, data);