为什么第一次运行后我的UI无法更新? (Android)

时间:2019-02-08 11:27:04

标签: android user-interface retrofit

我的UI表现得很有趣,经过大量研究,我仍然不知道为什么。

我从Internet检索了一些数据并将其呈现给用户。问题是,在第一次加载时,一切正常(检索到的数据并正确显示)。之后,当onClickListeners执行时,UI将不会更新(检索数据并将其应用于View,但是View不会更新)。但是,如果我更改了片段(过渡),然后又回到了片段,则一切正常(执行onClickListener动作时,视图将更新)。

使用RetroFit库检索数据。

我已经尝试过的方法:更新其他通用视图(例如TextView),以丢弃问题是MyView(MyProgressBar)类,在代码中的其他位置(在RetroFit方法之外,在onResponse的最后)更新UI在RetroFit等内部),使用AsyncTask并将RetroFit内容放入其中,调用invalidate和postInvalidate。无回应:我总是得到与上述相同的结果。 我已经调试了代码:一切都按预期执行,包括更新UI的行。响应来自服务器,结果全部正确,并已应用于视图,但不会更新。

请帮助!

PS:该应用程序还有其他与此非常相似的片段。它们都可以正常工作,但这是“家”,因此在此之后的另一个负荷。看起来一个片段的onDestroy调用是使其他片段起作用的原因,这没有任何意义,但也许可以提供一个线索。

这是我的课程(简体):

public class HomeFragment extends Fragment {

Activitys dayActivity; // An object to retreive from Internet API

private MyProgressBar stepProgress, walkingProgress, cyclingProgress, exerciseProgress, otherProgress,
        standingProgress, restingProgress; // Custom made Views
private TextView dateTextView,lastSyncTextView;
private View v; // The view where the Fragment is hosted
private Calendar calendar; // Store the date I am working on

public HomeFragment() {
    this.calendar = Calendar.getInstance();
}

public static HomeFragment getInstance(Date date) {
    HomeFragment r = new HomeFragment();

    r.calendar = Calendar.getInstance();
    r.calendar.setTime(date);

    return r;
}

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

    return inflater.inflate(R.layout.daily_progress_activity, container, false);
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    // Set Date to today if needed
    if (this.calendar == null)
        calendar = Calendar.getInstance();
    android.text.format.DateFormat dateFormat = new android.text.format.DateFormat();
    shownDate = dateFormat.format(DATE_FORMAT, calendar).toString();

    setupUi();

    //Get Retrofit Instance(API)
    Retrofit retrofit = ApiHelper.getClient();
    userClient = retrofit.create(UserClient.class);
    //API Request and set Progressbars
    getActivityData();

}

/**
 * connect UI with controller
 */
