【问题标题】:Parsing XML fron URL and stuck in loop从 URL 解析 XML 并陷入循环
【发布时间】:2016-02-27 18:52:44
【问题描述】:

我试图从 URL 解析 XML 并且没有得到任何数据,当我调试时我发现我陷入了while() 循环。在我放弃之前,我达到了 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&lt;Task&gt; tasks = task.getTasks();下面的行给出错误:

java.lang.NullPointerException:尝试在空对象引用上调用接口方法“int java.util.List.size()”

我认为我收到了该错误,因为我没有等待 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;
}

【问题讨论】:

  • 您正在解析 JSON 或 XML?代码与您的问题标题不匹配。
  • 是的,我正在解析 XML,我不知道我为什么要写 JSON。谢谢,现在编辑。
  • 仅从您的代码来看,它似乎卡在了第一步。触发案例条件 start_document 的原因你不要更改任何类似 Xpp.next 的东西,所以同样的事情会一次又一次地发生
  • @imsiso 我删除了所有的 if 语句,但保留了 if (eventType == XmlPullParser.START_TAG),为什么它永远不会为真,为什么我仍然卡在循环中?
  • 让我告诉你,我只使用逻辑,不知道你使用的代码。所以试试这个。 If(.start_tag){blabla}else{xpp.next();} 因此,如果您的条件不成立,那么 xpp.next 应该将您移动到下一个节点或其他东西,那么不会发生循环。如果这项工作将帮助您更近一步

标签: android xml parsing url android-asynctask


【解决方案1】:

这是一个示例 TaskLoader 和 Loader 的回调。

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)
    {
        //
    }
};

还有TaskLoader。

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

【讨论】:

    【解决方案2】:

    您应该为将在 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);
    

    让类实现TaskListener 接口。

    在此方法中,您将任务的结果提供给适配器。

    public void onTaskDone(final List<Task> tasks){
            runOnUiThread(new Runnable() {
    
                    @Override
                    public void run() {
                          mAdapter = new TaskAdapter(tasks);
                          mTaskRV.setAdapter(mAdapter);
                    }
            });
    
    
    }
    

    【讨论】:

    • 当我在 onTaskDone 上添加新代码时,onCreateView 不会等待 onTaskDone,因此视图将为空,这是新的 onTaskDone 代码:pastebin.com/w1Sr5CnJ
    【解决方案3】:

    首先让我们使用这个更清楚。并且使用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&lt;Task&gt; tasks = task.getTasks(); 中出现了一个错误,这应该有助于https://stackoverflow.com/a/218510/2226796

    我也没有得到这部分:

    Task task = new Task();
    new Task().execute();
    

    【讨论】:

    • 我知道你为什么会得到 NPE,我的问题是我怎么能等待 AsyncTask 所以我不明白。我使用 new Task().execte();运行 AsyncTask。
    • @neX 不知道:|只是我希望你在我给你的链接中找到更多。你可以检查一下
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多