Android 从URL解析XML并卡在循环中

Android 从URL解析XML并卡在循环中,android,xml,parsing,url,android-asynctask,Android,Xml,Parsing,Url,Android Asynctask,我试图从URL解析XML,但没有得到任何数据,调试时我发现自己陷入了while()循环。在我放弃之前,我的变量达到了160。我不明白为什么我被困在while循环中,而没有进入循环中的if语句 public class Task extends AsyncTask<Void,Void,Void> { private List<Task> tasks; public Task() { } @Override protected Void doInBackground(V

我试图从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;
}
代码
List 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;
}
@覆盖
CreateView上的公共视图(布局、充气机、视图组容器、捆绑包保存状态){
/*删除了不相关的代码*/
任务=新任务();
新任务().execute();
List tasks=task.getTasks();
mAdapter=新任务适配器(任务);
mTaskRV.setAdapter(mAdapter);
返回视图;
}

您应该提供异步任务的侦听器,该任务将在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);
    }
  }
}
让类实现
TaskListener
接口

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

public void onTaskDone(final List<Task> tasks){
        runOnUiThread(new Runnable() {

                @Override
                public void run() {
                      mAdapter = new TaskAdapter(tasks);
                      mTaskRV.setAdapter(mAdapter);
                }
        });


}
public void onTaskDone(最终列出任务){
runOnUiThread(新的Runnable(){
@凌驾
公开募捐{
mAdapter=新任务适配器(任务);
mTaskRV.setAdapter(mAdapter);
}
});
}

首先,让我们暂时使用它,这更清楚。使用get文本应该更好,因为它可以避免在其他情况下跳过标记等

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 tasks=task.getTasks()中找出该错误这应该有帮助

我也没有得到这个部分:

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

下面是一个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)
    {
        //
    }
};
private LoaderManager.LoaderCallbacks MLLoaderCallbacks=新建LoaderManager.LoaderCallbacks()
{
@凌驾
公共加载器onCreateLoader(int-id,Bundle-args)
{
返回新的TaskLoader(getContext());
}
@凌驾
public void onLoadFinished(加载程序,列表数据)
{
mTaskRV.setAdapter(新任务适配器(数据));
}
@凌驾
公共void onLoaderReset(加载器)
{
//
}
};
还有任务加载器

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;
    }
}
私有静态类TaskLoader扩展了AsyncTaskLoader
{
私有静态最终字符串标记=TaskLoader.class.getSimpleName();
私有列表mData=null;
公共任务加载器(上下文)
{
超级(上下文);
}
@凌驾
开始加载时受保护的void()
{
super.onStartLoading();
如果(mData!=null){
交付结果(mData);
}
if(takeContentChanged()| | mData==null){
力载荷();
}
}
@凌驾
公共无效交付结果(列表数据)
{
mData=数据;
super.deliverResult(数据);
}
@凌驾
公共列表加载背景()
{
试一试{
XmlPullParserFactory工厂=XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp=factory.newPullParser();
URL=新URL(“http://xxx");
InputStream in=null;
试一试{
in=url.openStream();
xpp.setInput(在“UTF-8”中);
返回任务(xpp);
}
最后{
if(in!=null){
in.close();
}
}
}
捕获(格式错误){
日志e(标签“loadInBackground”,e);
}
catch(XMLPullParseRexE){
日志e(标签“loadInBackground”,e);
}
捕获(IOE异常){
日志e(标签“loadInBackground”,e);
}
返回null;
}
私有列表解析任务(XmlPullParser xpp)
引发XmlPullParserException,IOException
{
ArrayList tasks=新建ArrayList();
int eventType=xpp.getEventType();
while(eventType!=XmlPullParser.END_文档){
if(eventType==XmlPullParser.START_标记){
if(xpp.getName().equalsIgnoreCase(“说明”)){
添加(新的TaskModel(xpp.nextText());
}
}
eventType=xpp.next();
}
返回任务;
}
}

您正在解析JSON或XML?代码与您的问题标题不匹配。是的,我正在解析XML,我不知道为什么要编写JSON。谢谢,现在编辑。从你的代码来看,它似乎卡在了第一步。案例条件启动文档被触发的原因您不要更改任何类似Xpp.next的内容,这样同样的事情会再次发生again@imsiso我删除了所有if语句,但保留了if(eventType==XmlPullParser.START_标记),为什么它永远不会成为现实,为什么我仍然被困在循环中?让我告诉你,我只使用逻辑,不知道你正在使用的代码。所以试试这个。如果(.start_tag){blabla}else{xpp.next();},那么如果您的条件不为真,那么xpp.next应该将您移动到下一个节点或其他位置,那么不会发生循环。如果这样做可以帮助你更进一步当我在onTaskDone上添加新代码时,onCreateView不会等待onTaskDone,因此视图将是emtpy,下面是新的onTaskDone代码:我知道你为什么会得到一个NPE,我的问题是我如何才能等待AsyncTask,所以我没有得到它。我使用新任务().execte();运行AsyncTask@neX不知道:|只是希望你能在我给你的链接中找到更多。你可以检查一下
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;
    }
}