我在运行RssReader的Android项目时出错。
代码:
URL url = new URL(urlToRssFeed);
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
XMLReader xmlreader = parser.getXMLReader();
RssHandler theRSSHandler = new RssHandler();
xmlreader.setContentHandler(theRSSHandler);
InputSource is = new InputSource(url.openStream());
xmlreader.parse(is);
return theRSSHandler.getFeed();
它显示以下错误:
android.os.NetworkOnMainThreadException
如何解决此问题?
对我来说是这样的:
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="10" />
我测试应用程序的设备是4.1.2,即SDK版本16!
确保目标版本与Android目标库相同。如果你不确定你的目标库是什么,右键单击你的项目->构建路径->Android,它应该是勾选的那个。
此外,正如其他人所提到的,包括访问Internet的正确权限:
<uses-permission android:name="android.permission.INTERNET"/>
在Android上,网络操作不能在主线程上运行。您可以使用线程、异步任务(短期运行任务)和服务(长期运行任务)来执行网络操作。当应用程序尝试在其主线程上执行网络操作时,将引发android.os.NetworkOnMainThreadException。如果您的任务耗时超过5秒,则需要强制关闭。
在AsyncTask中运行代码:
class FeedTask extends AsyncTask<String, Void, Boolean> {
protected RSSFeed doInBackground(String... urls) {
// TODO: Connect
}
protected void onPostExecute(RSSFeed feed) {
// TODO: Check this.exception
// TODO: Do something with the feed
}
}
Or
new Thread(new Runnable(){
@Override
public void run() {
try {
// Your implementation
}
catch (Exception ex) {
ex.printStackTrace();
}
}
}).start();
不建议这样做。
但出于调试目的,也可以使用以下代码禁用严格模式:
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy =
new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
RxAndroid是解决这个问题的另一个更好的选择,它让我们省去了创建线程然后在Android UI线程上发布结果的麻烦。
我们只需要指定需要在哪些线程上执行任务,并且所有事情都在内部处理。
Observable<List<String>> musicShowsObservable = Observable.fromCallable(new Callable<List<String>>() {
@Override
public List<String> call() {
return mRestClient.getFavoriteMusicShows();
}
});
mMusicShowSubscription = musicShowsObservable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<List<String>>() {
@Override
public void onCompleted() { }
@Override
public void onError(Throwable e) { }
@Override
public void onNext(List<String> musicShows) {
listMusicShows(musicShows);
}
});
通过指定(Schedulers.io()),RxAndroid将在不同的线程上运行getFavoriteMusicShows()。通过使用AndroidSchedulers.mainThread(),我们希望在UI线程上观察这个Observable,也就是说,我们希望我们的onNext()回调在UI线程中被调用。