0

I have a simple sun rise/sun set app that gives the user the times given a selected location.

When I run the code in the updateTime() method the time outputted to the Log (SUNRISE Unformatted\SUNRISE Formatted) is correct, but the TextView display does not update until the date has been changed to something else (and is correct when the date is changed back).

Is there anything that would cause the log to display the correct output but the TextView immediately after does not?

Full Fragment Code:

import android.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.DatePicker;
import android.widget.TextView;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import swindroid.suntime.R;
import swindroid.suntime.calc.AstronomicalCalendar;
import swindroid.suntime.calc.GeoLocation;

public class singleRiseSet extends Fragment {

int year, month, day;
private static GeoLocation currentLocation;

DatePicker dp;
static TextView sunriseTV, sunsetTV;

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

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

    dp = (DatePicker) view.findViewById(R.id.datePicker);
    sunriseTV = (TextView) view.findViewById(R.id.sunriseTimeTV);
    sunsetTV = (TextView) view.findViewById(R.id.sunsetTimeTV);

    initialiseUI();

    return view;
}

public void initialiseUI() {
    Log.d("SINGLERISESET", "INIT");
    Calendar cal = Calendar.getInstance();
    year = cal.get(Calendar.YEAR);
    month = cal.get(Calendar.MONTH);
    day = cal.get(Calendar.DAY_OF_MONTH);
    dp.init(year,month,day,dateChangeHandler); // setup initial values and reg. handler
}


public void updateTime(int newYear, int monthOfYear, int dayOfMonth, GeoLocation currentLocation) {
    AstronomicalCalendar ac = new AstronomicalCalendar(currentLocation);
    Log.d("SUNRISE Current", currentLocation.getLocationName());
    if (!(newYear == 0 && monthOfYear == 0 && dayOfMonth == 0)) {
        this.year = newYear;
        this.month = monthOfYear;
        this.day = dayOfMonth;
    }
    ac.getCalendar().set(year, month, day);
    Date srise = ac.getSunrise();
    Date sset = ac.getSunset();

    SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");

    Log.d("SUNRISE Unformatted", srise+"");
    Log.d("SUNRISE formatted", sdf.format(srise));

    sunriseTV.setText(sdf.format(srise));
    sunsetTV.setText(sdf.format(sset));
}

DatePicker.OnDateChangedListener dateChangeHandler = new DatePicker.OnDateChangedListener()
{
    public void onDateChanged(DatePicker dp, int year, int monthOfYear, int dayOfMonth)
    {
        updateTime(year, monthOfYear, dayOfMonth, currentLocation);
    }
};
}

layout file:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TableLayout android:id="@+id/TableLayout01"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:stretchColumns="0,1"
        android:gravity="center"
        android:padding="5sp">
        <TableRow android:id="@+id/TableRow01"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <TextView android:padding="2sp"
                android:gravity="center"
                android:textColor="#ffd700"
                android:textSize="20sp"
                android:text="Sun Rise"
                android:layout_height="wrap_content"
                android:layout_width="wrap_content">
            </TextView>
            <TextView android:padding="2sp"
                android:gravity="center"
                android:textColor="#ff8400"
                android:textSize="20sp"
                android:text="Sun Set"
                android:layout_height="wrap_content"
                android:layout_width="wrap_content">
            </TextView>
        </TableRow>

        <TableRow android:id="@+id/TableRow02"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
            <TextView android:padding="2sp"
                android:textSize="38sp"
                android:textColor="#ffd700"
                android:gravity="center"
                android:layout_height="wrap_content"
                android:id="@+id/sunriseTimeTV"
                android:layout_width="wrap_content">
            </TextView>
            <TextView android:padding="2sp"
                android:textSize="38sp"
                android:textColor="#ff8400"
                android:gravity="center"
                android:layout_height="wrap_content"
                android:id="@+id/sunsetTimeTV"
                android:layout_width="wrap_content">
            </TextView>
        </TableRow>

    </TableLayout>

    <ImageView android:id="@+id/ImageView01"
        android:layout_width="match_parent"
        android:src="@drawable/sunpic"
        android:padding="8dp"
        android:layout_height="60sp">
    </ImageView>
    <DatePicker android:id="@+id/datePicker"
        android:layout_width="fill_parent"
        android:padding="5sp"
        android:gravity="center"
        android:layout_height="wrap_content"
        android:calendarViewShown="false">
    </DatePicker>

