返回计时器片段时,计时器更新UI

时间:2017-07-26 15:39:46

标签: android timer fragment

我有两个片段。 在他们之间的交易我正在取代他们。 在第二个片段,我有一个Timer更新TextView。 这是我需要的流程。

  • 1)转到第二个片段。
  • 2)启动计时器。
  • 3)返回第一个片段(在计时器运行时)
  • 4)回到第二个片段并继续更新TextView。

我的问题是,当我回到第二个Fragment并且Timer正在运行时,TextView不再更新。

这是我的代码:

MainActivity:

public class MainActivity extends AppCompatActivity{

private FragmentManager fragmentManager;
private FragmentTransaction fragmentTransaction;


@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    setFragmentTransaction(null);

}



/**
 * A fragment transaction Method
 *
 * @param fragment the fragment we want to display
 */
public void setFragmentTransaction(Fragment fragment) {

    fragmentManager = getFragmentManager();
    fragmentTransaction = fragmentManager.beginTransaction();

    //replacing fragments new Fragments
    if (fragment != null ) {
        fragmentTransaction.replace(R.id.container, fragment);
    } else if(fragment == null && (fragmentManager.getBackStackEntryCount() == 0)) { // starting with main Fragment
        fragmentTransaction.add(R.id.container, new MainFragment());
    }

        fragmentTransaction.addToBackStack(null);
    fragmentTransaction.commitAllowingStateLoss();
    fragmentManager.executePendingTransactions();


}

}

主要片段:

public class MainFragment extends Fragment {

    private Context context;
    private View view;
    private Button button;


    @Override
    public void onAttach(Context context) {
        super.onAttach(context);

        this.context = context;
    }


    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {

        view = inflater.inflate(R.layout.fragment_main, container, false);

      button = (Button) view.findViewById(R.id.mainBTN);

      button.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v) {
              ((MainActivity)context).setFragmentTransaction(new TimerFragmnet());
          }
      });


        return view;

    }
}

计时器片段:

public class TimerFragmnet extends Fragment {


    private Context context;
    private TextView timerTextView;
    private Button startBTN, backBTN;
    private View view;
    private Timer timer;
    private int timerSec;


    @Override
    public void onAttach(Context context) {
        super.onAttach(context);

        this.context = context;

    }


    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {

        view = inflater.inflate(R.layout.fragment_timer, container, false);
        timerTextView = (TextView) view.findViewById(R.id.timerTextView);
        startBTN = (Button) view.findViewById(R.id.startBTN);
        backBTN = (Button) view.findViewById(R.id.backBTN);


        startBTN.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startTimer(180);
            }
        });


        backBTN.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ((MainActivity) context).setFragmentTransaction(new MainFragment());
            }
        });


        return view;
    }


    private final Handler mHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            Log.i("Timer", msg.toString());


            timerTextView.setText(createDateFormat((int) msg.obj));

        }
    };

    private void startTimer(final int seconds) {

        timerSec = seconds;
        timer = new Timer();

        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {


                Message message = Message.obtain();
                message.obj = timerSec;
                message.setTarget(mHandler);
                mHandler.sendMessage(message);
                timerSec--;


            }
        }, 100, 1000);


    }


    /**
     * Setting the timer format
     *
     * @param seconds
     * @return
     */
    public String createDateFormat(int seconds) {
        return String.format("%02d:%02d", (seconds % 3600) / 60, (seconds % 60));

    }


}

2 个答案:

答案 0 :(得分:3)

我最终做到了: 我创建了一个新的Class,它使得所有的Timer处理和我的Fragment实现了他的回调: 对于任何情况,我都会在这里使用代码:

enter image description here

<强> MainActivity:

public class MainActivity extends AppCompatActivity {
    private FragmentManager fragmentManager;
    private FragmentTransaction fragmentTransaction;


    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        setFragmentTransaction(null);

    }



    /**
     * A fragment transaction Method
     *
     * @param fragment the fragment we want to display
     */
    public void setFragmentTransaction(Fragment fragment) {

        fragmentManager = getFragmentManager();
        fragmentTransaction = fragmentManager.beginTransaction();

        //replacing fragments new Fragments
        if (fragment != null ) {
            fragmentTransaction.replace(R.id.container, fragment);
        } else if(fragment == null && (fragmentManager.getBackStackEntryCount() == 0)) { // starting with main Fragment
            fragmentTransaction.add(R.id.container, new MainFragment());
        }

        fragmentTransaction.addToBackStack(null);
        fragmentTransaction.commitAllowingStateLoss();
        fragmentManager.executePendingTransactions();


    }
}

<强> MainFragment:

public class MainFragment extends Fragment {

