【问题标题】:List not being displayed (using ListFragment and AsyncTask)未显示列表(使用 ListFragment 和 AsyncTask)
【发布时间】:2014-05-31 18:12:38
【问题描述】:

我有一个扩展 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 完成,但它似乎并没有像我预期的那样做。

我错过了什么?

【问题讨论】:

    标签: android json android-asynctask android-listfragment


    【解决方案1】:

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

    getListAdapter().notifyDataSetChanged();
    

    您也没有更改适配器内容本身。试试:

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

    【讨论】:

    • 我进行了更改,但没有任何区别。只有当我滚动到列表末尾但当前没有显示列表时才会到达该行。所以它并没有真正解决我目前的问题。还是谢谢。
    • 我看到了另一个问题。请注意以下行“currentResults = results;”更改存储在片段字段中的列表的引用 - 您根本没有更改适配器内容。尝试清除现有列表,addAll 然后 notifyDataSetChanged。
    【解决方案2】:

    原因是,您在 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");
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多