private void setupUi() {

    v = getView();
    stepProgress = (MyProgressBar) v.findViewById(R.id.dai_pb_pbSteps);
    walkingProgress = (MyProgressBar) v.findViewById(R.id.dai_pb_pbWalking);
    cyclingProgress = (MyProgressBar) v.findViewById(R.id.dai_pb_pbCycling);
    exerciseProgress = (MyProgressBar) v.findViewById(R.id.dai_pb_pbExercise);
    otherProgress = (MyProgressBar) v.findViewById(R.id.dai_pb_pbOthers);
    standingProgress = (MyProgressBar) v.findViewById(R.id.dai_pb_pbStanding);
    restingProgress = (MyProgressBar) v.findViewById(R.id.dai_pb_pbResting);
    //SyncTime
    lastSyncTextView = (TextView)v.findViewById(R.id.dai_pb_tvLastSync);
    //Date
    dateTextView = (TextView) v.findViewById(R.id.dailyTextViewDate);
    writeDateOverCircle();

    checkRightAngleVisibility();

    // With the left angle we go to the previous date
    // TODO: Start reseting progressBars, so if there is no data loaded, it will show all gray
    ImageView letfAngle = v.findViewById(R.id.dailyAngleLeft);
    letfAngle.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Log.d(TAG,"Push left");
            // Calculate previous day
            HomeFragment.this.calendar.add(Calendar.DATE, -1);
            // Store it in showDate
            android.text.format.DateFormat dateFormat = new android.text.format.DateFormat();
            shownDate = dateFormat.format(DATE_FORMAT, calendar).toString();
            writeDateOverCircle();
            checkRightAngleVisibility();
            // Call getActivityData
            getActivityData();
        }
    });

    // With the right angle we go to the next date (if possible)
    // TODO: Start reseting progressBars, so if there is no data loaded, it will show all gray
    ImageView rightAngle = v.findViewById(R.id.dailyAngleRight);
    rightAngle.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Calendar calendar = HomeFragment.this.calendar; // Make the calendar easy to access
            calendar.add(Calendar.DATE, 1); // Go to next date
            // Store it in showDate
            android.text.format.DateFormat dateFormat = new android.text.format.DateFormat();
            shownDate = dateFormat.format(DATE_FORMAT, calendar).toString();
            writeDateOverCircle();
            checkRightAngleVisibility();
            // Call getActivityData
            getActivityData();
        }
    });

    // Several views will have the same OnClickListener, so we create this and the apply it to
    // these views
    View.OnClickListener goToWeekView = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Fragment frag = HomeFragmentWeekly.getInstance(HomeFragment.this.calendar.getTime());
            FragmentManager manager = getActivity().getSupportFragmentManager();
            FragmentTransaction transaction = manager.beginTransaction();
            transaction.replace(R.id.main_home_fragment, frag);
            transaction.commit();
        }
    };
    v.findViewById(R.id.dayProgressCircleLeft).setOnClickListener(goToWeekView);
    v.findViewById(R.id.dayProgressCircleRight).setOnClickListener(goToWeekView);
    v.findViewById(R.id.dai_pb_tvWeekly).setOnClickListener(goToWeekView);
    v.findViewById(R.id.textViewDaily).setOnClickListener(goToWeekView);
    v.findViewById(R.id.dailyTextViewDate).setOnClickListener(goToWeekView);

    // When the user swipes the finger to the left, goes to the daily pie chart view
    v.setOnTouchListener(new OnSwipeTouchListener(getContext()) {
      public void onSwipeLeft() {
            Fragment frag = HomeFragmentPieChart.getInstance(HomeFragment.this.calendar.getTime());
            FragmentManager manager = getActivity().getSupportFragmentManager();
            FragmentTransaction transaction = manager.beginTransaction();
            transaction.replace(R.id.main_home_fragment, frag);
            transaction.commit();
        }
      });
}

/**
 * Paints the date over the top circle, checking that everything fits
 */
private void writeDateOverCircle() {
    // Try with the month's full name and see what happens
    String month = calendar.getDisplayName(Calendar.MONTH, Calendar.LONG, Locale.getDefault());
    int day = calendar.get(Calendar.DAY_OF_MONTH);
    dateTextView.setText(day + " " + month);

    // If the dateTextView is too wide, then redo with a shorter month name
    // To get the measures with safety, you need to use getMeasuredWidth. For it to work, you have to do a .meassure first
    dateTextView.measure(0,0);
    int dateWidth = dateTextView.getMeasuredWidth();
    View circle = v.findViewById(R.id.dayProgressCircleLeft);
    circle.measure(0,0);
    int circleWidth = circle.getMeasuredWidth();
    if (dateWidth > circleWidth-16) {
        month = calendar.getDisplayName(Calendar.MONTH, Calendar.SHORT, Locale.getDefault());
        month = month + ".";
    }
    dateTextView.setText(day + " " + month);
}

/**
 * Makes the right angle invisible is we are already in today's date, because we shouldn't be able
 * to navigate to the future
 */
private void checkRightAngleVisibility() {
    ImageView rightAngle = v.findViewById(R.id.dailyAngleRight);
    Calendar today = Calendar.getInstance();
    // Reset the time of the day in today
    today.set(Calendar.HOUR_OF_DAY, 0);
    today.set(Calendar.MINUTE, 0);
    today.set(Calendar.SECOND, 0);

    if (today.after(this.calendar))
        rightAngle.setVisibility(View.VISIBLE);
    else
        rightAngle.setVisibility(View.INVISIBLE);

}

/**
 * API request and set the Progressbar and TextView
 */
