应用程序恢复时 android.support.v4.app.Fragment.setUserVisibleHint 空指针

2023-11-25

我在片段代码中的应用程序恢复时发生崩溃。我自己从未见过这种崩溃,但我通过 TestFlight 收到了用户返回的崩溃报告。 我想我缺少一些东西,因为代码在大多数机器上运行良好。任何帮助将不胜感激。

这是调用堆栈。

java.lang.NullPointerException
android.support.v4.app.Fragment.setUserVisibleHint in Fragment.java on Line 819
android.support.v4.app.FragmentPagerAdapter.setPrimaryItem in FragmentPagerAdapter.java on Line 130
android.support.v4.view.ViewPager.populate in ViewPager.java on Line 1066
android.support.v4.view.ViewPager.populate in ViewPager.java on Line 914
android.support.v4.view.ViewPager.onMeasure in ViewPager.java on Line 1436
android.view.View.measure in View.java on Line 15323
android.view.ViewGroup.measureChildWithMargins in ViewGroup.java on Line 4924
android.widget.LinearLayout.measureChildBeforeLayout in LinearLayout.java on Line 1421
android.widget.LinearLayout.measureVertical in LinearLayout.java on Line 698
android.widget.LinearLayout.onMeasure in LinearLayout.java on Line 579
android.view.View.measure in View.java on Line 15323
android.view.ViewGroup.measureChildWithMargins in ViewGroup.java on Line 4924
android.widget.FrameLayout.onMeasure in FrameLayout.java on Line 315
android.view.View.measure in View.java on Line 15323
android.support.v4.widget.DrawerLayout.onMeasure in DrawerLayout.java on Line 639
android.view.View.measure in View.java on Line 15323
android.view.ViewGroup.measureChildWithMargins in ViewGroup.java on Line 4924
android.widget.FrameLayout.onMeasure in FrameLayout.java on Line 315
android.view.View.measure in View.java on Line 15323
android.view.ViewGroup.measureChildWithMargins in ViewGroup.java on Line 4924
android.widget.LinearLayout.measureChildBeforeLayout in LinearLayout.java on Line 1421
android.widget.LinearLayout.measureVertical in LinearLayout.java on Line 698
android.widget.LinearLayout.onMeasure in LinearLayout.java on Line 579
android.view.View.measure in View.java on Line 15323
android.view.ViewGroup.measureChildWithMargins in ViewGroup.java on Line 4924
android.widget.FrameLayout.onMeasure in FrameLayout.java on Line 315
com.android.internal.policy.impl.PhoneWindow$DecorView.onMeasure in PhoneWindow.java on Line 2155
android.view.View.measure in View.java on Line 15323
android.view.ViewRootImpl.performMeasure in ViewRootImpl.java on Line 1854
android.view.ViewRootImpl.measureHierarchy in ViewRootImpl.java on Line 1102
android.view.ViewRootImpl.performTraversals in ViewRootImpl.java on Line 1275
android.view.ViewRootImpl.doTraversal in ViewRootImpl.java on Line 1000
android.view.ViewRootImpl$TraversalRunnable.run in ViewRootImpl.java on Line 4218
android.view.Choreographer$CallbackRecord.run in Choreographer.java on Line 725
android.view.Choreographer.doCallbacks in Choreographer.java on Line 555
android.view.Choreographer.doFrame in Choreographer.java on Line 525
android.view.Choreographer$FrameDisplayEventReceiver.run in Choreographer.java on Line 711
android.os.Handler.handleCallback in Handler.java on Line 615
android.os.Handler.dispatchMessage in Handler.java on Line 92
android.os.Looper.loop in Looper.java on Line 137
android.app.ActivityThread.main in ActivityThread.java on Line 4744
java.lang.reflect.Method.invokeNative(Native Method)
java.lang.reflect.Method.invoke in Method.java on Line 511
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run in ZygoteInit.java on Line 786
com.android.internal.os.ZygoteInit.main in ZygoteInit.java on Line 553
dalvik.system.NativeStart.main(Native Method)

首先,我在活动的 OnResume 函数中设置视图寻呼机。

