在App断点续传android.support.v4.app.Fragment.setUserVisibleHint空指针 [英] android.support.v4.app.Fragment.setUserVisibleHint null pointer on app resuming

查看:585
本文介绍了在App断点续传android.support.v4.app.Fragment.setUserVisibleHint空指针的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我得到在碎片code中的应用程序的恢复崩溃。我从来没有见过这种崩溃自己,但我已通过TestFlight收到崩溃报告回用户的。 我想有一些东西,我很想念为code正常工作的大多数机器。任何帮助将大大AP preciated。

下面是调用堆栈。

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

首先,我在活动OnResume功能设置视图寻呼机。

 私人无效initialiseViewPager()
{
    mLoginFragment =新的WeakReference< LoginFragment>(新LoginFragment());
    捆绑loginBundle =新包();
    loginBundle.putInt(SpinnerIndex,HDMSLiveSession.getInstance()getSpinnerPosition());
    loginBundle.putString(用户名,HDMSLiveSession.getInstance()getUsername());
    loginBundle.putString(密码,HDMSLiveSession.getInstance()getPassword来());
    loginBundle.putInt(模式,HDMSLiveSession.getInstance()getConnectionMode()序号());
    loginBundle.putBoolean(的loggedIn,HDMSLiveSession.getInstance()isLoggedIn());
    loginBundle.putBoolean(保持通话,HDMSLiveSession.getInstance()isConnected());
    loginBundle.putString(LoginResult,HDMSLiveSession.getInstance()getLoginResult());
    loginBundle.putString(系统,HDMSLiveSession.getInstance()getSystem());
    loginBundle.putInt(code,HDMSLiveSession.getInstance()GetAccess的code());
    loginBundle.putLong(bytesSent,mCurrentSB);
    loginBundle.putLong(与BytesReceived,mCurrentRB);
    loginBundle.putLong(nbytesSent,mNCurrentSB);
    loginBundle.putLong(nbytesReceived,mNCurrentRB);
    loginBundle.putInt(APPID,mApp.getApplicationInfo()的uid);
    loginBundle.putString(mWebSocketAddress preference,mConnect.getWebSocketURL());
    loginBundle.putString(mAPIAddress preference,mLogin.getLiveServerURL());
    loginBundle.putBoolean(mAutoLogin preference,mAutoLoginEnabled);
    loginBundle.putBoolean(mAutoConnect preference,mLogin.isAutoConnectEnabled());
    loginBundle.putInt(mAutoReconnectTime preference,mConnect.getAutoReconnectTime());
    loginBundle.putInt(mMaxAutoReconnectionAttempts preference,mConnect.getMaxAutoReconnectionAttempts());
    loginBundle.putInt(mPingResponseTime preference,mConnect.getPingResponseTime());
    loginBundle.putInt(mAutoPingTime preference,mConnect.getAutoPingTime());
    loginBundle.putInt(mCurrentPing preference,mConnect.getCurrentPing());
    loginBundle.putInt(mAutoReconnectAttempts preference,mConnect.getAutoReconnectAttempts());
    loginBundle.putInt(mAutoReconnectTotalAttempts preference,mConnect.getAutoReconnectTotalAttempts());
    loginBundle.putBoolean(mPlayListMessage preference,messageSubscriptionContains(mPlayListMessage));
    loginBundle.putBoolean(mAutoPageSwap preference,mAutoPageSwap);
    loginBundle.putBoolean(mWifiChecked preference,mWifiChecked);
    loginBundle.putBoolean(mAutoWebChecked preference,mConnect.isAutoWebChecked());
    loginBundle.putBoolean(mGa​​tewayChecked preference,mGatewayChecked);
    loginBundle.putBoolean(mDHS1Checked preference,mDNS1Checked);
    loginBundle.putBoolean(mHDMSLiveChecked preference,mHDMSLiveChecked);
    loginBundle.putBoolean(mGoogleChecked preference,mGoogleChecked);
    loginBundle.putBoolean(mHDMSChecked preference,mHDMSChecked);
    loginBundle.putBoolean(mParrotChecked preference,mParrotChecked);
    loginBundle.putBoolean(mLocalIPChecked preference,mLocalIPChecked);
    loginBundle.putString(mLocalIP preference,mLocalIP);
    loginBundle.putInt(mMaxImagesFromWeb preference,mMaxImagesFromWeb);
    loginBundle.putInt(mMaxPingAttempts preference,mConnect.getMaxPingAttempts());
    loginBundle.putInt(mFailedPings preference,mConnect.getFailedPings());
    loginBundle.putBoolean(自动登录,mLogin.isAutoLogin());
    loginBundle.putBoolean(wasLoggedIn,HDMSLiveSession.getInstance()wasLoggedIn());
    。mLoginFragment.get()setArguments(loginBundle);

    mBAUFragment =新的WeakReference< BAUFragment>(新BAUFragment());
    捆绑bauBundle =新包();
    bauBundle.putBoolean(跳,mJumpToCurrent);
    bauBundle.putInt(地方,mBAUPosition);
    bauBundle.putBoolean(mBAUExpanded preference,mBAUExpanded);
    。mBAUFragment.get()setArguments(bauBundle);
    mPlayerFragment =新的WeakReference< PlayerFragment>(新PlayerFragment());

    mListFragment =新的WeakReference< ListFragment>(新ListFragment());
    捆绑listBundle =新包();
    listBundle.putInt(mListMode preference,mListMode);
    。mListFragment.get()setArguments(listBundle);

    mSearchFragment =新的WeakReference< SearchFragment>(新SearchFragment());
    捆绑searchBundle =新包();
    sea​​rchBundle.putInt(mSearchMode preference,mSearchMode);
    sea​​rchBundle.putString(searchQueryA,mSearchTextA);
    sea​​rchBundle.putString(searchQueryS,mSearchTextS);
    sea​​rchBundle.putString(titleLast,mTitleLast);
    sea​​rchBundle.putString(artistLast,mArtistLast);
    sea​​rchBundle.putString(listLast,mListLast);
    sea​​rchBundle.putString(yearLast,mYearLast);
    sea​​rchBundle.putString(genreLast,mGenreLast);
    。mSearchFragment.get()setArguments(searchBundle);

    mVideoFragment =新的WeakReference< VideoFragment>(新VideoFragment());
    捆绑videoBundle =新包();
    videoBundle.putInt(mVideoOutput preference,mVideoOutput);
    。mVideoFragment.get()setArguments(videoBundle);

    名单<片断>碎片=新矢量<片断>();
    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 =新ViewPagerAdapter(getSupportFragmentManager(),片段);

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

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

    mLastFragment = -1;
    UpdateDisplay();
}
 

