从 URL 解析 XML 并陷入循环
Parsing XML fron URL and stuck in loop
我正在尝试从 URL 解析 XML 但没有得到任何数据,当我debug 我看到我陷入了 while()
循环。在我放弃之前,变量 i 达到了 160。我不明白为什么我卡在 while 循环中而没有进入循环中的任何 if 语句。
public class Task extends AsyncTask<Void,Void,Void> {
private List<Task> tasks;
public Task()
{
}
@Override
protected Void doInBackground(Void... params) {
makeTask();
return null;
}
public Task(String title){
mTitle = title;
}
private List<Task> makeTask(){
int i = 0;
tasks = new ArrayList<>();
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
URL url = new URL("http://xxx");
InputStream stream = url.openStream();
xpp.setInput(stream, null);
int eventType = xpp.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_DOCUMENT) {
}
else if (eventType == XmlPullParser.END_DOCUMENT) {
}
else if (eventType == XmlPullParser.START_TAG) {
if (xpp.getName().equalsIgnoreCase("Task")) {
tasks.add(new Task(xpp.nextText()));
Log.d("Task: ", xpp.nextText());
}
else if (eventType == XmlPullParser.END_TAG) {
}
else if (eventType == XmlPullParser.TEXT) {
}
eventType = xpp.next();
}
i++;
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return tasks;
}
编辑:
这是新的 while()
循环,感谢 @imsiso
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) {
if (xpp.getName().equalsIgnoreCase("name")) {
tasks.add(new Task(xpp.nextText()));
}
eventType = xpp.next();
}
else
eventType = xpp.next();
代码 List<Task> tasks = task.getTasks();
下面的行给出了错误:
java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()' on a null object reference
我认为我收到该错误是因为我没有等待 AsyncTask
完成并且不知道我应该怎么做。
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
/*Removed irrelevant code here*/
Task task = new Task();
new Task().execute();
List<Task> tasks = task.getTasks();
mAdapter = new TaskAdapter(tasks);
mTaskRV.setAdapter(mAdapter);
return view;
}
您应该提供一个侦听器来监听将在 doInBackground() 完成时触发的异步任务。例如:
public interface TaskListener{
public void onTaskDone(List<Task> results);
}
public class Task extends AsyncTask<Void,Void,Void> {
private List<Task> tasks;
private TaskListener mListener;
public Task(TaskListener listener)
{
this.mListener = listener;
}
protected Void doInBackground(Void... params) {
.... xml parsing...
if (mListener != null){
mListener.onTaskDone(tasks);
}
}
}
创建任务时:
Task task = new Task(this);
让 class 实现 TaskListener
接口。
在此方法中,您将任务的结果提供给适配器。
public void onTaskDone(final List<Task> tasks){
runOnUiThread(new Runnable() {
@Override
public void run() {
mAdapter = new TaskAdapter(tasks);
mTaskRV.setAdapter(mAdapter);
}
});
}
先用这个比较清楚吧。使用 get text 应该更好,因为它可以避免在其他情况下跳过标签等。
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) {
if (xpp.getName().equalsIgnoreCase("name")) {
tasks.add(new Task(xpp.getText()));
}
}
eventType = xpp.next();
}
并指出 List<Task> tasks = task.getTasks();
中的错误 这应该会有所帮助
我也没有得到这部分:
Task task = new Task();
new Task().execute();
下面是加载程序的 TaskLoader 和回调示例。
private LoaderManager.LoaderCallbacks<List<TaskModel>> mLoaderCallbacks = new LoaderManager.LoaderCallbacks<List<TaskModel>>()
{
@Override
public Loader<List<TaskModel>> onCreateLoader(int id, Bundle args)
{
return new TaskLoader(getContext());
}
@Override
public void onLoadFinished(Loader<List<TaskModel>> loader, List<TaskModel> data)
{
mTaskRV.setAdapter(new TaskAdapter(data));
}
@Override
public void onLoaderReset(Loader<List<TaskModel>> loader)
{
//
}
};
还有任务加载器。
private static class TaskLoader extends AsyncTaskLoader<List<TaskModel>>
{
private static final String TAG = TaskLoader.class.getSimpleName();
private List<TaskModel> mData = null;
public TaskLoader(Context context)
{
super(context);
}
@Override
protected void onStartLoading()
{
super.onStartLoading();
if(mData != null){
deliverResult(mData);
}
if(takeContentChanged() || mData == null){
forceLoad();
}
}
@Override
public void deliverResult(List<TaskModel> data)
{
mData = data;
super.deliverResult(data);
}
@Override
public List<TaskModel> loadInBackground()
{
try{
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
URL url = new URL("http://xxx");
InputStream in = null;
try{
in = url.openStream();
xpp.setInput(in, "UTF-8");
return parseTasks(xpp);
}
finally{
if(in != null){
in.close();
}
}
}
catch(MalformedURLException e){
Log.e(TAG, "loadInBackground", e);
}
catch(XmlPullParserException e){
Log.e(TAG, "loadInBackground", e);
}
catch(IOException e){
Log.e(TAG, "loadInBackground", e);
}
return null;
}
private List<TaskModel> parseTasks(XmlPullParser xpp)
throws XmlPullParserException, IOException
{
ArrayList<TaskModel> tasks = new ArrayList<>();
int eventType = xpp.getEventType();
while(eventType != XmlPullParser.END_DOCUMENT){
if(eventType == XmlPullParser.START_TAG){
if(xpp.getName().equalsIgnoreCase("description")){
tasks.add(new TaskModel(xpp.nextText()));
}
}
eventType = xpp.next();
}
return tasks;
}
}
我正在尝试从 URL 解析 XML 但没有得到任何数据,当我debug 我看到我陷入了 while()
循环。在我放弃之前,变量 i 达到了 160。我不明白为什么我卡在 while 循环中而没有进入循环中的任何 if 语句。
public class Task extends AsyncTask<Void,Void,Void> {
private List<Task> tasks;
public Task()
{
}
@Override
protected Void doInBackground(Void... params) {
makeTask();
return null;
}
public Task(String title){
mTitle = title;
}
private List<Task> makeTask(){
int i = 0;
tasks = new ArrayList<>();
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
URL url = new URL("http://xxx");
InputStream stream = url.openStream();
xpp.setInput(stream, null);
int eventType = xpp.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_DOCUMENT) {
}
else if (eventType == XmlPullParser.END_DOCUMENT) {
}
else if (eventType == XmlPullParser.START_TAG) {
if (xpp.getName().equalsIgnoreCase("Task")) {
tasks.add(new Task(xpp.nextText()));
Log.d("Task: ", xpp.nextText());
}
else if (eventType == XmlPullParser.END_TAG) {
}
else if (eventType == XmlPullParser.TEXT) {
}
eventType = xpp.next();
}
i++;
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return tasks;
}
编辑:
这是新的 while()
循环,感谢 @imsiso
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) {
if (xpp.getName().equalsIgnoreCase("name")) {
tasks.add(new Task(xpp.nextText()));
}
eventType = xpp.next();
}
else
eventType = xpp.next();
代码 List<Task> tasks = task.getTasks();
下面的行给出了错误:
java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()' on a null object reference
我认为我收到该错误是因为我没有等待 AsyncTask
完成并且不知道我应该怎么做。
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
/*Removed irrelevant code here*/
Task task = new Task();
new Task().execute();
List<Task> tasks = task.getTasks();
mAdapter = new TaskAdapter(tasks);
mTaskRV.setAdapter(mAdapter);
return view;
}
您应该提供一个侦听器来监听将在 doInBackground() 完成时触发的异步任务。例如:
public interface TaskListener{
public void onTaskDone(List<Task> results);
}
public class Task extends AsyncTask<Void,Void,Void> {
private List<Task> tasks;
private TaskListener mListener;
public Task(TaskListener listener)
{
this.mListener = listener;
}
protected Void doInBackground(Void... params) {
.... xml parsing...
if (mListener != null){
mListener.onTaskDone(tasks);
}
}
}
创建任务时:
Task task = new Task(this);
让 class 实现 TaskListener
接口。
在此方法中,您将任务的结果提供给适配器。
public void onTaskDone(final List<Task> tasks){
runOnUiThread(new Runnable() {
@Override
public void run() {
mAdapter = new TaskAdapter(tasks);
mTaskRV.setAdapter(mAdapter);
}
});
}
先用这个比较清楚吧。使用 get text 应该更好,因为它可以避免在其他情况下跳过标签等。
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) {
if (xpp.getName().equalsIgnoreCase("name")) {
tasks.add(new Task(xpp.getText()));
}
}
eventType = xpp.next();
}
并指出 List<Task> tasks = task.getTasks();
中的错误 这应该会有所帮助
我也没有得到这部分:
Task task = new Task();
new Task().execute();
下面是加载程序的 TaskLoader 和回调示例。
private LoaderManager.LoaderCallbacks<List<TaskModel>> mLoaderCallbacks = new LoaderManager.LoaderCallbacks<List<TaskModel>>()
{
@Override
public Loader<List<TaskModel>> onCreateLoader(int id, Bundle args)
{
return new TaskLoader(getContext());
}
@Override
public void onLoadFinished(Loader<List<TaskModel>> loader, List<TaskModel> data)
{
mTaskRV.setAdapter(new TaskAdapter(data));
}
@Override
public void onLoaderReset(Loader<List<TaskModel>> loader)
{
//
}
};
还有任务加载器。
private static class TaskLoader extends AsyncTaskLoader<List<TaskModel>>
{
private static final String TAG = TaskLoader.class.getSimpleName();
private List<TaskModel> mData = null;
public TaskLoader(Context context)
{
super(context);
}
@Override
protected void onStartLoading()
{
super.onStartLoading();
if(mData != null){
deliverResult(mData);
}
if(takeContentChanged() || mData == null){
forceLoad();
}
}
@Override
public void deliverResult(List<TaskModel> data)
{
mData = data;
super.deliverResult(data);
}
@Override
public List<TaskModel> loadInBackground()
{
try{
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
URL url = new URL("http://xxx");
InputStream in = null;
try{
in = url.openStream();
xpp.setInput(in, "UTF-8");
return parseTasks(xpp);
}
finally{
if(in != null){
in.close();
}
}
}
catch(MalformedURLException e){
Log.e(TAG, "loadInBackground", e);
}
catch(XmlPullParserException e){
Log.e(TAG, "loadInBackground", e);
}
catch(IOException e){
Log.e(TAG, "loadInBackground", e);
}
return null;
}
private List<TaskModel> parseTasks(XmlPullParser xpp)
throws XmlPullParserException, IOException
{
ArrayList<TaskModel> tasks = new ArrayList<>();
int eventType = xpp.getEventType();
while(eventType != XmlPullParser.END_DOCUMENT){
if(eventType == XmlPullParser.START_TAG){
if(xpp.getName().equalsIgnoreCase("description")){
tasks.add(new TaskModel(xpp.nextText()));
}
}
eventType = xpp.next();
}
return tasks;
}
}