private void initialiseViewPager()
{
    mLoginFragment = new WeakReference<LoginFragment>(new LoginFragment());
    Bundle loginBundle = new Bundle();
    loginBundle.putInt("SpinnerIndex", HDMSLiveSession.getInstance().getSpinnerPosition());
    loginBundle.putString("UserName", HDMSLiveSession.getInstance().getUsername());
    loginBundle.putString("Password", HDMSLiveSession.getInstance().getPassword());
    loginBundle.putInt("Mode", HDMSLiveSession.getInstance().getConnectionMode().ordinal());
    loginBundle.putBoolean("LoggedIn", HDMSLiveSession.getInstance().isLoggedIn());
    loginBundle.putBoolean("Connected", HDMSLiveSession.getInstance().isConnected());
    loginBundle.putString("LoginResult", HDMSLiveSession.getInstance().getLoginResult());
    loginBundle.putString("System", HDMSLiveSession.getInstance().getSystem());
    loginBundle.putInt("code", HDMSLiveSession.getInstance().getAccessCode());
    loginBundle.putLong("bytesSent", mCurrentSB);
    loginBundle.putLong("bytesReceived", mCurrentRB);
    loginBundle.putLong("nbytesSent", mNCurrentSB);
    loginBundle.putLong("nbytesReceived", mNCurrentRB);
    loginBundle.putInt("appid", mApp.getApplicationInfo().uid);
    loginBundle.putString(mWebSocketAddressPreference, mConnect.getWebSocketURL());
    loginBundle.putString(mAPIAddressPreference, mLogin.getLiveServerURL());
    loginBundle.putBoolean(mAutoLoginPreference, mAutoLoginEnabled);
    loginBundle.putBoolean(mAutoConnectPreference, mLogin.isAutoConnectEnabled());
    loginBundle.putInt(mAutoReconnectTimePreference, mConnect.getAutoReconnectTime());
    loginBundle.putInt(mMaxAutoReconnectionAttemptsPreference, mConnect.getMaxAutoReconnectionAttempts());
    loginBundle.putInt(mPingResponseTimePreference, mConnect.getPingResponseTime());
    loginBundle.putInt(mAutoPingTimePreference, mConnect.getAutoPingTime());
    loginBundle.putInt(mCurrentPingPreference, mConnect.getCurrentPing());
    loginBundle.putInt(mAutoReconnectAttemptsPreference, mConnect.getAutoReconnectAttempts());
    loginBundle.putInt(mAutoReconnectTotalAttemptsPreference, mConnect.getAutoReconnectTotalAttempts());
    loginBundle.putBoolean(mPlayListMessagePreference, messageSubscriptionContains(mPlayListMessage));
    loginBundle.putBoolean(mAutoPageSwapPreference, mAutoPageSwap);
    loginBundle.putBoolean(mWifiCheckedPreference, mWifiChecked);
    loginBundle.putBoolean(mAutoWebCheckedPreference, mConnect.isAutoWebChecked());
    loginBundle.putBoolean(mGatewayCheckedPreference, mGatewayChecked);
    loginBundle.putBoolean(mDHS1CheckedPreference, mDNS1Checked);
    loginBundle.putBoolean(mHDMSLiveCheckedPreference, mHDMSLiveChecked);
    loginBundle.putBoolean(mGoogleCheckedPreference, mGoogleChecked);
    loginBundle.putBoolean(mHDMSCheckedPreference, mHDMSChecked);
    loginBundle.putBoolean(mParrotCheckedPreference, mParrotChecked);
    loginBundle.putBoolean(mLocalIPCheckedPreference, mLocalIPChecked);
    loginBundle.putString(mLocalIPPreference, mLocalIP);
    loginBundle.putInt(mMaxImagesFromWebPreference, mMaxImagesFromWeb);
    loginBundle.putInt(mMaxPingAttemptsPreference, mConnect.getMaxPingAttempts());
    loginBundle.putInt(mFailedPingsPreference, mConnect.getFailedPings());
    loginBundle.putBoolean("AutoLogin", mLogin.isAutoLogin());
    loginBundle.putBoolean("wasLoggedIn", HDMSLiveSession.getInstance().wasLoggedIn());
    mLoginFragment.get().setArguments(loginBundle);

    mBAUFragment = new WeakReference<BAUFragment>(new BAUFragment());
    Bundle bauBundle = new Bundle();
    bauBundle.putBoolean("jump", mJumpToCurrent);
    bauBundle.putInt("place", mBAUPosition);
    bauBundle.putBoolean(mBAUExpandedPreference, mBAUExpanded);
    mBAUFragment.get().setArguments(bauBundle);
    mPlayerFragment = new WeakReference<PlayerFragment>(new PlayerFragment());

    mListFragment = new WeakReference<ListFragment>(new ListFragment());
    Bundle listBundle = new Bundle();
    listBundle.putInt(mListModePreference, mListMode);
    mListFragment.get().setArguments(listBundle);

    mSearchFragment = new WeakReference<SearchFragment>(new SearchFragment());
    Bundle searchBundle = new Bundle();
    searchBundle.putInt(mSearchModePreference, mSearchMode);
    searchBundle.putString("searchQueryA", mSearchTextA);
    searchBundle.putString("searchQueryS", mSearchTextS);
    searchBundle.putString("titleLast", mTitleLast);
    searchBundle.putString("artistLast", mArtistLast);
    searchBundle.putString("listLast", mListLast);
    searchBundle.putString("yearLast", mYearLast);
    searchBundle.putString("genreLast", mGenreLast);
    mSearchFragment.get().setArguments(searchBundle);

    mVideoFragment = new WeakReference<VideoFragment>(new VideoFragment());
    Bundle videoBundle = new Bundle();
    videoBundle.putInt(mVideoOutputPreference, mVideoOutput);
    mVideoFragment.get().setArguments(videoBundle);

    List<Fragment> fragments = new Vector<Fragment>();
    fragments.add(mVideoFragment.get());
    fragments.add(mPlayerFragment.get());
    fragments.add(mBAUFragment.get());
    fragments.add(mListFragment.get());
    fragments.add(mSearchFragment.get());
    fragments.add(mLoginFragment.get());
    mPagerAdapter  = new ViewPagerAdapter(getSupportFragmentManager(), fragments);

    mViewPager = (ViewPager)findViewById(R.id.contentViewPager);
    mViewPager.setAdapter(mPagerAdapter);
    mViewPager.setOnPageChangeListener(this);
    mViewPager.setVisibility(View.VISIBLE);

    ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
    if (am.getMemoryClass() >= 32)
        mViewPager.setOffscreenPageLimit(Fragments.Max.ordinal());

    mLastFragment = -1;
    UpdateDisplay();
}

