从 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;
    }
}