Задача таймера отображается во фрагменте, но не начинает обратный отсчет - PullRequest
0 голосов
/ 12 июля 2019

Я супер новичок в программировании.Прошу прощения за любую фальшивку и / или ужасный код.Кроме того, вероятно, часть проблемы.

У меня есть фрагмент, который связан с viewpager.Viewpager отображает новые экземпляры фрагмента, когда пользователь нажимает кнопку / проведет пальцем.Во фрагменте есть таймер.Отображается таймер и, когда вы переходите к следующему представлению, изменяется время.Это, однако, не «обратный отсчет» в режиме реального времени.Он просто отображает время на момент создания фрагмента.Когда вы нажимаете на следующий фрагмент, время изменилось.Как правило, это время меньше, чем предыдущий фрагмент.Иногда это больше.

Я изначально построил таймер в своей основной деятельности.Там он отлично работал, но не отображался во фрагменте.Я переместил таймер на фрагмент.Вот когда это перестало работать.Я переместил таймерную задачу из onCreateView в onResume, а затем в OnStart.Я очистил свой код как можно лучше, учитывая мой текущий уровень знаний.Я искал stackoverflow в течение последних двух дней, пытаясь выяснить это.

Это фрагмент, в котором находится таймер.


public class TaskFragment extends Fragment {

  public static int done = 0;
  private static TextView clockDisplay;
  Button button1;
  private Timer activityTimer;
  private Timer clockTimer;
  private String activityTimeElapsedKey;
  private String clockFormat;
  private long activityTimerStart;
  private long activityTimeElapsed;

  private Context context;

  private int timeLimit;

  public static TaskFragment newInstance(String text) {

    TaskFragment frag1 = new TaskFragment();
    Bundle bundle = new Bundle();
    bundle.putString("msg", text);

    frag1.setArguments(bundle);

    return frag1;
  }

  @Override
  public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    context = getContext();
  }

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
      Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_task, container, false);

    TextView tv = view.findViewById(R.id.frag_1);
    tv.setText(getArguments().getString("msg"));

    clockDisplay = view.findViewById(R.id.clock_display);
    activityTimeElapsedKey = getString(R.string.activity_time_elapsed_key);
    clockFormat = getString(R.string.clock_format);

    button1 = view.findViewById(R.id.button_1);
    button1.setOnClickListener(view1 -> {
      pager.setCurrentItem(getNextPossibleItemIndex(1), true);
      done += 1;
    });

    return view;
  }

  private int getNextPossibleItemIndex(int change) {

    int currentIndex = pager.getCurrentItem();
    int total = MainActivity.NUM_PAGES;

    if (currentIndex + change < 0) {
      return 0;
    }
    return Math.abs((currentIndex + change) % total);
  }

  @Override
  public void onStart() {
    super.onStart();
    startActivityTimer();
  }

  public void updateClock() {
    timeLimit = PreferenceManager.getDefaultSharedPreferences(context).getInt("timer", 15);
    long remaining = (timeLimit * 60000) - (System.currentTimeMillis() - activityTimerStart);
    int minutes = (int) TimeUnit.MILLISECONDS.toMinutes(remaining);
    double seconds = TimeUnit.MILLISECONDS.toSeconds(remaining % 60000);
    clockDisplay.setText(String.format(clockFormat, minutes, seconds));
  }

  //TODO create a timeout task and tie to activity timer
  private void startActivityTimer() {
    activityTimer = new Timer();
    activityTimerStart = System.currentTimeMillis();
    activityTimeElapsed = 0;
    clockTimer = new Timer();
    clockTimer.schedule(new ClockTimerTask(), 0, 100);
    updateClock();
  }

  private class ClockTimerTask extends TimerTask {

    @Override
    public void run() {
      if (isVisible()) {
        getActivity().runOnUiThread(() -> updateClock());
      }
    }
  }

}

Это макет для фрагмента.


<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  android:layout_width="match_parent"
  android:layout_height="match_parent">


  <Button
    android:id="@+id/button_1"
    style="@style/Widget.AppCompat.Button.Borderless"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:clickable="true"
    android:focusable="true"
    android:gravity="center"
    android:text="Done!"
    android:textColor="@color/colorPurple"
    android:textSize="24dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toBottomOf="@id/frag_1"/>

  <TextView
    android:id="@+id/clock_display"
    style="@style/ClockDisplay"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:visibility="visible"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintTop_toTopOf="parent"/>

  <TextView
    android:id="@+id/frag_1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:layout_centerInParent="true"
    android:layout_centerVertical="true"
    android:padding="16dp"
    android:gravity="center"
    android:lineSpacingMultiplier="1.2"
    android:text="TextView"
    android:textColor="@color/colorDarkBlue"
    android:textSize="60dp"
    android:visibility="visible"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toBottomOf="@id/clock_display"/>

</androidx.constraintlayout.widget.ConstraintLayout>

Это адаптер страницы и способ переключения между экземплярами фрагмента.


private class MyPagerAdapter extends FragmentStatePagerAdapter {

    public MyPagerAdapter(FragmentManager fm) {
      super(fm);
    }


    //TODO Add Result fragment as case 5.
    @Override
    public Fragment getItem(int pos) {
      switch (pos) {
        case 0:
          return TaskFragment.newInstance("Get dressed.");
        case 1:
          return TaskFragment.newInstance("Brush your teeth.");
        case 2:
          return TaskFragment.newInstance("Make your bed.");
        case 3:
          return TaskFragment.newInstance("Put your shoes on.");
        case 4:
          return TaskFragment.newInstance("Get your backpack ready.");
        default:
          return TaskFragment.newInstance("Good morning!");
      }
    }



Expected Result: I expect my timer to countdown when the first fragment is opened. The timer should continue the countdown from where it left off when the fragment is replaced with the next version.

Actual Result: First fragment displays 19:59 (based on a preference setting of 20). No countdown. Second fragment displays 19:56 (example) also doesn't count down. Third/fourth fragment either display a few seconds countdown in the same pattern as the second fragment or a second or two are added rather than subtracted. The final fragment starts flickering between seconds back and forth.
...