除非是内存堆较小的设备,否则所有片段都会保留。目前有 6 个碎片,当内存中只有 4 个碎片时就会发生崩溃。所以我知道碎片的数量不是问题。我确实尝试将“查看寻呼机”设置保留为默认设置,唯一的区别是速度,因为应用程序需要在用户滑动时加载片段。当应用程序暂停时,所有片段都会被销毁。

@Override
protected void onSaveInstanceState(Bundle outState)
{
    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    if (mLoginFragment.get() != null)
        ft.remove(mLoginFragment.get());
    if (mPlayerFragment.get() != null)
        ft.remove(mPlayerFragment.get());
    if (mBAUFragment.get() != null)
        ft.remove(mBAUFragment.get());
    if (mListFragment.get() != null)
        ft.remove(mListFragment.get());
    if (mSearchFragment.get() != null)
        ft.remove(mSearchFragment.get());
    if (mVideoFragment.get() != null)
        ft.remove(mVideoFragment.get());
    ft.commit();

    mLoginFragment = new WeakReference<LoginFragment>(null);
    mPlayerFragment = new WeakReference<PlayerFragment>(null);
    mBAUFragment = new WeakReference<BAUFragment>(null);
    mListFragment = new WeakReference<ListFragment>(null);
    mSearchFragment = new WeakReference<SearchFragment>(null);
    mVideoFragment = new WeakReference<VideoFragment>(null);
    mPagerAdapter = null;
    mViewPager = null;

    mFragmentsLoaded = 0;
    mLastFragment = -1;
}

这是我的查看寻呼机代码。

package com.hdms.manager.Fragments;

/**
 * Created by bradj on 8/10/13.
 *
 */
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentTransaction;
import android.view.View;

import java.util.List;

