Android.support.v4.app.Fragment.setUserVisibleHint null указатель на возобновление приложения

Я получаю крах в резюме приложения в коде фрагментов. Я никогда не видел эту ошибку самостоятельно, но я получил отчеты о сбоях от пользователей через 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 в памяти. Поэтому я знаю, что количество фрагментов не является проблемой. Я попытался оставить настройки View Pagers по умолчанию, единственное различие – скорость, так как приложение должно загружать фрагменты, когда пользователь выполняет поиск. Все фрагменты уничтожаются, когда приложение приостановлено.

 @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(); } } 

Solutions Collecting From Web of "Android.support.v4.app.Fragment.setUserVisibleHint null указатель на возобновление приложения"

В заключение! Теперь я могу надежно воссоздать эту ошибку!

Чтобы воссоздать ошибку, закрыть активность / приложение и быстро открыть страницу с фрагментом. Возможно, вам придется попробовать несколько раз, потому что в моих тестах мне пришлось повторно открывать приложение в течение примерно 30 мс. Это время может быть медленнее или быстрее для разных устройств скорости.

Проблема заключалась в том, что я только однажды создал фрагмент (используя new ) один раз и сохранил ссылку на этот экземпляр, чтобы я мог его повторно использовать. Одно простое решение этой проблемы – всегда возвращать new экземпляр фрагмента 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 только кэширует один фрагмент на «левый» и «правый». Таким образом, в зависимости от вашего ограничения кэша вам придется иметь как минимум три вкладки, чтобы воссоздать ошибку таким образом.

Ppps – это решение исправляет NullPointerException для android.app.Fragment.setUserVisibleHint(Fragment.java:997) а также должно работать для android.support.v4.app.Fragment.setUserVisibleHint .

Я не думаю, что для ответа на ваш вопрос достаточно информации. Я хотел бы видеть точную строку вашего кода, вызывающую нулевой указатель.

В любом случае, просматривая свой код, единственный виновник, который я могу догадаться, может вызвать проблемы: getItem (), где вы передаете значение null:

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

Вы должны просто вернуть mFragments.get (aPosition), поскольку у вас уже есть overriden getCount ().