我想有一些我错过的东西,因为代码在大多数机器上运行正常.任何帮助将不胜感激.
这是调用堆栈.
- 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.