public class ViewPagerAdapter extends FragmentPagerAdapter
{
    private final List<Fragment> mFragments;
    FragmentManager mFragmentManager;

    public ViewPagerAdapter(FragmentManager aFragmentManager, List<Fragment> aFragments)
    {
        super(aFragmentManager);

        mFragmentManager = aFragmentManager;
        mFragments = aFragments;
    }

    @Override
    public Fragment getItem(int aPosition)
    {
        return mFragments.get(aPosition);
    }

    @Override
    public long getItemId(int aPosition)
    {
        return aPosition;
    }

    @Override
    public void destroyItem(android.view.ViewGroup aContainer, int aPosition, java.lang.Object aObject)
    {
        if (aPosition <= getCount() && aObject != null)
        {
            FragmentTransaction trans = mFragmentManager.beginTransaction();
            trans.remove((Fragment) aObject);
            trans.commit();
        }
    }

    @Override
    public int getCount()
    {
        return mFragments.size();
    }
}

最后!我现在能够可靠地重现此错误!

要重新创建错误,请关闭活动/应用程序,然后quickly使用片段重新打开页面。您可能需要尝试几次,因为在我的测试中,我必须在大约 30 毫秒内重新打开应用程序。对于不同速度的设备,这个时间可能会更慢或更快。

问题是我只显式创建了片段(使用new)一次,并保留对该实例的引用,以便我可以重用它。解决此问题的一个简单方法是始终返回newFragment 的实例FragmentPagerAdapter.getItem(...), 如下所示。

public class ViewPagerAdapter extends FragmentPagerAdapter {
    ...

    @Override
    public Fragment getItem(int position) {
        switch (position) {
            case 0: return mMyFragment; // Error. Has the edge-case crash.
            case 1: return new MyFragment(); // Works.
            default: return new MyDefaultFragment();
        }
    }
}

对于OP的具体情况,使用List<Fragment>保存引用可能与上面的问题情况相同。

ps - 根本问题可能与片段生命周期以及在其被销毁时尝试再次使用它有关。

pps - 重新创建错误的另一种方法是在足够的选项卡之间快速切换,以便需要销毁片段以从缓存中释放一些内存,然后快速返回到它。默认情况下,FragmentPagerAdapter 只缓存“左”和“右”各一个 Fragment。因此,根据您的缓存限制,您必须至少有三个选项卡才能以这种方式重新创建错误。

ppps - 此解决方案修复了 NullPointerExceptionandroid.app.Fragment.setUserVisibleHint(Fragment.java:997)并且还应该为android.support.v4.app.Fragment.setUserVisibleHint.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

应用程序恢复时 android.support.v4.app.Fragment.setUserVisibleHint 空指针 的相关文章

