列表未显示(使用ListFragment和AsyncTask)

时间:2014-05-31 18:12:39

标签: android json android-asynctask android-listfragment

我有一个扩展ListFragment的类(ListMainContentFragment)。其目的是获取JSON数据并使用自定义适配器将其显示在永无止境的列表中。最初,我从我的主要活动中调用了Fragment和AsyncTask,并且在我添加OnScrollListener之前完全正常,因为我需要从OnScrollListener中再次调用AsyncTask。所以我将整个AsyncTask代码移到了ListFragment中。现在,JSON数据将被解析,但不显示列表。出于某种原因,代码认为已显示列表并且正在调用onScroll方法。没有错误被抛出。代码如下。

// List Fragment
public static class ListMainContentFragment extends ListFragment {
  public static final String ARG_DATA_TO_DISPLAY = "parsed_data";
  public static List<Result> currentResults;

  public ListMainContentFragment() {
    // Empty constructor
  }

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    try {
      new GetJobsTask().execute(currentURL).get();
    } catch (InterruptedException | ExecutionException e) {
      e.printStackTrace();
    }
    JobsListAdaptor adapter = new JobsListAdaptor(inflater.getContext(), currentResults);
    setListAdapter(adapter);
//  Integer rSize = adapter.getCount();
//  Log.i("Scroll", "List generating with "+rSize.toString()+" entries");
    return inflater.inflate(R.layout.list_of_jobs, container, false);
  }


  /** Start Handling JSON Data **/

  private class GetJobsTask extends AsyncTask<String, Void, List<Result>> {
    AndroidHttpClient mClient = AndroidHttpClient.newInstance("");

    // Get JSON data, use JSONResponseHandler to parse into List of type Result
    @Override
    protected List<Result> doInBackground(String... url) {
      HttpGet request = new HttpGet(url[0]);
      JSONResponseHandler responseHandler = new JSONResponseHandler();
      try {
        return mClient.execute(request, responseHandler);
      } catch (ClientProtocolException e) {
        e.printStackTrace();
      } catch (IOException e) {
        e.printStackTrace();
      }
      return null;
    }

    // Close the Http client and log the number of results obtained.
    @Override
    protected void onPostExecute(List<Result> results) {
      if (mClient != null)
        mClient.close();
      currentResults = results;
      Log.i("onPostExecute", "There are "+results.size()+" entries");

    }
  }

  /** End Handling JSON Data **/

  public void onViewCreated(View view, Bundle savedInstanceState){
    Log.i("Scroll", "OnViewCreated entered");
    ListView mListView = (ListView) view.findViewById(android.R.id.list);
    Log.i("Scroll", "ListView accessed");
    mListView.setOnScrollListener(new AbsListView.OnScrollListener() {

      @Override
      public void onScrollStateChanged(AbsListView view, int scrollState) {
        // Auto-generated method stub
      }

      @Override
      public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        Log.i("Scroll", "List scrolled");
        switch(view.getId()) {
        case android.R.id.list:
          final Integer lastItem = firstVisibleItem + visibleItemCount;
          if ((lastItem == totalItemCount) & (preLast != lastItem)) {
            Log.i("Scroll", "Last item reached");
            currentURL = "http://api.indeed.com/ads/apisearch?publisher=9616825572719411&v=2&format=json&l=austin&limit=10&start="+lastItem.toString();
            new GetJobsTask().execute(currentURL);
            preLast = lastItem;
          }
        }
      }
    });
  }
}

这是我的Logcat输出:

05-31 17:57:39.245: I/Scroll(2559): OnViewCreated entered
05-31 17:57:39.245: I/Scroll(2559): ListView accessed
05-31 17:57:39.245: I/Scroll(2559): List scrolled
05-31 17:57:39.249: I/Scroll(2559): List scrolled
05-31 17:57:39.261: I/onPostExecute(2559): There are 20 entries

从logcat信息看,即使在onPostExecute完成之前,也会调用onScroll方法。并且只在onPostExecute中,我将AsyncTask的结果分配给变量currentResults。我尝试添加get()方法以强制主线程等待AsyncTask完成,但它似乎没有做我期望它做的事情。

我错过了什么?

2 个答案:

答案 0 :(得分:0)

每次更改适配器内容时,都应调用:

getListAdapter().notifyDataSetChanged();

此外,您不会更改适配器内容本身。尝试:

currentResults.clear();
currentResults.addAll(results);
getListAdapter().notifyDataSetChanged();

答案 1 :(得分:0)

原因是,您在AsyncTask执行之前设置了列表适配器。这意味着列表适配器已设置,但没有任何内容可供显示。

try {
    new GetJobsTask().execute(currentURL).get(); 
} catch (InterruptedException | ExecutionException e) {
    e.printStackTrace();
}
// Because the AsyncTask is handled in another thread, it returns straight away,
// so this is called before the AsyncTask is finished.
JobsListAdaptor adapter = new JobsListAdaptor(inflater.getContext(), currentResults);
setListAdapter(adapter);

相反,将此代码移动到onPostExecute方法中,如下所示:

@Override
protected void onPostExecute(List<Result> results) {
    if (mClient != null) {
        mClient.close();
    }
    JobsListAdaptor adapter = new JobsListAdaptor(inflater.getContext(), results);
    setListAdapter(adapter);
    Log.i("onPostExecute", "There are "+results.size()+" entries");

}