我正在学习HTML和使用XML DOM解析数据。为此,我创建了一个应用程序,该应用程序从Yahoo的Wheater API中读取了Wheater。

执行应用程序时,在logcat中显示一条错误:java.lang.RuntimeException:无法在没有调用程序Looper.prepare()的线程内创建处理程序。

我不知道这意味着什么,或者代码是否正确。

这是Yahoo的Wheater API的XML文件的链接:

http://weather.yahooapis.com/forecastrss?w=766273&u=c

这是我的代码:

public class WeatherActivity extends Activity {

private static final String WEATHER_URL = "http://weather.yahooapis.com/forecastjson?w=";
private static final String MADRID_CODE = "766273";

private static final String LOCATION_NAME = "location";
private static final String CITY_NAME = "city";
private static final String CONDITION_NAME = "condition";
private static final String TEMPERATURE_NAME = "temperature";
private static final String FORECAST_NAME = "forecast";
private static final String DAY_NAME = "day";
private static final String HIGH_TEMPERATURE_NAME = "high_temperature";
private static final String LOW_TEMPERATURE_NAME = "low_temperature";

private static final String TODAY = "Today";
private static final String TOMORROW = "Tomorrow";

private Button mButton;
private TextView mCity;
private TextView mToday;
private TextView mTomorrow;


private class WeatherInfo {
    String city;
    int temperatureNow;
    int lowTemperature;
    int highTemperature;
    int lowTemperatureTomorrow;
    int highTemperatureTomorrow;
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mCity = (TextView) findViewById(R.id.city);
    mToday = (TextView) findViewById(R.id.today);
    mTomorrow = (TextView) findViewById(R.id.tomorrow);

    mButton = (Button) findViewById(R.id.button);
    mButton.setOnClickListener(new OnClickListener() {

        public void onClick(View v) {
            launch();
        }
    });
}

private void launch(){
    try {
        new WeatherAsyncTask().execute(MADRID_CODE);
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
        Toast.makeText(WeatherActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
    }
}


private class WeatherAsyncTask extends AsyncTask<String, Void, WeatherInfo>{

    @Override
    protected WeatherInfo doInBackground(String... params) {
        String code = params[0];
        if (TextUtils.isEmpty(code))
            throw new IllegalArgumentException("Code cannot be empty");

        URL url = null;
        HttpURLConnection connection = null;

        try {
            url = new URL(WEATHER_URL + code);
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");

            InputStream is = connection.getInputStream();
            WeatherInfo info = readWeatherInfo(is);
            return info;

        } catch (IOException e) {
            e.printStackTrace();
            Toast.makeText(WeatherActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
        } finally {
            if (connection != null)
                connection.disconnect();
        }
        return null;
    }

    @Override
    protected void onPostExecute(WeatherInfo result) {
        super.onPostExecute(result);
        showResult(result);
    }



    private WeatherInfo readWeatherInfo(InputStream is){
        if (is == null)
            return null;

        WeatherInfo info = new WeatherInfo();

        try {

            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document dom = builder.parse(is);
            Element root = dom.getDocumentElement();
            NodeList items = root.getElementsByTagName("item");

            for (int i=0; i<items.getLength(); i++) {
                Node item = items.item(i);
                NodeList datos = item.getChildNodes();

                for (int j=0; j<datos.getLength(); j++) {
                    Node dato = datos.item(j);
                    String etiqueta = dato.getNodeName();

                    if (etiqueta.equals(LOCATION_NAME)) {
                        String texto = obtenerTexto(dato);
                        if (texto.equals(TEMPERATURE_NAME)) {
                            info.city = texto;
                        }
                    }

                    else if (etiqueta.equals(CONDITION_NAME)) {
                        String texto = obtenerTexto(dato);
                        if (texto.equals(CITY_NAME)) {
                            info.temperatureNow = Integer.parseInt(texto);
                        }
                    }
                    else if (etiqueta.equals(FORECAST_NAME)) {
                        String texto = obtenerTexto(dato);
                        String day = null;
                        int high = -111;
                        int low = -111;

                        if (texto.equals(DAY_NAME)){
                            day = texto;
                        } else if (texto.equals(HIGH_TEMPERATURE_NAME)){
                            high = Integer.parseInt(texto);
                        }  else if (texto.equals(LOW_TEMPERATURE_NAME)){
                            low = Integer.parseInt(texto);
                        }

                        if (day.equals(TODAY)){
                            info.highTemperature = high;
                            info.lowTemperature = low;
                        } else if (day.equals(TOMORROW)){
                            info.highTemperatureTomorrow = high;
                            info.lowTemperatureTomorrow = low;
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            throw new RuntimeException(ex);
        }

        return info;
    }


    private String obtenerTexto(Node dato) {
        StringBuilder texto = new StringBuilder();
        NodeList fragmentos = dato.getChildNodes();

        for (int k=0;k<fragmentos.getLength();k++) {
            texto.append(fragmentos.item(k).getNodeValue());
        }
        return texto.toString();
    }

}

private void showResult(WeatherInfo info){
    mCity.setText("Temperature in " + info.city);
    mToday.setText("Today: " + info.temperatureNow + " F (min: " + info.lowTemperature + " F / max: " + info.highTemperature + " F).");
    mTomorrow.setText("Tomorrow: min: " + info.lowTemperatureTomorrow + " F / max: " + info.highTemperatureTomorrow + " F.");
}


}

最佳答案

您不能在ToastdoInBackground中显示ASyncTask

尝试将其包装在runOnUIThread()中,如下所示:

runOnUiThread(new Runnable() {
    @Override
    public void run() {
        Toast.makeText(WeatherActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
    }
});

09-09 20:15