0

Have read all the set and get called from the UI thread, on stackoverflow but none seems relevent. this code worked 2years ago, recently opened it. and it shows this error. "Method setText must be called from the UI thread".
What updates are doing this? marked the setText lines with comments to make it more clear. Any sugestions?

public class MainActivity extends Activity {

    static final String baseURL = "http://api.yr.no/weatherapi/locationforecast/1.9/?lat=";
TextView dato, grader, vindhastighet, vindretning;



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.mainactivity);
        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder() .detectAll().penaltyLog().build();     StrictMode.setThreadPolicy(policy);


        SmartLocation.with(this).location()
                .oneFix()
                .start(new OnLocationUpdatedListener() {
                    @Override
                    public void onLocationUpdated(Location location) {

                        dato = (TextView)findViewById(R.id.gpsbydato_txt);
                        grader = (TextView)findViewById(R.id.gpsbygrader_txt);
                        vindhastighet = (TextView)findViewById(R.id.gpsbyvindhastighet_txt);
                        vindretning = (TextView)findViewById(R.id.gpsbyvindretning_txt);

                        Double latitude = location.getLatitude();
                        Double longtitude = location.getLongitude();

                        StringBuilder Url = new StringBuilder(baseURL);
                        Url.append(latitude + ";lon=" + longtitude);
                        final String fullUrl = Url.toString();


                        class Read extends AsyncTask<String, Integer, String> {
                            @Override
                            protected String doInBackground(String... arg0) {

                                try {
                                    URL website = new URL(fullUrl);
                                //xmlreader parser data
                                    SAXParserFactory spf = SAXParserFactory.newInstance();
                                    SAXParser sp = spf.newSAXParser();
                                    XMLReader xr = sp.getXMLReader();
                                    HandlingXMLStuff doingWork = new HandlingXMLStuff();
                                    xr.setContentHandler(doingWork);
                                    xr.parse(new InputSource(website.openStream()));

                                    String informationTemp = doingWork.getInformationTemp();
                                    String informationVindretning = doingWork.getInformationVindretning();
                                    String informationVindhastighet = doingWork.getInformationVindhastighet(); 
//grader.setText is causing the error.
                                    grader.setText(informationTemp);
//vindhastighet.setText is causing the error.  

                                    vindhastighet.setText(informationVindhastighet);
//vindretning.setText is causing the error.  

                                    vindretning.setText(informationVindretning);

                                } catch (Exception e) {
                                    Log.e("URL:", fullUrl);
                                    dato.setText("erroorrr"); //also this setText
                                    System.out.println(e);
                                }


                                return null;
                            }

                            @Override
                            protected void onPostExecute(String result) {
                                dato.setText(result);
                                super.onPostExecute(result);
                            }
                        }

                        }

    });
}
}
moody
  • 67
  • 1
  • 8

3 Answers3

4
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder() .detectAll().penaltyLog().build();     StrictMode.setThreadPolicy(policy);

That was actually turning off strict mode, which allowed unsafe things like updating the UI on non-UI threads and instead of crashing log it to disk. This isn't actually allowed anymore. So your code was always wrong, you were just ignoring the wrongness and hoping you wouldn't get caught. The correct fix is to move your code to the UI thread, and probably delete all mentions of StrictMode throughout your codebase- it should only be used as a debugging tool, and probably not even then.

And all the advice on not updating the UI from threads is absolutely relevant- you're setting the UI on an AsyncTask in doInBackground- so from another thread. Move that to the UI thread by either runOnUiThread, a handler, or by putting it off until onPostExecute or a progress message.

Gabe Sechan
  • 90,003
  • 9
  • 87
  • 127
  • "This isn't actually allowed anymore" -- out of curiosity, do you have any details on that? I never tried turning off thread-policy stuff, but disabling `FileUriExposedException` worked the last time I tried it. – CommonsWare May 11 '17 at 19:54
  • I'll see what I can turn up if I find some time this evening. I remember that at least some of them are disabled now. – Gabe Sechan May 11 '17 at 19:55
  • 1
    Or it might be related to https://issuetracker.google.com/issues/36951662 But either way the OP should avoid setting strict mode policies to write code like this – Gabe Sechan May 11 '17 at 19:56
  • Oh, definitely. I yell at people about that when presented with the opportunity. :-) Thanks! – CommonsWare May 11 '17 at 19:57
2

You can not update UI from doInBackground in AsyncTask.

All UI related operations need to be done inside UI thread.

You can use runonUithread to update text in your textview inside doInBackground

Here is an example

Code:

  @Override
protected String doInBackground(String... arg0) {

    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            grader.setText(informationTemp);
            vindhastighet.setText(informationVindhastighet);
            vindretning.setText(informationVindretning);

        }
    });

}

Or..better solution is to move your setText() code inside onPostExecute()

Community
  • 1
  • 1
rafsanahmad007
  • 23,683
  • 6
  • 47
  • 62
  • Thanks, tried it now, no error, but is best to remove the doInBackground and put try, catch there aswell? – moody May 11 '17 at 19:53
  • you can perform all non Ui related operation ...in your `doInBackground`...and you are already using try/catch in your `doInBackground `.. – rafsanahmad007 May 11 '17 at 19:56
  • `return null;`?...you should return a valid result in your `onPostExecute()` or can also move code from `doInBackground`..to `onPostExecute()`.. – rafsanahmad007 May 11 '17 at 19:57
  • yea i ment to just take the try and catch and put it into the onPostExecute. Sorry for mixup there. – moody May 11 '17 at 20:00
  • Haha, you were a step ahead of me :) – moody May 11 '17 at 20:00
0

You have to update UI from UI thread. As its not possible to update UI from doInBackground(), you can use runOnUiThread() to do update UI operations:

Try this:

@Override
protected String doInBackground(String... arg0) {

    ...........
    ...................

    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            grader.setText(informationTemp);
            vindhastighet.setText(informationVindhastighet);
            vindretning.setText(informationVindretning);

        }
    });

    .............
    .....................
}
Ferdous Ahamed
  • 21,438
  • 5
  • 52
  • 61