所有的碎片都保留,除非它是一个小内存堆的设备。目前,有6个片段,坠机是其中只有4在内存中存在的时候有。所以,我知道,碎片的数​​量是没有问题的。我也试着离开查看传呼机设置在默认情况下,唯一的区别是速度,应用程序需要加载片段用户刷卡时研究。当应用程序被暂停所有的碎片被摧毁。

  @覆盖
保护无效的onSaveInstanceState(包outState)
{
    FragmentTransaction英尺= getSupportFragmentManager()的BeginTransaction()。
    如果(mLoginFragment.get()!= NULL)
        ft.remove(mLoginFragment.get());
    如果(mPlayerFragment.get()!= NULL)
        ft.remove(mPlayerFragment.get());
    如果(mBAUFragment.get()!= NULL)
        ft.remove(mBAUFragment.get());
    如果(mListFragment.get()!= NULL)
        ft.remove(mListFragment.get());
    如果(mSearchFragment.get()!= NULL)
        ft.remove(mSearchFragment.get());
    如果(mVideoFragment.get()!= NULL)
        ft.remove(mVideoFragment.get());
    ft.commit();

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

    mFragmentsLoaded = 0;
    mLastFragment = -1;
}
 

下面是我的看法呼机code。

 包com.hdms.manager.Fragments;

/ **
 *在13年8月10日创建于bradj。
 *
 * /
进口android.support.v4.app.Fragment;
进口android.support.v4.app.FragmentManager;
进口android.support.v4.app.FragmentPagerAdapter;
进口android.support.v4.app.FragmentTransaction;
进口android.view.View;

进口的java.util.List;

