【问题标题】:Method setText must be called from the UI thread方法 setText 必须从 UI 线程调用
【发布时间】:2017-05-11 19:36:13
【问题描述】:

已阅读所有集合并从 UI 线程调用,在 stackoverflow 上,但似乎没有一个相关的。此代码在 2 年前有效,最近打开它。它显示了这个错误。 “必须从 UI 线程调用 setText 方法”。
这是什么更新? 用 cmets 标记 setText 行以使其更清晰。有什么建议吗?

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);
                            }
                        }

                        }

    });
}
}

【问题讨论】:

    标签: android multithreading android-asynctask background


    【解决方案1】:
    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder() .detectAll().penaltyLog().build();     StrictMode.setThreadPolicy(policy);
    

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

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

    【讨论】:

    • “这实际上不再被允许了”——出于好奇,你有这方面的任何细节吗?我从来没有尝试过关闭线程策略的东西,但是我上次尝试禁用 FileUriExposedException 时起作用了。
    • 如果我今晚有时间的话,我会看看我能找到什么。我记得现在至少有一些被禁用了。
    • 或者它可能与issuetracker.google.com/issues/36951662有关,但无论哪种方式,OP都应该避免设置严格的模式策略来编写这样的代码
    • 哦,当然。当有机会时,我会对人们大喊大叫。 :-) 谢谢!
    【解决方案2】:

    您无法从doInBackground 中的AsyncTask 更新UI。

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

    您可以使用runonUithreaddoInBackground 内的textview 中更新文本

    这是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()

    【讨论】:

    • 谢谢,现在试了,没有报错,不过最好把doInBackground去掉,然后把try,也抓到那里?
    • 您可以在您的doInBackground...中执行所有与UI无关的操作...并且您已经在您的doInBackground 中使用try/catch ...
    • return null;?...您应该在onPostExecute() 中返回有效结果,或者也可以将代码从doInBackground..移动到onPostExecute()..
    • 是的,只需尝试并捕获并将其放入 onPostExecute。很抱歉混淆了。
    • 哈哈,你比我领先一步 :)
    【解决方案3】:

    您必须从 UI thread 更新 UI。由于无法从doInBackground() 更新UI,您可以使用runOnUiThread() 进行更新UI 操作:

    试试这个:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多