</LinearLayout>
musica
  • 1,373
  • 3
  • 15
  • 34
Twulz
  • 43
  • 11
  • maybe you need to refresh your fragment. Check out this http://stackoverflow.com/questions/20702333/refresh-fragment-at-reload – grantespo Oct 24 '16 at 05:40

2 Answers2

0

You should initialise your UI (set your text) in onActivityCreated method. You are trying to set the text without returning your view in onCreateView. You just simply call your initialiseUI() method in onActivityCreated method. That should work. That is also the reason that your UI updates when you change the date afterwards because till that time, the onCreateView method has returned the view.

Karan
  • 356
  • 2
  • 6
  • By "set your text" do you mean initialising the textview i.e. this: "sunriseTV = (TextView) view.findViewById(R.id.sunriseTimeTV);" ? I can't access the view from the arguments of onActivityCreated. Otherwise I have put just initialiseUI() into an onActivityCreated method and now it crashes on changing the date (NullPointerException). The text is "set" (sunriseTV.setText(sdf.format(srise));) after the view is returned, as updateTime() is called after the return from onCreateView, unless I misunderstand your meaning. – Twulz Oct 24 '16 at 06:01
  • Apologies, the NullPointerException was caused by something else I was trying, though with that removed I still get the problem described in the initial question. – Twulz Oct 24 '16 at 06:17
0

You need to consider Android's view Lifecycle (By Arpit Mathur)

You are likely changing your TextView sometime after a draw and before a subsequent new draw. Try using requestLayout() or invalidate() after you change the time. Should update the time on screen nearly immediately.

sunriseTV.setText(sdf.format(srise));
sunsetTV.setText(sdf.format(sset));
sunriseTV.requestLayout();
sunsetTV.requestLayout();

Also see: Force Layout Requests

Community
  • 1
  • 1
  • Thanks for the reply, however neither requestLayout() nor invalidate() fix this problem, including combining it with the other below answer using onActivityCreated() method. – Twulz Oct 24 '16 at 06:19
  • could be wrong - just stabbing in the dark, but your DatePicker listener might be running outside the UI thread. If so, I don't think updates to your TextViews will update properly. You might try running your updateTime method in a UI Thread. Try wrapping the contents of your updateTime method in the UI Thread described [here](http://stackoverflow.com/questions/5400288/update-textview-from-thread-please-help) – Sam Boychuk Oct 24 '16 at 06:36
  • Thanks, but wouldn't that cause the opposite problem? i.e. the initial value would be set correctly but subsequent changes (i.e. changes made by the datePicker) would be incorrect? All changes made by selection of the datePicker are updated correctly. – Twulz Oct 24 '16 at 06:58
  • shouldn't. It means that when you first call update time (and your log output is correct) the time will be updated in a UI Thread meaning the view will be updated immediately. Every time the Datepicker listener calls updateTime it is calling a UI Thread, so all subsequent changes will update immediately. (Theoretically) – Sam Boychuk Oct 24 '16 at 07:07
  • hmmm ok, so what should I be changing to alleviate this? I still don't entirely understand – Twulz Oct 24 '16 at 07:20
  • try replacing: sunriseTV.setText(sdf.format(srise)); sunsetTV.setText(sdf.format(sset)); with: getActivity().runOnUiThread(new Runnable() { public void run() { sunriseTV.setText(sdf.format(srise)); sunsetTV.setText(sdf.format(sset)); } }); (you might have to make some variables final or class parameters) – Sam Boychuk Oct 24 '16 at 15:35
  • check out - http://stackoverflow.com/questions/12850143/android-basics-running-code-in-the-ui-thread – Sam Boychuk Oct 24 '16 at 15:41