公共类ViewPagerAdapter扩展FragmentPagerAdapter
{
    私人最终名单,其中,片断> mFragments;
    FragmentManager mFragmentManager;

    公共ViewPagerAdapter(FragmentManager aFragmentManager,名单,其中,片断> aFragments)
    {
        超(aFragmentManager);

        mFragmentManager = aFragmentManager;
        mFragments = aFragments;
    }

    @覆盖
    公共片段的getItem(INT。负责)
    {
        返回mFragments.get(。负责);
    }

    @覆盖
    众长getItemId(INT。负责)
    {
        返回。负责;
    }

    @覆盖
    公共无效destroyItem(android.view.ViewGroup的aContainer,INT。负责,java.lang.Object中aObject)
    {
        如果(。负责&其中; = getCount将()&安培;&安培;!aObject =空)
        {
            FragmentTransaction反式= mFragmentManager.beginTransaction();
            trans.remove((片段)aObject);
            trans.commit();
        }
    }

    @覆盖
    公众诠释getCount将()
    {
        返回mFragments.size();
    }
}
 

解决方案

终于来了!我现在可以可靠地重现这个错误!

要重现错误,关闭活动/应用程序,并与片段快速重新打开页面。您可能需要尝试几次,因为在我的测试中,我不得不在大约30毫秒重新打开该应用程序。这个时候可能会比较慢或更快的速度不同的设备。

问题是,我只明确创建的片段(使用)一次,并保持一个引用实例,这样我可以重新使用它。一个简单的解决这个问题的方法是总是返回片段的新实例 FragmentPagerAdapter.getItem(...),如下所示。

 公共类ViewPagerAdapter扩展FragmentPagerAdapter {
    ...

    @覆盖
    公共片段的getItem(INT位置){
        开关(位置){
            情况下0:返回mMyFragment; // 错误。有边缘的崩溃。
            案例1:返回新MyFragment(); // 作品。
            默认值:返回新MyDefaultFragment();
        }
    }
}
 

有关业务方案的特定情况下,使用名单,其中,片断> 持有引用可能是同样的问题,如果上面

PS - 问题的根源可能有事情做与片段的生命周期,并试图再次使用它,而它被破坏

PPS - 另一种方式来重现错误是足够的标签页之间快速切换,这样的片段要被销毁,以释放从缓存中一些内存,然后迅速回去吧。默认情况下,FragmentPagerAdapter只能缓存一个片段,以左和右。所以,这取决于你的缓存限制,你必须至少有三个标签来重新创建错误这样的。

公私伙伴关系 - 这种解决方案修复NullPointerException异常为 android.app.Fragment.setUserVisibleHint(Fragment.java:997),也应适​​用于安卓.support.v4.app.Fragment.setUserVisibleHint

I am getting a crash on the resume of the app in the fragments code. I have never seen this crash myself but I have received crash reports back from users via TestFlight. I guess there is something that I am missing as the code works fine on most machines. Any help would be greatly appreciated.

Here is the call stack.

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)

First I set up the view pager in the OnResume function of the activity.

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

All fragments are retained unless it is a device with a small memory heap. Currently there are 6 fragments, the crash was occuring when there where only 4 in memory. So I know that the number of fragments isn't the problem. I did try leaving the View Pagers settings at the default, the only difference is speed as the app needs to load fragments in when the user swipes. All the fragments are destroyed when the app is paused.

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

Here is my view pager code.

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

解决方案

Finally! I'm now able to reliably recreate this error!

To recreate error, close activity/app, and quickly reopen page with fragment. You may have to try a few times because in my tests I had to reopen the app within about 30ms. This time may be slower or faster for different speed devices.

The problem was that I only explicitly created the Fragment (using new) once, and kept a reference to that instance so that I could reuse it. One simple fix to this problem is to always return a new instance of the Fragment the FragmentPagerAdapter.getItem(...), as shown below.

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

For the OP's specific case, using the List<Fragment> to hold references is likely the same problem case as above.

ps - The root problem likely has something to do with the Fragment lifecycle and trying to use it again while it's being destroyed.

pps - Another way to recreate error is to quickly switch between enough tabs so that the Fragment wants to be destroyed to free some memory from cache, then quickly go back to it. By default, the FragmentPagerAdapter only caches one Fragment to the "left" and "right". So, depending on your cache limit, you will have to have at least three tabs to recreate the error this way.

ppps - This solution fixes the NullPointerException for android.app.Fragment.setUserVisibleHint(Fragment.java:997) and should also work for android.support.v4.app.Fragment.setUserVisibleHint.

这篇关于在App断点续传android.support.v4.app.Fragment.setUserVisibleHint空指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