private void getActivityData() {
    Call<ResponseProgress> call = userClient.getProgress(projKey, patKey, shownDate, dayCount);

    call.enqueue(new Callback<ResponseProgress>() {
        @Override
        public void onResponse(Call<ResponseProgress> call, Response<ResponseProgress> response) {
            Log.d(TAG,"Get Data");
            if (response.isSuccessful()) {
                Log.d(TAG, response.body().toString());
                //Get Activity Values
                dayActivity = response.body().getValue().getData()[0].getValues();
                //Steps
                HomeFragment.this.dayStepsCount = dayActivity.getActivityStepsCount();
                //Walking
                HomeFragment.this.dayWalkingTime = dayActivity.getActivityWalkingTime();
                //Cycling
                HomeFragment.this.dayCyclingTime = dayActivity.getActivityCyclingTime();
                //Exercise
                HomeFragment.this.dayExerciseTime = dayActivity.getActivityExerciseTime();
                //Other
                HomeFragment.this.dayOtherTime = dayActivity.getActivityOtherTime();
                //Standing
                HomeFragment.this.dayStandingTime = dayActivity.getActivityStandingTime();
                //Resting
                HomeFragment.this.dayRestingTime = dayActivity.getActivityrestingtime();

                syncTime(); // I tried commenting this line. Same results.
                putDataToUI();  // This is the call that is causing no effect
            } else {
                ErrorHelper error = new ErrorHelper();
                ErrorMessage errorMessage = error.help(response.errorBody());
                Toast.makeText(v.getContext(), errorMessage.getStatus_msg(), Toast.LENGTH_LONG).show();
            }
        }

        @Override
        public void onFailure(Call<ResponseProgress> call, Throwable t) {

        }
    });

}
/**
 * Get last SyncTime from Sensor. To see the data are up to date or not.
 */
private void syncTime() {
    Call<ResponseSensors> call = userClient.getSensors(HelperShared.loadString(getContext(),
            Constants.PREF_TOKEN), HelperShared.loadString(getContext(), Constants.PREF_ORGID),
            HelperShared.loadString(getContext(), Constants.PREF_PROJ_ID));
    call.enqueue(new Callback<ResponseSensors>() {
        @Override
        public void onResponse(Call<ResponseSensors> call, Response<ResponseSensors> response) {

            if (response.isSuccessful()) {
                Log.d(TAG, "Sensor: " + response.body().getValue().
                        getSensorWithShortName(sensorShortName).getLast_synced_timestamp());
                String lastSync = response.body().getValue().
                        getSensorWithShortName(sensorShortName).getLast_synced_timestamp();
                lastSyncTextView.setText(lastSync);
            } else {
                ErrorHelper error = new ErrorHelper();
                ErrorMessage errorMessage = error.help(response.errorBody());
                Toast.makeText(getContext(), errorMessage.getStatus_msg(), Toast.LENGTH_LONG).show();
            }
        }

        @Override
        public void onFailure(Call<ResponseSensors> call, Throwable t) {
            Log.d(TAG, "FEhler: " + t.getMessage());

        }
    });
}

private void putDataToUI() {
    Log.d(TAG,"Set Progress");
    //Steps
    setProgressBar(stepProgress, stepGoal, stepProg, this.dayStepsCount);
    //Walking
    setProgressBar(walkingProgress, walkingGoal, walkingProg, this.dayWalkingTime);
    //Cycling
    setProgressBar(cyclingProgress, cyclingGoal, cyclingProg, this.dayCyclingTime);
    //Exercise
    setProgressBar(exerciseProgress, exerciseGoal, exerciseProg, this.dayExerciseTime);
    //Other
    setProgressBar(otherProgress, otherGoal, otherProg, this.dayOtherTime);
    //Standing
    setProgressBar(standingProgress, standingGoal, standingProg, this.dayStandingTime);
    //Resting
    setProgressBar(restingProgress, restingGoal, restingProg, this.dayRestingTime);

    // Here I tried v.invalidate() and v.postInvalidate(). No results.
    // Also tried to invalidate and postInvalidate each MyProgressBar. No results.
}


/**
 * @param progBar       Progressbar to set the values
 * @param goal          daily goal the user has to reach
 * @param activityValue the value form the API for the spacific activity
 */
private void setProgressBar(MyProgressBar progBar, float goal, float progGoal, float activityValue) {
    float value = (100 / progGoal) * activityValue;
    float dailyGoal = (100 / progGoal) * goal;
    progBar.setSecondaryProgress((int) dailyGoal);
    if (value >= 100) {
        progBar.setProgress(100);
    } else {
        progBar.setProgress((int) value);
    }
    if (progBar != stepProgress) {
        int houers = (int) activityValue / 60;
        int minutes = (int) activityValue % 60;
        progBar.setTagText(houers + "h:" + minutes + "min");
    } else {
        progBar.setTagText((int) activityValue + "");
    }

}

}

0 个答案:

没有答案
相关问题