I have a project (https://github.com/checklist/NestedFragmentsRecycler) with nested fragments. FragmentA is in the MainActivity and contains RecyclerView with an adapter. Each of the items in the adapter will have in return FragmentB. Since I need to give an id for loading FragmentB into position and it needs to be unique, I am generating my own ids. The first fragments are shown fine but unfortunately, the moment I start scrolling, I get an exception that my unique id cannot be found:
W/ResourceType: No package identifier when getting name for resource number 0x00000004 E/FragmentManager: No view found for id 0x4 (unknown) for fragment FragmentB{30cad9b #3 id=0x4} E/FragmentManager: Activity state: D/FragmentManager: Local FragmentActivity 6d29cb6 State: D/FragmentManager: mCreated=truemResumed=true mStopped=false mReallyStopped=false D/FragmentManager:
mLoadersStarted=true D/FragmentManager: Active Fragments in a2d5538: D/FragmentManager: #0: FragmentA{6948911 #0 id=0x7f0b0056} D/FragmentManager: mFragmentId=#7f0b0056 mContainerId=#7f0b0056 mTag=null D/FragmentManager: mState=5 mIndex=0 mWho=android:fragment:0 mBackStackNesting=0 D/FragmentManager:
mAdded=true mRemoving=false mFromLayout=false mInLayout=false D/FragmentManager: mHidden=false mDetached=false mMenuVisible=true mHasMenu=false D/FragmentManager:
mRetainInstance=false mRetaining=false mUserVisibleHint=true D/FragmentManager: mFragmentManager=FragmentManager{a2d5538 in HostCallbacks{327ba76}} D/FragmentManager:
mHost=android.support.v4.app.FragmentActivity$HostCallbacks@327ba76 D/FragmentManager: mArguments=Bundle[{}] D/FragmentManager:
mContainer=android.widget.FrameLayout{ffe8877 V.E...... ........ 128,32-2432,1496 #7f0b0056 app:id/fragmentA} D/FragmentManager:
mView=android.widget.LinearLayout{ffe8ce4 V.E...... ........ 0,0-2304,1464} D/FragmentManager:
mInnerView=android.widget.LinearLayout{ffe8ce4 V.E...... ........ 0,0-2304,1464} D/FragmentManager: Child FragmentManager{aa7a54d in FragmentA{6948911}}: D/FragmentManager: Active Fragments in aa7a54d: D/FragmentManager: #0: FragmentB{44d0802 #0 id=0x1} D/FragmentManager: mFragmentId=#1 mContainerId=#1 mTag=null D/FragmentManager: mState=5 mIndex=0 mWho=android:fragment:0:0 mBackStackNesting=0 D/FragmentManager:
mAdded=true mRemoving=false mFromLayout=false mInLayout=false D/FragmentManager: mHidden=false mDetached=false mMenuVisible=true mHasMenu=false D/FragmentManager:
mRetainInstance=false mRetaining=false mUserVisibleHint=true D/FragmentManager:
mFragmentManager=FragmentManager{aa7a54d in FragmentA{6948911}} D/FragmentManager:
mHost=android.support.v4.app.FragmentActivity$HostCallbacks@327ba76 D/FragmentManager: mParentFragment=FragmentA{6948911 #0 id=0x7f0b0056} D/FragmentManager:
mArguments=Bundle[{TEXT=This is Fragment B:0}] D/FragmentManager:
mContainer=android.widget.FrameLayout{c93513 V.E...... ........ 0,0-800,1464 #1} D/FragmentManager:
mView=android.widget.LinearLayout{3899350 V.E...... ........ 0,0-800,1464} D/FragmentManager:
mInnerView=android.widget.LinearLayout{3899350 V.E...... ........ 0,0-800,1464} D/FragmentManager: Child FragmentManager{c564949 in FragmentB{44d0802}}: D/FragmentManager:
FragmentManager misc state: D/FragmentManager:
mHost=android.support.v4.app.FragmentActivity$HostCallbacks@327ba76 D/FragmentManager:
mContainer=android.support.v4.app.Fragment$1@287a24e D/FragmentManager: mParent=FragmentB{44d0802 #0 id=0x1} D/FragmentManager: mCurState=5 mStateSaved=false mDestroyed=false D/FragmentManager: #1: FragmentB{d880f6f #1 id=0x2} D/FragmentManager:
mFragmentId=#2 mContainerId=#2 mTag=null D/FragmentManager:
mState=5 mIndex=1 mWho=android:fragment:0:1 mBackStackNesting=0 D/FragmentManager: mAdded=true mRemoving=false mFromLayout=false mInLayout=false D/FragmentManager:
mHidden=false mDetached=false mMenuVisible=true mHasMenu=false D/FragmentManager: mRetainInstance=false mRetaining=false mUserVisibleHint=true D/FragmentManager:
mFragmentManager=FragmentManager{aa7a54d in FragmentA{6948911}} D/FragmentManager:
mHost=android.support.v4.app.FragmentActivity$HostCallbacks@327ba76 D/FragmentManager: mParentFragment=FragmentA{6948911 #0 id=0x7f0b0056} D/FragmentManager:
mArguments=Bundle[{TEXT=This is Fragment B:1}] D/FragmentManager:
mContainer=android.widget.FrameLayout{67c947c V.E...... ........ 0,0-800,1464 #2} D/FragmentManager:
mView=android.widget.LinearLayout{c313105 V.E...... ........ 0,0-800,1464} D/FragmentManager:
mInnerView=android.widget.LinearLayout{c313105 V.E...... ........ 0,0-800,1464} D/FragmentManager: Child FragmentManager{cbf955a in FragmentB{d880f6f}}: D/FragmentManager:
FragmentManager misc state: D/FragmentManager:
mHost=android.support.v4.app.FragmentActivity$HostCallbacks@327ba76 D/FragmentManager:
mContainer=android.support.v4.app.Fragment$1@ab0338b D/FragmentManager: mParent=FragmentB{d880f6f #1 id=0x2} D/FragmentManager: mCurState=5 mStateSaved=false mDestroyed=false D/FragmentManager: #2: FragmentB{53c7c68 #2 id=0x3} D/FragmentManager:
mFragmentId=#3 mContainerId=#3 mTag=null D/FragmentManager:
mState=5 mIndex=2 mWho=android:fragment:0:2 mBackStackNesting=0 D/FragmentManager: mAdded=true mRemoving=false mFromLayout=false mInLayout=false D/FragmentManager:
mHidden=false mDetached=false mMenuVisible=true mHasMenu=false D/FragmentManager: mRetainInstance=false mRetaining=false mUserVisibleHint=true D/FragmentManager:
mFragmentManager=FragmentManager{aa7a54d in FragmentA{6948911}} D/FragmentManager:
mHost=android.support.v4.app.FragmentActivity$HostCallbacks@327ba76 D/FragmentManager: mParentFragment=FragmentA{6948911 #0 id=0x7f0b0056} D/FragmentManager:
mArguments=Bundle[{TEXT=This is Fragment B:2}] D/FragmentManager:
mContainer=android.widget.FrameLayout{918d881 V.E...... ........ 0,0-800,1464 #3} D/FragmentManager:
mView=android.widget.LinearLayout{651ad26 V.E...... ........ 0,0-800,1464} D/FragmentManager:
mInnerView=android.widget.LinearLayout{651ad26 V.E...... ........ 0,0-800,1464} D/FragmentManager: Child FragmentManager{4ec7d67 in FragmentB{53c7c68}}: D/FragmentManager:
FragmentManager misc state: D/FragmentManager:
mHost=android.support.v4.app.FragmentActivity$HostCallbacks@327ba76 D/FragmentManager:
mContainer=android.support.v4.app.Fragment$1@b90f714 D/FragmentManager: mParent=FragmentB{53c7c68 #2 id=0x3} D/FragmentManager: mCurState=5 mStateSaved=false mDestroyed=false D/FragmentManager: #3: FragmentB{30cad9b #3 id=0x4} D/FragmentManager:
mFragmentId=#4 mContainerId=#4 mTag=null D/FragmentManager:
mState=1 mIndex=3 mWho=android:fragment:0:3 mBackStackNesting=0 D/FragmentManager: mAdded=true mRemoving=false mFromLayout=false mInLayout=false D/FragmentManager:
mHidden=false mDetached=false mMenuVisible=true mHasMenu=false D/FragmentManager: mRetainInstance=false mRetaining=false mUserVisibleHint=true D/FragmentManager:
mFragmentManager=FragmentManager{aa7a54d in FragmentA{6948911}} D/FragmentManager:
mHost=android.support.v4.app.FragmentActivity$HostCallbacks@327ba76 D/FragmentManager: mParentFragment=FragmentA{6948911 #0 id=0x7f0b0056} D/FragmentManager:
mArguments=Bundle[{TEXT=This is Fragment B:3}] D/FragmentManager:
Added Fragments: D/FragmentManager: #0: FragmentB{44d0802 #0 id=0x1} D/FragmentManager: #1: FragmentB{d880f6f #1 id=0x2} D/FragmentManager: #2: FragmentB{53c7c68 #2 id=0x3} D/FragmentManager: #3: FragmentB{30cad9b #3 id=0x4} D/FragmentManager: FragmentManager misc state: D/FragmentManager:
mHost=android.support.v4.app.FragmentActivity$HostCallbacks@327ba76 D/FragmentManager:
mContainer=android.support.v4.app.Fragment$1@5797bbd D/FragmentManager: mParent=FragmentA{6948911 #0 id=0x7f0b0056} D/FragmentManager: mCurState=5 mStateSaved=false mDestroyed=false D/FragmentManager: Added Fragments: D/FragmentManager: #0: FragmentA{6948911 #0 id=0x7f0b0056} D/FragmentManager: FragmentManager misc state: D/FragmentManager:
mHost=android.support.v4.app.FragmentActivity$HostCallbacks@327ba76 D/FragmentManager:
mContainer=android.support.v4.app.FragmentActivity$HostCallbacks@327ba76 D/FragmentManager: mCurState=5 mStateSaved=false mDestroyed=false I/art: Do partial code cache collection, code=30KB, data=27KB I/art: After code cache collection, code=29KB, data=27KB I/art: Increasing code cache capacity to 128KB D/FragmentManager: View Hierarchy: D/FragmentManager: com.android.internal.policy.DecorView{99b75b2 V.E..... ... 0,0-2560,1800} D/FragmentManager:
android.widget.LinearLayout{eb98903 V.E..... ... 0,0-2560,1704} D/FragmentManager: android.view.ViewStub{8107080 G.E..... ... 0,0-0,0 #10203ef android:id/action_mode_bar_stub} D/FragmentManager:
android.widget.FrameLayout{44716b9 V.E..... ... 0,48-2560,1704} D/FragmentManager:
android.support.v7.widget.ActionBarOverlayLayout{7473afe V.E..... ... 0,0-2560,1656 #7f0b0044 app:id/decor_content_parent} D/FragmentManager:
android.support.v7.widget.ContentFrameLayout{bc1b25f V.E..... ... 0,128-2560,1656 #1020002 android:id/content} D/FragmentManager:
android.widget.RelativeLayout{a4c14ac V.E..... ... 0,0-2560,15287f0b0055 app:id/activity_main} D/FragmentManager: android.widget.FrameLayout{ffe8877 V.E..... ... 128,32-2432,1496
7f0b0056 app:id/fragmentA} D/FragmentManager: android.widget.LinearLayout{ffe8ce4 V.E..... ... 0,0-2304,1464}
D/FragmentManager:
android.support.v7.widget.RecyclerView{9b96575 VFEDH... F.. 0,0-2304,1464 #7f0b0057 app:id/listView} D/FragmentManager:
android.widget.LinearLayout{e58090a V.E..... ... -19,0-781,1464} W/ResourceType: No package identifier when getting name for resource number 0x00000001 D/FragmentManager:
android.widget.FrameLayout{c93513 V.E..... ... 0,0-800,1464 #1} D/FragmentManager:
android.widget.LinearLayout{3899350 V.E..... ... 0,0-800,1464} D/FragmentManager:
android.support.v7.widget.AppCompatTextView{5f9157b V.ED.... ... 0,0-254,38 #7f0b0070 app:id/textView} D/FragmentManager:
android.widget.LinearLayout{7bbcf98 V.E..... ... 781,0-1581,1464} W/ResourceType: No package identifier when getting name for resource number 0x00000002 D/FragmentManager:
android.widget.FrameLayout{67c947c V.E..... ... 0,0-800,1464 #2} D/FragmentManager:
android.widget.LinearLayout{c313105 V.E..... ... 0,0-800,1464} D/FragmentManager:
android.support.v7.widget.AppCompatTextView{bc7e3f1 V.ED.... ... 0,0-254,38 #7f0b0070 app:id/textView} D/FragmentManager:
android.widget.LinearLayout{8f5abd6 V.E..... ... 1581,0-2381,1464} W/ResourceType: No package identifier when getting name for resource number 0x00000003 D/FragmentManager:
android.widget.FrameLayout{918d881 V.E..... ... 0,0-800,1464 #3} D/FragmentManager:
android.widget.LinearLayout{651ad26 V.E..... ... 0,0-800,1464} D/FragmentManager:
android.support.v7.widget.AppCompatTextView{8798e57 V.ED.... ... 0,0-254,38 #7f0b0070 app:id/textView} D/FragmentManager:
android.support.v7.widget.ActionBarContainer{36a4d44 V.ED.... ... 0,0-2560,128 #7f0b0045 app:id/action_bar_container} D/FragmentManager: android.support.v7.widget.Toolbar{e65ce2d V.E..... ... 0,0-2560,1287f0b0046 app:id/action_bar} D/FragmentManager: android.support.v7.widget.AppCompatTextView{9f8af62 V.ED.... ...
48,37-153,91} D/FragmentManager:
android.support.v7.widget.ActionMenuView{c1eb8f3 V.E..... ... 2544,0-2544,128} D/FragmentManager:
android.support.v7.widget.ActionBarContextView{460f9b0 G.E..... ... 0,0-0,0 #7f0b0047 app:id/action_context_bar} D/FragmentManager:
android.view.View{77e2029 V.ED.... ... 0,1704-2560,1800 #1020030 android:id/navigationBarBackground} D/FragmentManager:
android.view.View{7365fae V.ED.... ... 0,0-2560,48 #102002f android:id/statusBarBackground} D/AndroidRuntime: Shutting down VM E/AndroidRuntime: FATAL EXCEPTION: main Process: example.com.demo, PID: 8156 java.lang.IllegalArgumentException: No view found for id 0x4 (unknown) for fragment FragmentB{30cad9b #3 id=0x4} at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1107) at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1295) at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:801) at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1682) at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:541) at android.os.Handler.handleCallback(Handler.java:751) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6119) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) Disconnected from the target VM, address: 'localhost:8616', transport: 'socket'
The 2 main classes are FragmentAAdapter and FragmentB (you can see the other classes if you need, in the git repo):
public class FragmentAAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
FragmentA fragmentA;
Activity activity;
RecyclerView listView;
public FragmentAAdapter(FragmentA fragmentA, Activity activity, RecyclerView listView) {
this.fragmentA = fragmentA;
this.activity = activity;
this.listView = listView;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.fragment_b, parent, false);
RecyclerView.ViewHolder vh = new BoardViewHolder(v, this);
return vh;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof BoardViewHolder){
BoardViewHolder pHolder = (BoardViewHolder)holder;
pHolder.onBindViewHolder(position);
}
}
@Override
public int getItemCount() {
return 10;
}
public class BoardViewHolder extends RecyclerView.ViewHolder {
FragmentAAdapter adapter;
FragmentB fragmentB;
View view;
public BoardViewHolder(View itemView, FragmentAAdapter adapter) {
super(itemView);
this.view = itemView;
this.adapter = adapter;
}
public void onBindViewHolder(int position) {
FragmentManager fm = fragmentA.getChildFragmentManager();
if (fragmentB==null) {
Bundle bundle = new Bundle();
bundle.putString("TEXT", "This is Fragment B:" + position);
fragmentB = FragmentB.getInstance(bundle);
int boardId = generateViewId();
// switch the id of the board to be unique
View board = view.findViewById(R.id.board);
board.setId(boardId);
// now flip fragmentB
FragmentTransaction ft = fm.beginTransaction();
ft.replace(boardId, fragmentB);
ft.commit();
}
}
}
private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
public static int generateViewId() {
for (;;) {
final int result = sNextGeneratedId.get();
// aapt-generated IDs have the high byte nonzero; clamp to the range under that.
int newValue = result + 1;
if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
if (sNextGeneratedId.compareAndSet(result, newValue)) {
return result;
}
}
}
}
and FragmentB:
public class FragmentB extends Fragment {
View root;
Activity activity;
String text;
private TextView textView;
public static FragmentB getInstance(Bundle bundle) {
FragmentB instance = new FragmentB();
instance.setArguments(bundle);
return instance;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activity = (Activity) getActivity();
if (getArguments()!=null) {
text = getArguments().getString("TEXT");
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
root = inflater.inflate(R.layout.row, null, false);
textView = (TextView)root.findViewById(R.id.textView);
textView.setText(text);
return root;
}
}
Full code: https://github.com/checklist/NestedFragmentsRecycler
Thanks!
After a lot of soul searching, I can confirm that it is not possible to generate IDs inside fragments. IF you do so, Android gets confused while rendering the UI and the app crashes.
I have tried this in another project where we generated ids for radio buttons and groups that were dynamically generated and placed within a fragment and same behavior. Two solutions: - do not create programatically so you don't need to generate ids - do not use fragments
User contributions licensed under CC BY-SA 3.0