编辑:我发现Activity保存了实例,但是Fragment保存的数据并没有传递到Activity的savedInstanceState中。我在outState中保存了当前时间,但是这个时间并没有传递到Activity的SavedInstanceState中。如果我将其打印到日志中,Activity中的时间返回“null”...
我正在构建一个应用程序,其中包含计时器。计时器的基本托管活动是FragmentActivity,它托管一个FragementPagerAdapter,在代码中填充了两个片段(我没有为XML中的片段定义ID,因为它们在.xml中没有定义为片段)。一切都很正常,直到方向改变,然后活动似乎失去与旧片段的联系,只选择创建新的片段。这意味着任何当前倒计时都会丢失,并且任何选择的时间也会在配置更改时丢失。我需要保持计数(如果已经开始),并保留任何当前显示的数字...
我知道适配器应该自己处理这些事情,并在OnCreate和OnCreateView中设置SetRetainInstance(true)。
我在Fragment代码中添加了钩子,以便在saveInstanceState不为null时让我知道情况,但似乎实例始终为NULL,并且从头开始创建...一直。
其他一些解决方案让我重写instantiateItem,但似乎它仅用于重置回调,其他则更改Manifest中的设置(这被反对)...其他解决方案看起来对我来说设置正确...但显然,我在途中搞砸了什么。我只提供FragmentActivity、FragementPagerAdapter和一些Fragment代码的代码,因为我不想在帖子中发布可能不是问题的代码。
FragmentActivity
我正在构建一个应用程序,其中包含计时器。计时器的基本托管活动是FragmentActivity,它托管一个FragementPagerAdapter,在代码中填充了两个片段(我没有为XML中的片段定义ID,因为它们在.xml中没有定义为片段)。一切都很正常,直到方向改变,然后活动似乎失去与旧片段的联系,只选择创建新的片段。这意味着任何当前倒计时都会丢失,并且任何选择的时间也会在配置更改时丢失。我需要保持计数(如果已经开始),并保留任何当前显示的数字...
我知道适配器应该自己处理这些事情,并在OnCreate和OnCreateView中设置SetRetainInstance(true)。
我在Fragment代码中添加了钩子,以便在saveInstanceState不为null时让我知道情况,但似乎实例始终为NULL,并且从头开始创建...一直。
其他一些解决方案让我重写instantiateItem,但似乎它仅用于重置回调,其他则更改Manifest中的设置(这被反对)...其他解决方案看起来对我来说设置正确...但显然,我在途中搞砸了什么。我只提供FragmentActivity、FragementPagerAdapter和一些Fragment代码的代码,因为我不想在帖子中发布可能不是问题的代码。
FragmentActivity
public class Timer_Main extends FragmentActivity {
ViewPager pager;
Timer_Pager mAdapter;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.timer_pager);
mAdapter = new Timer_Pager(this, getSupportFragmentManager());
pager = (ViewPager) findViewById(R.id.timer_pager_display);
pager.setAdapter(mAdapter);
}
public static String getTitle(Context ctxt, int position) {
// TODO Auto-generated method stub
return null;
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("pageItem", pager.getCurrentItem());
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
}
}
The FragementPagerAdapter
public class Timer_Pager extends FragmentPagerAdapter{
Context ctxt = null;
public Timer_Pager(Context ctxt, FragmentManager fm) {
super(fm);
this.ctxt = ctxt;
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0: {
return(Countdown_Fragment.newInstance());
}
case 1:
return(Countup_Fragment.newInstance());
}
return null;
}
@Override
public String getPageTitle(int position) {
switch (position) {
case 0:
return(String.format(ctxt.getString(R.string.Countdown_label)));
case 1:
return(String.format(ctxt.getString(R.string.Countup_label)));
}
return null;
}
@Override
public int getCount() {
// doing only three pages, right now...one for countdown, one for countup, and one for Tabata.
return 2;
}
private static String makeFragmentName(int viewId, int position)
{
return "android:switcher:" + viewId + ":" + position;
}
}
这个Fragment代码有点多,所以我只会推送核心问题的部分... 如果需要更多内容,我会将它们拼接在一起。
public class Countdown_Fragment extends Fragment implements OnClickListener {
Calendar CountdownTime = Calendar.getInstance();
static AutoResizeTextView tv;
static ImageButton HoursUp;
static ImageButton HoursDown;
static ImageButton MinutesUp;
static ImageButton MinutesDown;
static ImageButton SecondsUp;
static ImageButton SecondsDown;
static ImageButton Reset;
static ImageButton StartPausecount;
static ImageButton Stopcount;
static Boolean Arewecounting = false;
static Boolean Arewecountingdown = false;
static AutoResizeTextView ThreetwooneGO;
static MyCountdownTimer Countdown_Timer_Activity;
ThreetwooneCount Start_countdown;
static Long MillstoPass;
static Countdown_Fragment newInstance() {
Countdown_Fragment frag = new Countdown_Fragment();
return (frag);
}
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putString("CurrentTimer", (String) tv.getText());
Log.v("status", "saved fragment state" + tv.getText());
super.onSaveInstanceState(outState);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
}
@Override
public void onCreate(Bundle savedInstanceState) {
setRetainInstance(true);
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
setRetainInstance(true);
View result = inflater.inflate(R.layout.countdown_timer_layout,
container, false);
tv = (AutoResizeTextView) result.findViewById(R.id.timer_textview);
tv.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
new TimePickerDialog(getActivity(), t, 0, 0, true).show();
}
});
if (savedInstanceState != null) {
Log.v("status", "fragment is NOT empty");
tv.setText(savedInstanceState.getString("CurrentTimer",
tv.toString()));
} else {
Log.v("status", "fragment is empty");
// tv.setText("00:00:00");
}
tv.resizeText();
ThreetwooneGO = (AutoResizeTextView) result
.findViewById(R.id.timer_countdown_text);
HoursUp = (ImageButton) result.findViewById(R.id.hours_up);
HoursDown = (ImageButton) result.findViewById(R.id.hours_down);
MinutesUp = (ImageButton) result.findViewById(R.id.minutes_up);
MinutesDown = (ImageButton) result.findViewById(R.id.minutes_down);
SecondsUp = (ImageButton) result.findViewById(R.id.seconds_up);
SecondsDown = (ImageButton) result.findViewById(R.id.seconds_down);
Reset = (ImageButton) result.findViewById(R.id.reset);
StartPausecount = (ImageButton) result
.findViewById(R.id.startpausecount);
Stopcount = (ImageButton) result.findViewById(R.id.stopcount);
HoursUp.setOnClickListener(this);
HoursDown.setOnClickListener(this);
SecondsUp.setOnClickListener(this);
SecondsDown.setOnClickListener(this);
MinutesUp.setOnClickListener(this);
MinutesDown.setOnClickListener(this);
Reset.setOnClickListener(this);
StartPausecount.setOnClickListener(this);
Stopcount.setOnClickListener(this);
return (result);
}
public void chooseTime(View v) {
new TimePickerDialog(getActivity(), t, 0, 0, true).show();
}
TimePickerDialog.OnTimeSetListener t = new TimePickerDialog.OnTimeSetListener() {
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
CountdownTime.set(Calendar.HOUR_OF_DAY, hourOfDay);
CountdownTime.set(Calendar.MINUTE, minute);
CountdownTime.set(Calendar.SECOND, 0);
CountdownTime.set(Calendar.MILLISECOND, 0);
updateLabel();
}
};
private void updateLabel() {
String entiretime;
entiretime = String.format("%tT", CountdownTime);
tv.setText(entiretime);
}
这是我用于倒计时的计时器...
public class MyCountdownTimer {
private long millisInFuture;
private long countDownInterval;
Countdown_Fragment ctxt;
AutoResizeTextView Timer_edit;
private volatile boolean IsStopped = false;
public MyCountdownTimer(long pMillisInFuture, long pCountDownInterval,
AutoResizeTextView Artv) {
this.millisInFuture = pMillisInFuture;
this.countDownInterval = pCountDownInterval;
Timer_edit = Artv;
}
public void Start() {
final Handler handler = new Handler();
final Runnable counter = new Runnable() {
public void run() {
if (IsStopped == false) {
if (millisInFuture <= 0) {
Countdown_Fragment.done_counting();
} else {
long sec = millisInFuture / 1000;
Timer_edit.setText(String.format("%02d:%02d:%02d",
sec / 3600, (sec % 3600) / 60, (sec % 60)));
millisInFuture -= countDownInterval;
handler.postDelayed(this, countDownInterval);
}
}
}
};
handler.postDelayed(counter, countDownInterval);
}
public void Cancel() {
IsStopped = true;
Timer_edit = null;
Log.v("status", "Main Timer cancelled");
// this.ctxt = null;
}
public long whatisourcount(){
return(millisInFuture);
}
}