在 AsyncTask 中使用 ArrayList 填充 ArrayAdapter 时出现 NullPointerException

NullPointerException when populating ArrayAdapter with ArrayList in AsyncTask

我初始化一个ArrayList,

    ArrayList<Episode> episodes = new ArrayList<Episode>(32);

然后通过轮询 RSS 提要异步填充该列表。

当异步调用 onPostExecutes 时,我通过 populateList 剧集:

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            populateList(episodes);
        }

ArrayList 传递到自定义 ArrayAdapterEpisodeAdapter

    public void populateList(ArrayList<Episode> episodes) {
        episodeAdapter = new EpisodeAdapter(getContext(), R.layout.row_episodes, episodes);
        mList.setAdapter(episodeAdapter);
    }

多亏了新的崩溃报告,我开始意识到 这导致 NullPointerExceptions... 的频率非常高(但我似乎无法在本地复制它!)。

根据我当时使用的修复程序,堆栈跟踪看起来像这样:

java.lang.NullPointerException: 
  at android.view.LayoutInflater.from(LayoutInflater.java:234)
  at android.widget.ArrayAdapter.<init>(ArrayAdapter.java:178)
  at android.widget.ArrayAdapter.<init>(ArrayAdapter.java:163)
  at com.workingagenda.democracydroid.Adapters.EpisodeAdapter.<init>(EpisodeAdapter.java:47)
  at com.workingagenda.democracydroid.MainActivity$PodcastFragment.populateList(MainActivity.java:236)
  at com.workingagenda.democracydroid.MainActivity$PodcastFragment$GetAudioFeed.onPostExecute(MainActivity.java:590)
  at com.workingagenda.democracydroid.MainActivity$PodcastFragment$GetAudioFeed.onPostExecute(MainActivity.java:545)

我尝试了很多方法来减少崩溃次数,即在我调用 populateList 之前检查 ArrayList episodes .size() 不是 0(我总是想因为我将它初始化为 32 的长度)。或者,在 populateList 中,我检查第一项是否为 null(例如:

        if (episodes.get(0) != null){
            episodeAdapter = new EpisodeAdapter(getContext(), R.layout.row_episodes, episodes);
            mList.setAdapter(episodeAdapter);
        }

但有时我会得到一个 java.lang.IndexOutOfBoundsException(但有时仍然是 NullPointerException

如果剧集由于某种原因未被异步调用填充,我如何防止应用程序崩溃?

我是否应该在适配器的 getView() 方法中检查 null?

检查第一项是否为 null 没有任何意义吗?或者我应该检查 检查 ArrayList 的 size()

检查数组列表是否为空

 if (!episodes.isEmpty()){
        episodeAdapter = new EpisodeAdapter(getContext(), R.layout.row_episodes, episodes);
        mList.setAdapter(episodeAdapter);
    }

我相信您在 AsyncTask 中收到了空响应。在这种情况下,当您将该值分配给 episodes 变量时,它将变为 null,因此 NullPointerException.

只需在更新 episodes 变量的值之前进行空值检查。

@Override
protected void doInBackground(Void... voids) {
    List<Episode> newEpisodes = yourNetworkCallHere();
    if (newEpisodes != null) {
        episodes = newEpisodes;
    }
}

制作新的适配器时崩溃...

java.lang.NullPointerException: 
    at android.view.LayoutInflater.from(LayoutInflater.java:234)
    at android.widget.ArrayAdapter.<init>(ArrayAdapter.java:178)
    at android.widget.ArrayAdapter.<init>(ArrayAdapter.java:163)
    at com.workingagenda.democracydroid.Adapters.EpisodeAdapter.<init>(EpisodeAdapter.java:47)

这是错误的数据更新方式。


您需要清除列表,然后重新填充,然后通知。

我还建议您 return 来自 doInBackground

的新列表
@Override
protected void doInBackground(List<Episode> episodes) {
    List<Episode> newEpisodes = new ArrayList<>();

    try {
        yourNetworkCallHere();
        newEpisodes.add(...);
    } catch (Exception e) {} 

    return newEpisodes;  // this can't be null 
}

@Override
public void onPostExecute(List<Episode> results) {
    episodes.clear();
    episodes.addAll(results);
    episodeAdapter.notifyDataSetChanged();
} 

如果出现网络错误,则会得到一个空列表,该列表不为空。

如果出现越界异常,那是其他地方的逻辑错误