问题:
根据我的理解,我尝试在(工作人员?)chartview
activity
之外的thread
(GraphicalView chartView = ChartFactory.getLineChartView(getActivity(),dataSet,mRenderer);)
我使用WeatherLib
作为library
来接收天气数据。
谁知道我哪里出错?
代码:
import android.app.Fragment;
import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.LinearLayout;
import com.survivingwithandroid.weather.lib.WeatherClient;
import com.survivingwithandroid.weather.lib.WeatherConfig;
import com.survivingwithandroid.weather.lib.exception.WeatherLibException;
import com.survivingwithandroid.weather.lib.exception.WeatherProviderInstantiationException;
import com.survivingwithandroid.weather.lib.model.DayForecast;
import com.survivingwithandroid.weather.lib.model.HourForecast;
import com.survivingwithandroid.weather.lib.model.WeatherHourForecast;
import com.survivingwithandroid.weather.lib.provider.IWeatherProvider;
import com.survivingwithandroid.weather.lib.provider.WeatherProviderFactory;
import com.survivingwithandroid.weather.lib.provider.openweathermap.OpenweathermapProviderType;
import com.survivingwithandroid.weather.lib.request.WeatherRequest;
import org.achartengine.ChartFactory;
import org.achartengine.GraphicalView;
import org.achartengine.chart.BarChart;
import org.achartengine.chart.PointStyle;
import org.achartengine.model.RangeCategorySeries;
import org.achartengine.model.XYMultipleSeriesDataset;
import org.achartengine.model.XYSeries;
import org.achartengine.renderer.XYMultipleSeriesRenderer;
import org.achartengine.renderer.XYSeriesRenderer;
import java.util.List;
import java.util.Locale;
public class ChartWeatherFragment extends Fragment {
private LinearLayout chartLyt;
private View v;
private Animation fadeAnim;
// London, UK
private static final String CITY_ID = "2643743";
private WeatherClient client;
private List<DayForecast> dayForecast;
private List<HourForecast> nextHourForecast;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
fadeAnim = AnimationUtils.loadAnimation(getActivity(), R.anim.fade_anim);
getData();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
v = inflater.inflate(R.layout.fragment_chart, container, false);
chartLyt = (LinearLayout) v.findViewById(R.id.chart);
return v;
}
private void getData() {
Log.d("ChartWeatherFragment", "getData method");
final WeatherClient.ClientBuilder builder = new WeatherClient.ClientBuilder();
WeatherConfig config = new WeatherConfig();
config.lang = Locale.getDefault().getLanguage();
config.maxResult = 5;
config.numDays = 5;
config.unitSystem = WeatherConfig.UNIT_SYSTEM.M;
// Forecast IO API key
// config.ApiKey = "6396685aea23558da6383a01d9725666";
// Open Weather map API key
config.ApiKey = "#####################################";
try {
client = builder.attach(getActivity())
.provider(new OpenweathermapProviderType())
.httpClient(com.survivingwithandroid.weather.lib.client.okhttp.
WeatherDefaultClient.class)
.config(config)
.build();
} catch (WeatherProviderInstantiationException e) {
e.printStackTrace();
}
client.getHourForecastWeather(new WeatherRequest(CITY_ID), new WeatherClient.HourForecastWeatherEventListener() {
@Override
public void onWeatherRetrieved(WeatherHourForecast weatherHourForecast) {
nextHourForecast = weatherHourForecast.getHourForecast();
chartLyt.addView(createTempGraph(), 0);
}
@Override
public void onWeatherError(WeatherLibException e) {
e.printStackTrace();
}
@Override
public void onConnectionError(Throwable t) {
t.printStackTrace();
}
});
}
private View createTempGraph() {
// We start creating the XYSeries to plot the temperature
XYSeries series = new XYSeries("London Temperature hourly");
// We start filling the series
int hour = 0;
for (HourForecast hf : nextHourForecast) {
series.add(hour++, hf.weather.temperature.getTemp());
}
// Now we create the renderer
XYSeriesRenderer renderer = new XYSeriesRenderer();
renderer.setLineWidth(2);
renderer.setColor(Color.RED);
// Include low and max value
renderer.setDisplayBoundingPoints(true);
// we add point markers
renderer.setPointStyle(PointStyle.CIRCLE);
renderer.setPointStrokeWidth(3);
// Now we add our series
XYMultipleSeriesDataset dataSet = new XYMultipleSeriesDataset();
dataSet.addSeries(series);
// Finaly we create the multiple series renderer to control the graph
XYMultipleSeriesRenderer mRenderer = new XYMultipleSeriesRenderer();
mRenderer.addSeriesRenderer(renderer);
// We want to avoid black border
mRenderer.setMarginsColor(Color.argb(0x00, 0xff, 0x00, 0x00));
// Disable Pan on two axis
mRenderer.setPanEnabled(false, false);
mRenderer.setYAxisMax(35);
mRenderer.setYAxisMin(0);
mRenderer.setShowGrid(true); // we show the grid
GraphicalView chartView = ChartFactory.getLineChartView(getActivity(), dataSet, mRenderer);
// Enable chart click
mRenderer.setClickEnabled(true);
return chartView;
}
}
堆栈跟踪:
06-30 20:24:44.012 1903-1903/nl.inversion.weatherapp D/ChartWeatherFragment﹕ getData method
06-30 20:24:44.012 1903-1903/nl.inversion.weatherapp D/SwA﹕ Client [com.survivingwithandroid.weather.lib.client.okhttp.WeatherDefaultClient@b40a4ac8]
06-30 20:24:44.052 1903-1903/nl.inversion.weatherapp D/dalvikvm﹕ GC_FOR_ALLOC freed 220K, 10% free 3400K/3740K, paused 3ms, total 4ms
06-30 20:24:44.092 1903-1920/nl.inversion.weatherapp W/dalvikvm﹕ VFY: unable to find class referenced in signature (Ljava/nio/file/Path;)
06-30 20:24:44.092 1903-1920/nl.inversion.weatherapp W/dalvikvm﹕ VFY: unable to find class referenced in signature ([Ljava/nio/file/OpenOption;)
06-30 20:24:44.092 1903-1920/nl.inversion.weatherapp I/dalvikvm﹕ Could not find method java.nio.file.Files.newOutputStream, referenced from method okio.Okio.sink
06-30 20:24:44.092 1903-1920/nl.inversion.weatherapp W/dalvikvm﹕ VFY: unable to resolve static method 8451: Ljava/nio/file/Files;.newOutputStream (Ljava/nio/file/Path;[Ljava/nio/file/OpenOption;)Ljava/io/OutputStream;
06-30 20:24:44.092 1903-1920/nl.inversion.weatherapp D/dalvikvm﹕ VFY: replacing opcode 0x71 at 0x000a
06-30 20:24:44.092 1903-1920/nl.inversion.weatherapp W/dalvikvm﹕ VFY: unable to find class referenced in signature (Ljava/nio/file/Path;)
06-30 20:24:44.092 1903-1920/nl.inversion.weatherapp W/dalvikvm﹕ VFY: unable to find class referenced in signature ([Ljava/nio/file/OpenOption;)
06-30 20:24:44.092 1903-1920/nl.inversion.weatherapp I/dalvikvm﹕ Could not find method java.nio.file.Files.newInputStream, referenced from method okio.Okio.source
06-30 20:24:44.092 1903-1920/nl.inversion.weatherapp W/dalvikvm﹕ VFY: unable to resolve static method 8450: Ljava/nio/file/Files;.newInputStream (Ljava/nio/file/Path;[Ljava/nio/file/OpenOption;)Ljava/io/InputStream;
06-30 20:24:44.092 1903-1920/nl.inversion.weatherapp D/dalvikvm﹕ VFY: replacing opcode 0x71 at 0x000a
06-30 20:24:44.302 1903-1920/nl.inversion.weatherapp D/dalvikvm﹕ GC_FOR_ALLOC freed 386K, 13% free 3525K/4032K, paused 2ms, total 2ms
06-30 20:24:44.302 1903-1920/nl.inversion.weatherapp W/dalvikvm﹕ threadid=11: thread exiting with uncaught exception (group=0xb3d2db20)
06-30 20:24:44.302 1903-1920/nl.inversion.weatherapp E/AndroidRuntime﹕ FATAL EXCEPTION: OkHttp Dispatcher
Process: nl.inversion.weatherapp, PID: 1903
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:200)
at android.os.Handler.<init>(Handler.java:114)
at org.achartengine.GraphicalView.<init>(GraphicalView.java:93)
at org.achartengine.ChartFactory.getLineChartView(ChartFactory.java:71)
at nl.inversion.weatherapp.ChartWeatherFragment.createTempGraph(ChartWeatherFragment.java:152)
at nl.inversion.weatherapp.ChartWeatherFragment.access$100(ChartWeatherFragment.java:40)
at nl.inversion.weatherapp.ChartWeatherFragment$1.onWeatherRetrieved(ChartWeatherFragment.java:101)
at com.survivingwithandroid.weather.lib.client.okhttp.WeatherDefaultClient$6.onResponse(WeatherDefaultClient.java:381)
at com.squareup.okhttp.Call$AsyncCall.execute(Call.java:150)
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:841)
更新,问题已解决
感谢
由于我无法使用Activity.runOnUiThread(new Runnable()),我现在正在使用似乎有效的处理程序。感谢名单!
代码snippit:
client.getHourForecastWeather(new WeatherRequest(cityId),
new WeatherClient.HourForecastWeatherEventListener() {
@Override
public void onWeatherRetrieved(WeatherHourForecast weatherHourForecast) {
nextHourForecast = weatherHourForecast.getHourForecast();
/* Update UI
* Since callback is invoked on a background worker thread, create a handler
* to update the layout in the main UI thread
*/
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
public void run() {
chartLyt.addView(createTempGraph(), 0);
}
});
}
@Override
public void onWeatherError(WeatherLibException e) {
e.printStackTrace();
}
@Override
public void onConnectionError(Throwable t) {
t.printStackTrace();
}
});
答案 0 :(得分:3)
是的,在后台工作线程上调用onWeatherRetrieved()
回调。您只能在主UI线程上触摸UI小部件,因此只能触摸异常。
使用例如Activity
runOnUiThread()
发布要在主UI线程上运行的Runnable
。