我想有一些我错过的东西,因为代码在大多数机器上运行正常.任何帮助将不胜感激.
这是调用堆栈.
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(); } }
解决方法
要重新创建错误,关闭活动/应用程序,并快速重新打开页面与片段.您可能需要尝试几次,因为在我的测试中,我不得不在30秒内重新打开应用程序.不同速度设备的时间可能会更慢或更快.
问题是我只显式创建了Fragment(使用new)一次,并保留了对该实例的引用,以便我可以重用它.对此问题的一个简单的解决方案是始终返回Fragment的Fragment的新实例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的具体情况,使用列表< Fragment>持有引用可能与上述相同的问题案例.
ps – 根问题可能与Fragment生命周期有关,并尝试在销毁它时再次使用它.
pps – 另一种重新创建错误的方法是在足够的选项卡之间快速切换,以使Fragment想要被破坏,从缓存中释放一些内存,然后快速返回.默认情况下,FragmentPagerAdapter仅将一个片段缓存到“左”和“右”.因此,根据您的缓存限制,您必须至少有三个选项卡以这种方式重新创建错误.
ppps – 此解决方案修复了用于android.app.Fragment.setUserVisibleHint(Fragment.java:997)的NullPointerException,并且也适用于android.support.v4.app.Fragment.setUserVisibleHint.