6

EDIT:アクティビティがインスタンスを保存していますが、フラグメント保存データがアクティビティsavedInstanceStateになっていないことがわかりました。私はoutStateに現在の時間を保存していますが、そのアクティビティは時間のSavedInstanceStateに何もないので、logcatに出力するとその時間は 'null'を返します。 ..FragmentPagerAdapterはオリエンテーション変更時にフラグメントを復元しません

私は、カウントアップとカウントダウンタイマーが組み込まれているアプリケーションを構築しています。タイマーの基本的なホストアクティビティは、コード内に2つのフラグメントを展開するFragementPagerAdapterをホストするFragmentActivityです(id .xml内のフラグメントとして定義されていないため、XML内のフラグメントに追加します)。オリエンテーションが変わるまではすべてがうまくいき、古い断片との接触がなくなり、新しい断片を作成するように選択するだけです。これは、現在のカウントダウンが失われ、設定が変更されると選択された時間も失われることを意味します。 (開始された場合)、現在表示されている数値が残っている必要があります。

アダプターはこれらのことを自分で処理することになっています。SetRetainInstance(true )をOnCreateとOnCreateViewの両方で使用します。

saveInstanceStateがnullでないため、少なくとも私は何が起こっているのか分かりませんが、インスタンスが常にNULLであるように見えますが、スクラッチから作成すると、フラグメントコードにフックを入れます。常に。

instantiateItemをオーバーライドするいくつかのソリューションがありますが、コールバックがリセットされ、マニフェストの設定が変更されている他のソリューション(....)セットアップの権利...しかし、明らかに、私は途中で何かを台無しにしています。 FragmentActivity、FragementPagerAdapter、および断片化コードのコードは、問題ではないコードで迷惑メールにしたくないため、コードを提供しています。

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); 

    } 
}  

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; 
    } 
}  

断片はそれに少しより多くのコードを持っているので、私は問題の核心であるべきものだけでプッシュします...それ以上は必要とされている.IF、私はそれをつなぎ合わせます。

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); 
    } 

ここで私はCOUNのために使用している私のタイマーです結局のところTDOWN ....

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); 
} 
} 

答えて

4

、RetainInstanceは自身の対立を引き起こしていたし、ViewPager /アダプタ/ FragmentManagerは彼らのことをやって。これを削除すると、Pagerは以前にはなかったTextViewを含め、フラグメントを適切に再構築しました。また、OnCreateViewでBundleを受け取るようになりました。ここでは、RetainInstanceがTrueに設定されている前に常にnullになっていました。

RetainInstanceを削除し、OnSaveInstanceStateとOnCreateViewを使用して、破棄される前にフラグメントの現在のステータスを渡し、OnCreateViewで再作成してフラグメントを破棄する前の状態にリセットする必要がありました。

私がカウントダウンを行うために使っていたRunnableが生き残るか、それを再接続できると思っていましたが、方法を見つけることができませんでした。私は現在のカウントをミリ秒単位で保存し、断片に戻ってそれを中断したところから続ける必要がありました。それほど大きな取引ではありませんが、あなたが本当にそれらのすべてのものを再付着できるかどうかを知りたいのです。 Runnable DOESは設定変更後も継続しますが、UIの何も更新しないため、OnSaveInstanceStateの中にコールバックをキャンセルしてnullにします。

また、AsyncTaskが付いたアイテムや他の同様のアイテムにRetainInstanceを使用する必要があるアイテムも読んでいます。そうでない場合は、コード内で再構築してください。

+0

こんにちは..私は同様の問題に直面しています。インスタンスを保持するインスタンスを真に保ち、それを動作させる方法はありますか?そうでなければ、私は自分のロジック全体を書き直す必要があるからです。事前に感謝:) – jaffa

+0

方法を見つけることができませんでした –

+0

http://stackoverflow.com/questions/6976027/reusing-fragments-in-a-fragmentpageradapter/29287415#29287415 –

関連する問題