java如何使DatePickerDialog在更改屏幕方向时保持选定的用户日期?
在打开的DatePickerDialog中,当屏幕方向改变时,它会重置所选的用户数据
(DatePickerDialog不会关闭,也不会维护所选数据)
代码:
public class ActivityNeki extends FragmentActivity {
DialogFragment newDF = null;
private int datY, datM, datD;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity);
if(savedInstanceState == null){ setTheData(); writeTheData(); }
}
@Override protected void onSaveInstanceState(Bundle outState) {
outState.putInt("izY", datY); outState.putInt("izM", datM); outState.putInt("izD", datD);
super.onSaveInstanceState(outState);
}
@Override protected void onRestoreInstanceState(Bundle savedInstanceState) { super.onRestoreInstanceState(savedInstanceState);
datY = savedInstanceState.getInt("izY"); datM = savedInstanceState.getInt("izM"); datD = savedInstanceState.getInt("izD");
writeTheData();
}
public void onClickOpenDPD(View view) { // the method that is caled from XML onClick
class MyDialogFragment extends DialogFragment {
@Override public void onDestroyView() {
if (getDialog() != null && getRetainInstance()) getDialog().setDismissMessage(null);
super.onDestroyView();
}
@Override public void onCreate(Bundle state) { super.onCreate(state);
setRetainInstance(true);
}
@Override public Dialog onCreateDialog(Bundle state) {
DatePickerDialog dpd = new DatePickerDialog( getActivity(), new DatePickerDialog.OnDateSetListener() {
@Override public void onDateSet(DatePicker view, int leto, int mesec, int dan) {
datY = leto; datM = mesec; datD = dan;
writeTheData();
} }, datY, datM, datD);
return dpd;
}
}
newDF = new MyDialogFragment();
newDF.show( getSupportFragmentManager(), null );
}
public void setTheData(){
Calendar c = Calendar.getInstance();
datY = c.get(Calendar.YEAR); datM = c.get(Calendar.MONTH); datD = c.get(Calendar.DAY_OF_MONTH);
}
public void writeTheData(){ /* writes the data in a txtView */ }
}
建议我,如何解决这个问题
# 1 楼答案
正确实现的DialogFragment将能够恢复状态,而无需您进行任何额外的工作。代码中的主要问题是非静态内部类。这是有缺陷的,原因有二:
非静态的内部类自然会保留对其外部类的引用(参见#2中的链接)。这实际上是指你的活动、你的背景、你的观点;基本上,用户所面临的一切。当设备旋转或用户切换到其他应用程序时,您的应用程序很可能会关闭。然而,保留的片段将保持活性,这有时非常有用。但是,由于在您的情况下它是一个内部类,所以不允许垃圾收集对上下文、活动等进行垃圾回收,因为仍然存在一个活动引用。因此,您正在泄漏内存。如果您在应用程序重新创建后访问此上下文(例如更新视图),您将得到一个运行时异常,告诉您您正在处理一个过时的上下文/视图。如果你真的想沿着那条路走,你可能想去看看
WeakReference
https://stackoverflow.com/a/10968689/1493269
非静态内部类危险的另一个原因是它们从不提供默认构造函数。但是Android框架要求每个片段都有一个空构造函数,以便在幕后实例化它。如果你的应用程序被删除并重新启动(例如,在旋转更改时),那么Android将通过强制默认构造函数重新实例化你的片段,然后通过序列化包恢复状态。如果没有默认构造函数:运行时异常。你通过保留片段来解决这个问题,但我在1)中解释了为什么这也不好
http://thecodersbreakfast.net/index.php?post/2011/09/26/Inner-classes-and-the-myth-of-the-default-constructor
故事的寓意:小心非静态的内部类
您的代码应该如何工作:
ActivityNeki。java
MyDialogFragment。java
请原谅我的小错误,因为我没有经过测试就把它写在了我的头上
# 2 楼答案
你的代码看起来很糟糕
首先,在方法体中声明匿名片段类-但是,最好将该类与
Activity
类分开,或者使其成为静态内部类然后,您
setRetainInstance(true)
,它告诉Android不要在活动旋转时销毁片段。这是用于其他用例的,而您的用例不是我建议您阅读以下信息:
Handling runtime changes
Activity Lifecycle
How to communicate Activity with Fragments
基本上,如果你按照安卓规则玩游戏,大部分用户输入将在设备旋转时为你保存(见上面的链接)
# 3 楼答案
当方向改变时,应用程序实际上被销毁并再次创建。因此,您必须将状态保存到某个位置,例如在instantState包中
新编辑
我尝试了另一种方法,使用OnClickListener回调按钮,状态保持不变