
我遇到了困扰我好几天的问题.
主活动中有一个VIEwPager,它将3个片段作为制表符片段保存.在第一个片段中有一个ListVIEw,它包含一些视图,其中最重要的是另一个VIEwPager.我想在子VIEwPager中保存一些照片,并在这里使用更多片段.
现在有麻烦:
当第一个Fragment停止时(在屏幕上看到父VIEwPager中的第三个片段)并恢复(用户切换到第二个片段),应用程序崩溃,调试器说:
@H_301_11@java.lang.IllegalArgumentException: No vIEw found for ID 0x7f05008b (com.example.vIEwpager:ID/sub_vIEwpager) for fragment ScreenSlIDePageFragment
我已经使用了getChildFragmentManager(),因为这是nested fragments的情况.
以下是与父VIEwPager中第一个片段对应的列表适配器的关键代码:
@H_301_11@@OverrIDepublic VIEw getVIEw(int position, VIEw convertVIEw, VIEwGroup parent) { int type = getItemVIEwType(position); switch (type) { case TYPE_BANNER: if (convertVIEw == null) { convertVIEw = mBannerVIEw.getBannerVIEw(parent); } mBannerVIEw.update(convertVIEw); break; case TYPE_ITEM: break; } return convertVIEw;}这是mBannerVIEw的代码:
@H_301_11@public class BannerVIEw { private static final displayImageOptions IMAGE_OPTIONS_SCALE_@R_609_4041@ = new displayImageOptions.Builder() .cacheInMemory() .cacheOndisc() .imageScaleType(ImageScaleType.EXACTLY_@R_609_4041@) .build(); private FragmentActivity mActivity; private Fragment mFragment; private List<Banner> mBanners; private ScreenSlIDePagerAdapter mPagerAdapter; private VIEwPager mVIEwPager; public BannerVIEw(FragmentActivity activity, Fragment fragment) { mActivity = activity; mFragment = fragment; } public voID update(VIEw convertVIEw) { mVIEwPager = (VIEwPager) convertVIEw; if (mBanners != null && !mBanners.isEmpty()) { if (mPagerAdapter == null) { mPagerAdapter = new ScreenSlIDePagerAdapter(mFragment.getChildFragmentManager()); mVIEwPager.setAdapter(mPagerAdapter); } } mVIEwPager.setonClickListener(new VIEw.OnClickListener() { @OverrIDe public voID onClick(VIEw v) { if (mOnBannerClickListener != null) { mOnBannerClickListener.onBannerClick(); } } }); } class ScreenSlIDePagerAdapter extends FragmentStatePagerAdapter { public ScreenSlIDePagerAdapter(FragmentManager fm) { super(fm); } @OverrIDe public Fragment getItem(int position) { return new ScreenSlIDePageFragment(mBanners.get(position).getimageUrl()); } @OverrIDe public int getCount() { return mBanners == null ? 0 : mBanners.size(); } } class ScreenSlIDePageFragment extends Fragment { private String mUrl; ScreenSlIDePageFragment(String url) { super(); mUrl = url; } @OverrIDe public VIEw onCreateVIEw(LayoutInflater inflater, VIEwGroup container, Bundle savedInstanceState) { VIEw vIEw = inflater.inflate(R.layout.item_banner, container, false); if (vIEw != null) { ImageVIEw imageVIEw = (ImageVIEw) vIEw.findVIEwByID(R.ID.item_banner_image); imageVIEw.setLayoutParams(new linearLayout.LayoutParams( linearLayout.LayoutParams.MATCH_PARENT, linearLayout.LayoutParams.MATCH_PARENT)); ImageLoader.getInstance().displayImage(mUrl, imageVIEw, IMAGE_OPTIONS_SCALE_@R_609_4041@); } return vIEw; } }}这是详细的错误列表:
@H_301_11@11-10 18:12:19.217 1444-1444/? E/MessageQueue-JNI﹕ java.lang.IllegalArgumentException: No vIEw found for ID 0x7f05008b (com.example.vIEwpager:ID/sub_vIEwpager) for fragment ScreenSlIDePageFragment{428d8ea0 #0 ID=0x7f05008b} at androID.support.v4.app.FragmentManagerImpl.movetoState(FragmentManager.java:919) at androID.support.v4.app.FragmentManagerImpl.movetoState(FragmentManager.java:1104) at androID.support.v4.app.FragmentManagerImpl.movetoState(FragmentManager.java:1086) at androID.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1884) at androID.support.v4.app.Fragment.performActivityCreated(Fragment.java:1514) at androID.support.v4.app.FragmentManagerImpl.movetoState(FragmentManager.java:947) at androID.support.v4.app.FragmentManagerImpl.attachFragment(FragmentManager.java:1280) at androID.support.v4.app.BackStackRecord.run(BackStackRecord.java:672) at androID.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1467) at androID.support.v4.app.FragmentManagerImpl.executePendingTransactions(FragmentManager.java:472) at androID.support.v4.app.FragmentPagerAdapter.finishUpdate(FragmentPagerAdapter.java:141) at androID.support.v4.vIEw.VIEwPager.populate(VIEwPager.java:1068) at androID.support.v4.vIEw.VIEwPager.populate(VIEwPager.java:914) at androID.support.v4.vIEw.VIEwPager$3.run(VIEwPager.java:244) at androID.support.v4.vIEw.VIEwPager.completeScroll(VIEwPager.java:1761) at androID.support.v4.vIEw.VIEwPager.onIntercepttouchEvent(VIEwPager.java:1896) at androID.vIEw.VIEwGroup.dispatchtouchEvent(VIEwGroup.java:1854) at androID.vIEw.VIEwGroup.dispatchtransformedtouchEvent(VIEwGroup.java:2211) at androID.vIEw.VIEwGroup.dispatchtouchEvent(VIEwGroup.java:1912) at androID.vIEw.VIEwGroup.dispatchtransformedtouchEvent(VIEwGroup.java:2211) at androID.vIEw.VIEwGroup.dispatchtouchEvent(VIEwGroup.java:1912) at androID.vIEw.VIEwGroup.dispatchtransformedtouchEvent(VIEwGroup.java:2211) at androID.vIEw.VIEwGroup.dispatchtouchEvent(VIEwGroup.java:1912) at com.androID.internal.policy.impl.PhoneWindow$DecorVIEw.superdispatchtouchEvent(PhoneWindow.java:2228) at com.androID.internal.policy.impl.PhoneWindow.superdispatchtouchEvent(PhoneWindow.java:1471) at androID.app.Activity.dispatchtouchEvent(Activity.java:2424) at com.androID.internal.policy.impl.PhoneWindow$DecorVIEw.dispatchtouchEvent(PhoneWindow.java:2176) at androID.vIEw.VIEw.dispatchPointerEvent(VIEw.java:7571) at androID.vIEw.VIEwRootImpl$VIEwPostImeinputStage.processpointerEvent(VIEwRootImpl.java:3883) at androID.vIEw.VIEwRootImpl$VIEwPostImeinputStage.onProcess(VIEwRootImpl.java:3778) at androID.vIEw.VIEwRootImpl$inputStage.deliver(VIEwRootImpl.java:3379) at androID.vIEw.VIEwRootImpl$inputStage.onDeliverToNext(VIEwRootImpl.java:3429) at androID.vIEw.VIEwRootImpl$inputStage.forward(VIEwRootImpl.java:3398) at androID.vIEw.VIEwRootImpl$AsyncinputStage.forward(VIEwRootImpl.java:3483) at androID.vIEw.VIEwRootImpl$inputStage.apply(VIEwRootImpl.java:3406) at androID.vIEw.VIEwRootImpl$AsyncinputStage.apply(VIEwRootImpl.java:3540) at androID.vIEw.VIEwRootImpl$inputStage.deliver(VIEwRootImpl.java:3379) at androID.vIEw.VIEwRootImpl$inputStage.onDeliverToNext(VIEwRootImpl.java:3429) at androID.vIEw.VIEwRootImpl$inputStage.forward(VIEwRootImpl.java:3398) at androID.vIEw.VIEwRootImpl$inputStage.apply(VIEwRootImpl.java:3406) at androID.vIEw.VIEwRootImpl$inputStage.deliver(VIEwRootImpl.java:3379) at androID.vIEw.VIEwRootImpl.deliverinputEvent(VIEwRootImpl.java:5419) at androID.vIEw.VIEwRootImpl.doProcessinputEvents(VIEwRootImpl.java:5399) at androID.vIEw.VIEwRootImpl.enqueueinputEvent(VIEwRootImpl.java:5370) at androID.vIEw.VIEwRootImpl$WindowinputEventReceiver.oninputEvent(VIEwRootImpl.java:5493) at androID.vIEw.inputEventReceiver.dispatchinputEvent(inputEventReceiver.java:182) at androID.os.MessageQueue.nativePollOnce(Native Method) at androID.os.MessageQueue.next(MessageQueue.java:132) at androID.os.Looper.loop(Looper.java:124) at androID.app.ActivityThread.main(ActivityThread.java:5289) at java.lang解决方法:
更新:
我已经阅读了FragmentManager的源代码,最后得到了真正的原因:当vIEwpager附加到其父级之前,片段想要附加到vIEwpager时会发生此异常.换句话说,在getVIEw()方法返回之前,片段会膨胀.然后调用VIEwPager容器的findVIEwByID()方法,但VIEwPager仍处于分离状态,因此找到null并抛出IllegalArgumentException.
解决方案是创建自定义viewPager并延迟设置适配器:
@H_301_11@public class BannerVIEwPager extends VIEwPager { PagerAdapter mPagerAdapter; @OverrIDe protected voID onAttachedToWindow() { super.onAttachedToWindow(); if (mPagerAdapter != null) { super.setAdapter(mPagerAdapter); mPageIndicator.setVIEwPager(this); } } @OverrIDe public voID setAdapter(PagerAdapter adapter) { } public voID storeAdapter(PagerAdapter pagerAdapter) { mPagerAdapter = pagerAdapter; } public BannerVIEwPager(Context context) { super(context); } public BannerVIEwPager(Context context, AttributeSet attrs) { super(context, attrs); }}在getVIEw()方法中,使用storeAdapter()而不是setAdapter.
以下陈述不正确.上面的话就是实际的原因.
最后我得到了答案.它由两部分组成.
>在父VIEwPager中,我使用FragmentPagerAdapter来保存片段,但现在我使用FragmentStatePagerAdapter.这两者之间的区别可以在这里找到:Difference between FragmentPagerAdapter and FragmentStatePagerAdapter.
简单来说,FragmentPagerAdapter将在片段停止时存储更多信息.在这种情况下,父VIEwPager中的第一个片段会被停止但不会被销毁,而此片段中的视图将被销毁.恢复后,片段尝试重新膨胀所有视图.但是在调用getVIEw()方法并重新创建子VIEwPager之前,子FragmentManager尝试查找子VIEwPager以保存先前存储的片段.因此,出现“java.lang.IllegalArgumentException:找不到ID的视图”.
>用FragmentStatePagerAdapter替换FragmentPagerAdapter后,出现另一个问题.当父片段(父视图中的第一个片段)被停止,销毁和恢复时,子视图抓取器丢失.当选择第一个片段时很快就会发生这种情况,之后很快就会选择第三个片段,最后重新选择第一个片段.
我认为这是androID sdk的一个BUG.灵感来自here和here,我使用一些棘手的方法来解决问题.关键是,当一个父片段被销毁时,字段成员— mChildFragmentManager“最终会破坏内部状态”并且不会被彻底清除.重新创建父片段时,mChildFragmentManager不为null,但子片段在被销毁之后已被销毁,该片段由mChildFragmentManager管理.因此,子VIEwPager在屏幕上显示一个空视图,该视图响应实际上不存在的假片段.有趣的是,在子VIEwPager上直接滑动几次后,子片段和视图再次出现.
这是代码:
父适配器:
@H_301_11@@OverrIDepublic VIEw getVIEw(int position, VIEw convertVIEw, VIEwGroup parent) { if (convertVIEw == null) { convertVIEw = getBannerVIEw(mParent); } mVIEwPager = (VIEwPager) convertVIEw; if (mBanners != null && !mBanners.isEmpty()) { if (mPagerAdapter == null) { FragmentManager childFM = mFragment.getChildFragmentManager(); removeoldFragment(childFM); mPagerAdapter = new ScreenSlIDePagerAdapter(childFM, mBanners); mVIEwPager.setAdapter(mPagerAdapter); } } return convertVIEw;}关键方法:
@H_301_11@ private voID removeoldFragment(FragmentManager fm) { try { FIEld added = fm.getClass().getDeclaredFIEld("mAdded"); added.setAccessible(true); added.set(fm, null); } catch (NoSuchFIEldException e) { throw new RuntimeException(e); } catch (illegalaccessexception e) { throw new RuntimeException(e); } try { FIEld active = fm.getClass().getDeclaredFIEld("mActive"); active.setAccessible(true); active.set(fm, null); } catch (NoSuchFIEldException e) { throw new RuntimeException(e); } catch (illegalaccessexception e) { throw new RuntimeException(e); } } 总结 以上是内存溢出为你收集整理的android – IllegalArgumentException:找不到用于片段的id的视图 – ViewPager中的ViewPager全部内容,希望文章能够帮你解决android – IllegalArgumentException:找不到用于片段的id的视图 – ViewPager中的ViewPager所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)