随机推荐

  • ExpandableListView 显示没有子项的组的指示器

    我正在创建一个ExpandableListView与数据库中的数据 为此 我正在使用CursorTreeAdapter我用一个填充它Cursor包含我从数据库检索的数据的对象 我认为 默认情况下Android会考虑没有孩子的组 不可扩展 但
  • 为什么从 v6 升级到 IdentityModel v7 后出现 IDX20803 错误?

    升级后Microsoft IdentityModel Tokens and System IdentityModel Tokens Jwt to 7 0 0 我收到此错误 IDX20803 无法从 https example com rea
  • 修改本地存储?

    我正在使用 simplecartjs 为在线商店提供支持 它将数据存储在本地存储中 如下所示 SCI 1 quantity 1 id SCI 1 price 20 name Mattamusta teippi size Tyhj SCI 3
  • Android:如何将预览帧保存为jpeg图像?

    我想将预览帧保存为 jpeg 图像 我尝试编写以下代码 public void onPreviewFrame byte data Camera camera if settings isRecording Camera Parameters
  • 使用 TypeScript 和 React 输入 redux 表单 v7

    我有一个简单的由react redux驱动的表单 我希望有一个 form container tsx 和一个 form component tsx 其中 form container tsx 保存所有到 redux 状态的连接减去 Fiel
  • Xcode 界面生成器未检测到 Admob 框架类

    我一直在尝试在我的 iOS 应用程序中实现原生 Google adMob 广告 并遵循 admob 官方教程 https developers google com admob ios native advanced 无论我是手动添加所需的
  • c# 中的 blackmagic SDK

    我正在尝试在 windows7 64x 上使用最新的 SDK 2011 年 6 月 和 C VS 2010 Express 从一张 blackmagic 强度专业卡捕获 720p 我已经成功编译并运行了一个以 YUV 捕获帧的程序 但是 捕
  • 使用 Moq 模拟 nHibernate QueryOver

    测试时 以下行因空引用而失败 var awards session QueryOver Where x gt x BusinessId int business List 我的测试是这样的 var mockQueryOver new Moc
  • MongoDB 子文档嵌套文档验证

    我得到了一份结构如下的文档 我的问题是如何在数据库端进行嵌套部分 角色 验证 我的要求是 角色大小可以为 0 或大于 1 如果创建了角色 则存在角色的 name 和created by id 123456 name User Name ro
  • bootstrap-table-filter-control 扩展在 bootstrap-table 中不起作用

    I use 引导表并想使用表过滤器控制扩大 在this您可以通过示例了解如何使用此扩展 当我想将此扩展用于更多列时 它不起作用 在我的示例中 过滤器仅适用于一列 jsfiddle html table class table table s
  • 如何使用GDI+绘制ARGB位图?

    我有有效的HBITMAP的句柄ARGB类型 如何使用它来绘制GDI 我尝试过方法 graphics DrawImage Bitmap FromHBITMAP m hBitmap NULL 0 0 但它不使用 Alpha 通道 我有工作样本
  • Angular js 缩小后出现错误。错误:[$injector:unpr] 未知提供者:eProvider <- e <- makeErrorsDirective

    我使用 Gulp 来缩小整个 js 文件 缩小后 我收到如下错误 injector unpr Unknown provider eProvider lt e lt makeErrorsDirective 我的控制器文件中有一个自定义指令 v
  • 从 Common Lisp 中的嵌套循环返回

    我正在尝试将此 Python 代码转换为 Common Lisp for a in xrange 1 1000 for b in xrange a 1000 c a 2 b 2 0 5 s a b c if s 1000 return a
  • 并行运行单元测试

    有谁知道是否有办法在 Visual Studio 中并行运行不同的 测试方法 NUnit 2 5有一个选项支持并行运行单元测试 这与 VS 内置的单元测试框架无关 但可以使用正确的插件在 VS 内运行 NUnit 测试
  • 如何在 MKAnnotations 上方显示 MKOverlay?

    我正在尝试使用MKOverlay 特别是MKPolyline 在地图上显示路线 但是 我需要路线显示在我现有的引脚上方 自定义MKAnnotationViews 有没有好的方法可以带MKPolyline到引脚上方的前面 研究注释层可能会很有
  • 禁用 NSOutputStream 的 Nagle 算法

    我正在使用创建多人游戏MPCF 您可以使用 iPhone 在 iPad 上控制宇宙飞船 我在随机时间和间隔内经历了各种程度的滞后和延迟以及缓冲 暂停 现在已登陆苹果技术问答 NW26讨论禁用 Nagle 算法的论文 我正在尝试 但我的程序不
  • 如何在 jQuery 中动态添加锚点/href

    我是 jQuery 新手 我正在尝试将所有手机类转换为带有 h ref 的锚点 我拥有的 div class phone 111 111 1111 div div class phone 666 555 4444 div 我想要的是 div
  • 将项目添加到 ember-data 的过滤结果中

    我有一个DS Store它使用DS RESTAdapter and a ChatMessage对象定义如下 App ChatMessage DS Model extend contents DS attr string roomId DS
  • 如何使用c停止终端中的回显?

    假设我正在使用 fgets 读取字符串 并且我想防止该字符串的字符在终端内部回显 没有 bash 技巧 我怎样才能做到这一点 假设您在 POSIX 兼容操作系统上运行 您需要使用本地控制终端 termios 标志stdin using tc
  • 应用程序恢复时 android.support.v4.app.Fragment.setUserVisibleHint 空指针

    我在片段代码中的应用程序恢复时发生崩溃 我自己从未见过这种崩溃 但我通过 TestFlight 收到了用户返回的崩溃报告 我想我缺少一些东西 因为代码在大多数机器上运行良好 任何帮助将不胜感激 这是调用堆栈 java lang NullPo