我正在关注一个Android教程并构建一个Weather应用程序,但是当我尝试将mTemperature TextView设置为我从预测API获得的温度时,我收到此错误" android.view.ViewRootImpl $ CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能触及其视图。"。当我登录查看所有天气细节时,代码确实工作正常。 有人可以提出解决方案吗?我必须提到我正在使用名为OkHTTP的异步HTTP调用的第三方API。
这是我在MainActivity中的代码:
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)
答案 0 :(得分:2)
尝试从不是UI线程的任何线程访问UI元素时发生此错误。
要从non-UI-thread
访问/修改元素,请使用runOnUIThread