    private Context context;
    private View view;
    private Button button;


    @Override
    public void onAttach(Context context) {
        super.onAttach(context);

        this.context = context;
    }


    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {

        view = inflater.inflate(R.layout.fragment_main, container, false);

        button = (Button) view.findViewById(R.id.mainBTN);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ((MainActivity)context).setFragmentTransaction(new TimerFragment());
            }
        });


        return view;

    }
}

<强> TimerFragment:

public class TimerFragment extends Fragment implements MyTimer.TimerRuning {


    private Context context;
    private TextView timerUpTextView, timerDownTextView;
    private Button startBTN, backBTN, stopTimerBTN;
    private View view;



    @Override
    public void onAttach(Context context) {
        super.onAttach(context);

        this.context = context;

    }


    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {


        MyTimer.getInstance().setTimerRuningListener(this);

        view = inflater.inflate(R.layout.fragment_timer, container, false);
        timerUpTextView = (TextView) view.findViewById(R.id.timerUpTextView);
        timerDownTextView = (TextView) view.findViewById(R.id.timerDownTextView);
        startBTN = (Button) view.findViewById(R.id.startBTN);
        backBTN = (Button) view.findViewById(R.id.backBTN);
        stopTimerBTN = (Button) view.findViewById(R.id.stopTimerBTN);


        startBTN.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                MyTimer.getInstance().startTimer(180);
            }
        });


        stopTimerBTN.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                MyTimer.getInstance().stopTimer();
            }
        });


        backBTN.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ((MainActivity) context).setFragmentTransaction(new MainFragment());
            }
        });



        return view;
    }


    @Override
    public void onTimerChange(String remainSec, String startSec) {
        timerUpTextView.setText(startSec);
        timerDownTextView.setText(remainSec);
    }

    @Override
    public void onTimerStopped(String remainSec, String startSec) {
        timerUpTextView.setText(startSec);
        timerDownTextView.setText(remainSec);
    }
}

MyTimer - Class

public class MyTimer {    

    private Timer timer;
    private MyTimer.TimerRuning timerRuningListener;
    private int remainingSec, startSec;
    public boolean isRunning;


    private static final String TAG = "MyTimer";


    private static final MyTimer ourInstance = new MyTimer();

    public static MyTimer getInstance() {
        return ourInstance;
    }

    private final Handler mHandler = new Handler() {

        @Override
        public void handleMessage(Message msg) {

            int[] timeArr = (int[]) msg.obj;

            if (timeArr[0] == 0) {
                MyTimer.this.stopTimer();
                if(timerRuningListener != null) {
                    timerRuningListener.onTimerStopped(createDateFormat(0), createDateFormat(0));
                }
            } else {
                if(timerRuningListener != null) {
                    timerRuningListener.onTimerChange(createDateFormat(timeArr[0]), createDateFormat(timeArr[1]));
                }
            }


        }
    };


    public void startTimer(final int seconds) {


        startSec = 0;   

        remainingSec = seconds;
        timer = new Timer();

        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                Log.i(TAG, "Timer running......");
                isRunning = true;
                Message message = Message.obtain();
                int[] counters = new int[2];
                counters[0] = remainingSec;
                counters[1] = startSec;
                message.obj = counters;
                message.setTarget(mHandler);
                mHandler.sendMessage(message);
                remainingSec--;
                startSec++;


            }
        }, 100, 1000);


    }


    /**
     * Setting the timer format
     *
     * @param seconds
     * @return
     */
    public String createDateFormat(int seconds) {

        return String.format("%02d:%02d", (seconds % 3600) / 60, (seconds % 60));

    }

    public void setTimerRuningListener(MyTimer.TimerRuning timerRuningListener) {
        this.timerRuningListener = timerRuningListener;
    }


    public interface TimerRuning {
        void onTimerChange(String remainSec, String startSec);

        void onTimerStopped(String remainSec, String startSec);
    }

    public void stopTimer() {
        if (timer != null) {
            timerRuningListener.onTimerStopped(createDateFormat(0), createDateFormat(0));
            isRunning = false;
            timer.cancel();
        }
    }    

}

答案 1 :(得分:0)

当我回到第二片段并且计时器正在运行时,你的意思是什么?当你回到你的第一个片段时,第二个片段会被破坏,计时器也会被破坏。当你“回到”第二个片段时,你正在创建一个新实例,它将有一个未运行的新计时器。

我建议您使用Service。您可以在那里启动计时器并每秒发送一次广播来更新您的UI。当您的第二个片段开始时,您注册一个BroadcastReceiver将获得这些更新。当该片段停止时,您可以取消注册BroadcastReceiver