android.view.ViewRootImpl$CalledFromErrorThreadException,OkHttp

android.view.ViewRootImpl$CalledFromErrorThreadException,OkHttp,android,multithreading,exception,Android,Multithreading,Exception,我正在学习android教程并构建一个天气应用程序,但是当我尝试将mTemperature TextView设置为从forecast API获得的温度时,我得到了以下错误:“android.view.ViewRootImpl$calledFromErrorThreadException:只有创建视图层次结构的原始线程才能接触其视图。”。当我登录查看所有天气细节时,代码确实工作得很好。 有人能提出解决办法吗?我必须提到,我正在使用第三方API进行名为OkHTTP的异步HTTP调用 这是我的主要活动

我正在学习android教程并构建一个天气应用程序,但是当我尝试将mTemperature TextView设置为从forecast API获得的温度时,我得到了以下错误:“android.view.ViewRootImpl$calledFromErrorThreadException:只有创建视图层次结构的原始线程才能接触其视图。”。当我登录查看所有天气细节时,代码确实工作得很好。 有人能提出解决办法吗?我必须提到,我正在使用第三方API进行名为OkHTTP的异步HTTP调用

这是我的主要活动中的代码:

public class MainActivity extends Activity {
public static final String TAG = MainActivity.class.getSimpleName();
private TextView mTemperature;
private CurrentWeather mCurrentWeather;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    //-----------MY CODE STARTS HERE------------------
    mTemperature = (TextView)findViewById(R.id.temp);
    String API_KEY = "API_KEY";
    //aberdeen, coordinates
    double latitude = 57.1531;
    double longtitude = -2.0928;
    String forecast = "https://api.forecast.io/forecast/"+ API_KEY +"/"+ latitude+","+ longtitude;

    if(isNetworkAvailable()) {
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url(forecast)
                .build();

        Call call = client.newCall(request);

        call.enqueue(new Callback() {
            @Override
            public void onFailure(Request request, IOException e) {a

            }
            //when the call to the Okhttp library finishes, than calls this method:
            @Override
            public void onResponse(Response response) throws IOException {
                try {
                    String jsonData = response.body().string();
                    //Log.v(TAG, jsonData);
                    if (response.isSuccessful()) {
                        mCurrentWeather = getCurrentDetails(jsonData);
                        //do sth with the forecast details
                        mTemperature.setText(mCurrentWeather.getTemperature()+"");
                    } else {
                        alertUserAboutError();
                    }
                } catch (IOException e) {
                    Log.e(TAG, "Exception caught:", e);
                }
                catch (JSONException e){
                    Log.e(TAG, "Exception caught:", e);
                }
            }
        });
    }else{
        //Toast.makeText(this,getString(R.string.network_unavailable_message),Toast.LENGTH_LONG).show();
        WIFIDialogFragment dialog = new WIFIDialogFragment();
        dialog.show(getFragmentManager(), getString(R.string.error_dialog_text));
    }
    Log.d(TAG, "Main UI code is running!");


}
//throws JSONException, doing it like that, we place the
// responsability of handaling this exeption to the caller of the method
private CurrentWeather getCurrentDetails(String jsonData) throws JSONException{
    JSONObject forecast = new JSONObject(jsonData);
    String timezone = forecast.getString("timezone");
    Log.i(TAG,"From JSON: " + timezone);

    JSONObject currently = forecast.getJSONObject("currently");
    CurrentWeather currentWeather = new CurrentWeather();
    currentWeather.setHumidity(currently.getDouble("humidity"));
    currentWeather.setTime(currently.getLong("time"));
    currentWeather.setIcon(currently.getString("icon"));
    currentWeather.setPrecipChange(currently.getDouble("precipProbability"));
    currentWeather.setSummery(currently.getString("summary"));
    currentWeather.setTemperature(currently.getDouble("temperature"));
    currentWeather.setTimeZone(timezone);

    Log.d(TAG,currentWeather.getFormattedTime());
    return currentWeather;
}

private boolean isNetworkAvailable() {
    ConnectivityManager manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = manager.getActiveNetworkInfo();
    boolean isAvailable = false;
    //contition to check if there is a network and if the device is connected
    if(networkInfo != null && networkInfo.isConnected()){
        isAvailable = true;
    }

    return isAvailable;
}

private void alertUserAboutError() {
    AlertDIalogFragment dialog = new AlertDIalogFragment();
    dialog.show(getFragmentManager(),getString(R.string.error_dialog_text));
}
}

这是logcat的完整日志:

05-16 03:25:59.941    5348-5370/koemdzhiev.com.stormy E/AndroidRuntime﹕ FATAL EXCEPTION: OkHttp Dispatcher
Process: koemdzhiev.com.stormy, PID: 5348
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
        at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6357)
        at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:874)
        at android.view.View.requestLayout(View.java:17476)
        at android.view.View.requestLayout(View.java:17476)
        at android.view.View.requestLayout(View.java:17476)
        at android.view.View.requestLayout(View.java:17476)
        at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:360)
        at android.view.View.requestLayout(View.java:17476)
        at android.widget.TextView.checkForRelayout(TextView.java:6871)
        at android.widget.TextView.setText(TextView.java:4057)
        at android.widget.TextView.setText(TextView.java:3915)
        at android.widget.TextView.setText(TextView.java:3890)
        at koemdzhiev.com.stormy.MainActivity$1.onResponse(MainActivity.java:67)
        at com.squareup.okhttp.Call$AsyncCall.execute(Call.java:168)
        at com.squareup.okhttp.internal.NamedRunnable.run(NamedRunnable.java:33)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
        at java.lang.Thread.run(Thread.java:818)

当尝试从非UI线程的任何线程访问UI元素时,会发生此错误


要从
非UI线程访问/修改元素
,请使用
runOnUIThread

谢谢您的快速响应。我是android开发新手,你能告诉我怎么做吗