必须从UI线程调用方法setText

时间:2017-05-11 19:36:14

标签: android multithreading android-asynctask background

读取了所有的set并从UI线程调用,在stackoverflow上但似乎没有相关的。这段代码工作了2年,最近打开了它。它显示了这个错误。 “必须从UI线程调用方法setText” 有什么更新呢? 用注释标记setText行以使其更清晰。任何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);
                            }
                        }

                        }

    });
}
}

2 个答案:

答案 0 :(得分:4)

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

这实际上是关闭严格模式,这允许不安全的事情,例如更新非UI线程上的UI而不是将其记录到磁盘。实际上不允许这样做了。所以你的代码总是错的,你只是忽略了错误,并希望你不会被抓住。正确的解决方法是将代码移动到UI线程,并且可能在整个代码库中删除StrictMode的所有提及 - 它应该只用作调试工具,甚至可能不会用。

关于不从线程更新UI的所有建议都是绝对相关的 - 你在doInBackground中的AsyncTask上设置UI,所以从另一个线程。通过runOnUiThread,处理程序或将其关闭直到onPostExecute或进度消息,将其移动到UI线程。

答案 1 :(得分:2)

您无法从doInBackground中的AsyncTask更新用户界面。

所有与UI相关的操作都需要在UI线程内完成。

您可以使用runonUithread更新doInBackground

内文本视图中的文字

这是example

代码:

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

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

        }
    });

}

或者......更好的解决方案是将setText()代码移到onPostExecute()