1

I'm making a weather application for Android and I'm trying to use a non-final variable from my Thread in runOnUiThread. However, I'm not allowed to do this.

What am I doing wrong?

Beneath is code from the whole activity. The thread is parsing xml from yr.no.

public class WeatherActivity extends Activity implements OnClickListener {

ImageView forecastImage;
TextView updateWeatherText;
TextView temperatureText;
TextView cloudinessText;
TextView windspeedText;
TextView precipitationText;

Thread updateWeather = new Thread(new GetWeather());
Thread updateWeatherFromButton = new Thread(new GetWeather());

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

    forecastImage = (ImageView) findViewById(R.id.forecastIcon);

    updateWeatherText = (TextView) findViewById(R.id.updatingWeatherText);

    temperatureText = (TextView) findViewById(R.id.temperatureText);
    cloudinessText = (TextView) findViewById(R.id.cloudinessText);
    windspeedText = (TextView) findViewById(R.id.windspeedText);
    precipitationText = (TextView) findViewById(R.id.precipitationText);

    updateWeather.start();

    Button refreshButton = (Button) findViewById(R.id.refreshButton);
    refreshButton.setOnClickListener(this);
}

class GetWeather implements Runnable {

    public void run() {

        try {

            String temp;
            String windspeed;
            String cloudiness;
            String precipitation;


            URL weatherURL = new URL(
                    "http://api.yr.no/weatherapi/locationforecast/1.8/?lat=62.39;lon=17.30");

            XmlPullParserFactory parserFactory = XmlPullParserFactory
                    .newInstance();
            XmlPullParser parser = parserFactory.newPullParser();

            parser.setInput(weatherURL.openStream(), null);

            updateWeatherText.setText("Updating...");
            int parserEvent = parser.getEventType();
            while (parserEvent != XmlPullParser.END_DOCUMENT) {

                switch (parserEvent) {

                case XmlPullParser.TEXT:
                    String tag = parser.getName();

                    if (tag.compareTo("temperature") == 0) {
                        temp = parser.getAttributeValue(
                                null, "value") + " 'C";
                    } else if (tag.compareTo("windSpeed") == 0) {
                        windspeed = parser.getAttributeValue(
                                null, "mps") + " m/s";

                    } else if (tag.compareTo("cloudiness") == 0) {
                        if (Integer.parseInt(parser.getAttributeValue(null,
                                "percent")) >= 0
                                && Integer
                                        .parseInt(parser.getAttributeValue(
                                                null, "percent")) <= 12.5) {
                            cloudiness = "Klart";
                        } else if (Integer.parseInt(parser
                                .getAttributeValue(null, "percent")) > 12.5
                                && Integer
                                        .parseInt(parser.getAttributeValue(
                                                null, "percent")) < 25) {
                            cloudiness = "Mestadels klart";
                        } else if (Integer.parseInt(parser
                                .getAttributeValue(null, "percent")) >= 25
                                && Integer
                                        .parseInt(parser.getAttributeValue(
                                                null, "percent")) < 75) {
                            cloudiness = "Växlande molnighet";
                        } else if (Integer.parseInt(parser
                                .getAttributeValue(null, "percent")) >= 75
                                && Integer
                                        .parseInt(parser.getAttributeValue(
                                                null, "percent")) < 87.5) {
                            cloudiness = "Mestadels mulet";
                        } else if (Integer.parseInt(parser
                                .getAttributeValue(null, "percent")) >= 87.5
                                && Integer
                                        .parseInt(parser.getAttributeValue(
                                                null, "percent")) <= 100) {
                            cloudiness = "Mulet";
                        }

                    } else if (tag.compareTo("precipitation") == 0) {
                        if (Integer.parseInt(parser.getAttributeValue(null, "minvalue")) > 0) forecastImage.setBackgroundResource(R.drawable.rain);
                        precipitation = "Mellan "
                                        + parser.getAttributeValue(null,
                                                "minvalue")
                                        + " mm och "
                                        + parser.getAttributeValue(null,
                                                "maxvalue") + " mm";
                    }
                    break;
                }
                parserEvent = parser.next();

                runOnUiThread(new Runnable() {

                    public void run() {
                        temperatureText.setText(temp);
                        windspeedText.setText(windspeed);
                        cloudinessText.setText(cloudiness);
                        precipitationText.setText(precipitation);

                        if (cloudiness.compareTo("Klart") == 0){
                            forecastImage.setBackgroundResource(R.drawable.sunny);
                        } else if ( cloudiness.compareTo("Mestadels klart" ) == 0) {
                            forecastImage.setBackgroundResource(R.drawable.sunny);
                        }
                          else if ( cloudiness.compareTo("Växlande molnighet") == 0) {
                              forecastImage.setBackgroundResource(R.drawable.cloudy);
                        } else if ( cloudiness.compareTo("Mestadels mulet") == 0) {
                            forecastImage.setBackgroundResource(R.drawable.overcast);
                        } else if ( cloudiness.compareTo("Mulet") == 0) {
                            forecastImage.setBackgroundResource(R.drawable.overcast);
                        }                           
                    }
                });
            }
            updateWeatherText.setText("Last updated: "
                    + System.currentTimeMillis());

        } catch (Exception e) {
        }
    }
}

public void onClick(View v) {

    switch (v.getId()) {

    case R.id.refreshButton:
        updateWeatherFromButton.start();

    }
}

2 Answers2

1

As some have already pointed out you can't. One workaround is to reassign the non final variable to a final variable before defining the Runnable:

String aNonFinalString = "a";
aNonFinalString = "b";

final String aFinalString = aNonFinalString;

runOnUiThread(new Runnable() {
    public void run() {
        useYourString(aFinalString);
     }
}
assylias
  • 321,522
  • 82
  • 660
  • 783
  • 1
    This is wrong. The value of aNonFinalString may change by the time your run method is executed. There is a reason why it should be 'final'. – Anirudh Apr 16 '12 at 20:10
  • @Anirudh Not sure I understand what you mean. I don't use aNonFinalString in the runnable, which the whole point. – assylias Apr 16 '12 at 20:18
  • I was trying to say that the developer @user1258829 may not be expecting a possibly 'stale' value i.e. final String aFinalString = aNonFinalString; when the runnable actually runs. aNonFinalString may be changed based on some logic. But the runnable will only provide a snapshop of the value with the final variable. – Anirudh Apr 16 '12 at 20:21
  • @Anirudh Ok understood what you mean. In which case he can use accessors. – assylias Apr 16 '12 at 20:23
0

You can't..it is Java you can't use outer variables inside anonymous inner class unless it is declared final. Refer to this question to get more details

Community
  • 1
  • 1
Mahdi Hijazi
  • 4,424
  • 3
  • 24
  • 29