Android:升级支持库后使用 findFragmentById() 出现 NullPointerException
Android: NullPointerException using findFragmentById() after ugrading support libraries
我刚刚将一个旧的 Android 项目从 Eclipse 切换到 Android Studio,在这个过程中我从旧的支持库版本 19.0.1
更新到 22.2.0
。在此之后,我在以前的工作代码中遇到了一些错误。我下载了中间的所有 SDK 并检查了错误首先出现的位置,它似乎是 21.1.0
及更高版本。我查看了那个版本的 release notes,但找不到任何感兴趣的内容。
我的错误是我在这里得到 NullPointerException
。请注意,此方法是 Activity
的一部分,而不是父 Fragment
.
public synchronized void onRecipesFiltered(ArrayList<Recipe> filteredRecipes)
{
FilteredRecipesListFragment filteredRecipesListFragment = (FilteredRecipesListFragment)
getSupportFragmentManager().findFragmentById(R.id.mm_filtered_recipes_list_fragment);
// filteredRecipesListFragment becomes null
filteredRecipesListFragment.onRecipesFiltered(filteredRecipes);
}
我得到的 Fragment
是一个 ListFragment
,它是 XML 文件的一部分,该文件在应用程序启动时被膨胀。似乎这个 ListFragment
在 inflation 期间添加到 FragmentManager
内部 父 Fragment
。这可能就是为什么我在获取 Activity
的 FragmentManager
时得到空指针的原因。因此,我的问题是:
如何在 Activity
中获取 ListFragment
?是否需要保留对父 Fragment
的引用以通过其 FragmentManager
获取 ListFragment
?在 FragmentPagerAdapter#getItem()
中返回 new MyFragment()
时,父 Fragment
被夸大了,没有其他地方,因此在 Activity
.[=38= 中获得正确的引用有点棘手]
还有一件事需要注意:我看到一些消息告诉我应该更新到 JDK 1.7
,我做到了 (OpenJDK 1.7
)。我不记得我做了什么,但在 "External Libraries" 下我看到 <1.7> (/usr/lib/jvm/java-1.7.0-openjdk-amd64)
。不确定这是否重要。
尝试替换:
FilteredRecipesListFragment filteredRecipesListFragment = (FilteredRecipesListFragment)
getSupportFragmentManager().findFragmentById(R.id.mm_filtered_recipes_list_fragment);
至:
FilteredRecipesListFragment filteredRecipesListFragment = (FilteredRecipesListFragment)
getChildFragmentManager().findFragmentById(R.id.mm_filtered_recipes_list_fragment);
在 getChildFragmentManager() documentation
上阅读有关 getChildFragmentManager()
的更多信息
我按照 this 的回答解决了问题。似乎不太可能以一种漂亮的方式从 ViewPager
中获取 Fragment
s,因此它们必须在创建后作为参考保存,并在需要时获取。
我把答案的主要代码复制在这里,以防万一。主要思想是将 Fragment
保留在 SparseArray
中,以便在需要时获取它们。它们必须在 creation/before 删除后插入和删除。
public class MyPagerAdapter extends FragmentStatePagerAdapter {
SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();
public MyPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public int getCount() {
return ...;
}
@Override
public Fragment getItem(int position) {
return MyFragment.newInstance(...);
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
return fragment;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
super.destroyItem(container, position, object);
}
public Fragment getRegisteredFragment(int position) {
return registeredFragments.get(position);
}
}
完成此操作后,我可以使用 getChildFragmentManager()
将我的方法重写为以下内容,如@Skizo 所述:
public synchronized void onRecipesFiltered(ArrayList<Recipe> filteredRecipes)
{
MyPagerAdapter myPagerAdapter = (MyPagerAdapter) mMyViewPager.getAdapter();
FilteredRecipesFragment filteredRecipesFragment = (FilteredRecipesFragment)
myPagerAdapter.getRegisteredFragment(PagerConstants.PAGE_FILTER_RECIPES);
if (filteredRecipesFragment == null)
{
// Fragments that has not yet been instantiated will be returned as null. Cannot do anything about it.
// Should be fairly unlikely. See:
//
return;
}
FilteredRecipesListFragment listFragment = (FilteredRecipesListFragment)
filteredRecipesFragment.getChildFragmentManager().findFragmentById(R.id.mm_filtered_recipes_list_fragment);
listFragment.onRecipesFiltered(filteredRecipes);
}
我刚刚将一个旧的 Android 项目从 Eclipse 切换到 Android Studio,在这个过程中我从旧的支持库版本 19.0.1
更新到 22.2.0
。在此之后,我在以前的工作代码中遇到了一些错误。我下载了中间的所有 SDK 并检查了错误首先出现的位置,它似乎是 21.1.0
及更高版本。我查看了那个版本的 release notes,但找不到任何感兴趣的内容。
我的错误是我在这里得到 NullPointerException
。请注意,此方法是 Activity
的一部分,而不是父 Fragment
.
public synchronized void onRecipesFiltered(ArrayList<Recipe> filteredRecipes)
{
FilteredRecipesListFragment filteredRecipesListFragment = (FilteredRecipesListFragment)
getSupportFragmentManager().findFragmentById(R.id.mm_filtered_recipes_list_fragment);
// filteredRecipesListFragment becomes null
filteredRecipesListFragment.onRecipesFiltered(filteredRecipes);
}
我得到的 Fragment
是一个 ListFragment
,它是 XML 文件的一部分,该文件在应用程序启动时被膨胀。似乎这个 ListFragment
在 inflation 期间添加到 FragmentManager
内部 父 Fragment
。这可能就是为什么我在获取 Activity
的 FragmentManager
时得到空指针的原因。因此,我的问题是:
如何在 Activity
中获取 ListFragment
?是否需要保留对父 Fragment
的引用以通过其 FragmentManager
获取 ListFragment
?在 FragmentPagerAdapter#getItem()
中返回 new MyFragment()
时,父 Fragment
被夸大了,没有其他地方,因此在 Activity
.[=38= 中获得正确的引用有点棘手]
还有一件事需要注意:我看到一些消息告诉我应该更新到 JDK 1.7
,我做到了 (OpenJDK 1.7
)。我不记得我做了什么,但在 "External Libraries" 下我看到 <1.7> (/usr/lib/jvm/java-1.7.0-openjdk-amd64)
。不确定这是否重要。
尝试替换:
FilteredRecipesListFragment filteredRecipesListFragment = (FilteredRecipesListFragment)
getSupportFragmentManager().findFragmentById(R.id.mm_filtered_recipes_list_fragment);
至:
FilteredRecipesListFragment filteredRecipesListFragment = (FilteredRecipesListFragment)
getChildFragmentManager().findFragmentById(R.id.mm_filtered_recipes_list_fragment);
在 getChildFragmentManager() documentation
上阅读有关getChildFragmentManager()
的更多信息
我按照 this 的回答解决了问题。似乎不太可能以一种漂亮的方式从 ViewPager
中获取 Fragment
s,因此它们必须在创建后作为参考保存,并在需要时获取。
我把答案的主要代码复制在这里,以防万一。主要思想是将 Fragment
保留在 SparseArray
中,以便在需要时获取它们。它们必须在 creation/before 删除后插入和删除。
public class MyPagerAdapter extends FragmentStatePagerAdapter {
SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();
public MyPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public int getCount() {
return ...;
}
@Override
public Fragment getItem(int position) {
return MyFragment.newInstance(...);
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
return fragment;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
super.destroyItem(container, position, object);
}
public Fragment getRegisteredFragment(int position) {
return registeredFragments.get(position);
}
}
完成此操作后,我可以使用 getChildFragmentManager()
将我的方法重写为以下内容,如@Skizo 所述:
public synchronized void onRecipesFiltered(ArrayList<Recipe> filteredRecipes)
{
MyPagerAdapter myPagerAdapter = (MyPagerAdapter) mMyViewPager.getAdapter();
FilteredRecipesFragment filteredRecipesFragment = (FilteredRecipesFragment)
myPagerAdapter.getRegisteredFragment(PagerConstants.PAGE_FILTER_RECIPES);
if (filteredRecipesFragment == null)
{
// Fragments that has not yet been instantiated will be returned as null. Cannot do anything about it.
// Should be fairly unlikely. See:
//
return;
}
FilteredRecipesListFragment listFragment = (FilteredRecipesListFragment)
filteredRecipesFragment.getChildFragmentManager().findFragmentById(R.id.mm_filtered_recipes_list_fragment);
listFragment.onRecipesFiltered(filteredRecipes);
}