2016-11-07 92 views
0

我有一個嵌套片段的項目(https://github.com/checklist/NestedFragmentsRecycler)。 FragmentA位於MainActivity中,幷包含帶有適配器的RecyclerView。適配器中的每個項目都會返回FragmentB。由於我需要提供一個用於將FragmentB加載到位的ID,並且它需要是唯一的,所以我生成了我自己的ID。第一個片段顯示正常,但不幸的是,我開始滾動的那一刻,我得到一個例外,我的唯一的ID不能被發現:使用RecyclerView的Android嵌套片段

W /的ResourceType:資源獲取的名字時,沒有包裝標識 數0x00000004 E/FragmentManager:沒有爲ID 0x4 (未知)的片段FragmentB {30cad9b#3 id = 0x4}找到視圖E/FragmentManager: 活動狀態:D/FragmentManager:本地FragmentActivity 6d29cb6 狀態:D/FragmentManager:mCreated = truemResumed = true mStopped = false mReallyStopped = false D/FragmentManager:
mLoadersStarted = true D/FragmentManager:a2d5538中的活動片段: d/FragmentManager:#0:FragmentA {6948911#0的id = 0x7f0b0056} d/FragmentManager:mFragmentId =#7f0b0056 mContainerId =#7f0b0056 MTAG =空d/FragmentManager:mState = 5 MINDEX = 0 mWho =機器人:片段:0 mBackStackNesting = 0 d/FragmentManager:
mAdded =真mRemoving =假mFromLayout =假mInLayout =假 d/FragmentManager:mHidden =假mDetached =假 mMenuVisible =真mHasMenu =假d/FragmentManager:
mRetainInstance =假mRetaining = false mUserVisibleHint = true D/FragmentManager:mFragmentManager = FragmentManager {a2d5538在 HostCallbacks {327ba76}} D/FragmentManager:
mHost = and [email protected] D/FragmentManager:mArguments = Bundle [{}] D/FragmentManager:
mContainer = android.widget.FrameLayout {ffe8877 VE ..... .... ... 128,32-2432,1496#7f0b0056 app:id/fragmentA} D/FragmentManager:
mView = android.widget.LinearLayout {ffe8ce4 VE ..... ........ 0,0-2304,1464} D/FragmentManager:
mInnerView = android.widget.LinearLayout {ffe8ce4 VE ..... ........ 0,0-2304,1464} D/FragmentManager:子片段管理器{aa7a54d in FragmentA {6948911}}:D/FragmentManager: 中的活動片段aa7a54d:D /片段管理器:#0:FragmentB {44d0802#0 id = 0x1} d/FragmentManager:mFragmentId =#1 mContainerId =#1 MTAG =空d/FragmentManager:mState = 5 MINDEX = 0 mWho =機器人:片段:0:0 mBackStackNesting = 0 d/FragmentManager:
mAdded =真mRemoving =假mFromLayout =假mInLayout =假 d/FragmentManager:mHidden =假mDetached =假 mMenuVisible =真mHasMenu =假d/FragmentManager:
mRetainInstance =假mRetaining =假mUserVisibleHint =真 d/FragmentManager:
mFragmentManager = FragmentManager {aa7a54d in FragmentA {6948911}} D/FragmentManager:
mHost = android.support.v4.app.FragmentActivity $ HostCallbac KS @ 327ba76 d/FragmentManager:mParentFragment = FragmentA {6948911#0 ID = 0x7f0b0056} d/FragmentManager:
mArguments =捆綁[{TEXT =這是片段B:0}] d/FragmentManager:
mContainer =機器人.widget.FrameLayout {c93513 VE ..... ........ 0,0-800,1464#1} D /片段管理器:
mView = android.widget.LinearLayout {3899350 VE ..... ........ 0,0-800,1464} D/FragmentManager:
mInnerView = android.widget.LinearLayout {3899350 VE ..... ........ 0,0-800,1464} D/FragmentManager:Child FragmentManager {c564949 in FragmentB {44d0802 }}:d/FragmentManager:
FragmentManager其它狀態:d/FragmentManager:
[email protected]a76 d/FragmentManager:
mContainer = android.support.v4.app 。片段$ 1 @ 287a24e D/FragmentM anager:mParent = FragmentB {44d0802#0 ID =爲0x1} d/FragmentManager:mCurState = 5 mStateSaved =假mDestroyed =假d/FragmentManager:#1: FragmentB {d880f6f#1的ID = 0×2} d/FragmentManager:
mFragmentId =#2 mContainerId =#2 MTAG =空d/FragmentManager:
mState = 5 MINDEX = 1 mWho =機器人:片段:0:1 mBackStackNesting = 0 d/FragmentManager:mAdded =真mRemoving =假 mFromLayout =假mInLayout =假d/FragmentManager:
mHidden =假mDetached =假mMenuVisible =真mHasMenu =假 d/FragmentManager:mRetainInstance =假mRetaining =假 mUserVisibleHint =真d/FragmentManager:
mFragmentManager = FragmentManager {aa7a54d在FragmentA {6948911}} d/FragmentManager:
[email protected]a76 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 VE ..... ...... .. 0,0-800,1464#2} D/FragmentManager:
mView = android.widget.LinearLayout {c313105 VE ..... ........ 0,0-800,1464 } D /碎片管理器:
mInnerView = android.widget.LinearLayout {c313105 VE ..... ........ 0,0-800,1464} D/FragmentManager:Child FragmentManager {cbf955a in FragmentB {d880f6f}}:D/FragmentManager:
FragmentManager其它狀態:d/FragmentManager:
[email protected]a76 d/FragmentManager:
mContainer = android.support.v4.app.Fragment $ -1 @ ab0338b d/FragmentManager:mParent = FragmentB {d880f6f#1 ID = 0×2} d/FragmentManager:mCurState = 5 mStateSaved =假mDestroyed =假d/FragmentManager:#2: FragmentB {53c7c68#2的ID = 0x3} d /片段管理器:
mFragmentId =#3 mContainerId =#3 MTAG = NULL d/FragmentManager:
mState = 5 MINDEX = 2 mWho =機器人:片段:0:2 mBackStackNesting = 0 d/FragmentManager:mAdded =真mRemoving =假 mFromLayout =假mInLayout =假d/FragmentManager:
mHidden =假mDetached =假mMenuVisible =真mHasMenu =假 d/FragmentManager:mRetainInstance =假mRetaining =假 mUserVisibleHint =真d/FragmentManager:
mFragmentManager = FragmentManager {aa7a54d在FragmentA {6948911}} D/FragmentManager:
mHost = android.support.v4.app。FragmentActivity $ HostCallbacks @ 327ba76 d/FragmentManager:mParentFragment = FragmentA {6948911#0 ID = 0x7f0b0056} d/FragmentManager:
mArguments =捆綁[{TEXT =這是片段B:2}] d/FragmentManager:
mContainer = android.widget.FrameLayout {918d881 VE ..... ........ 0,0-800,1464#3} D/FragmentManager:
mView = android.widget.LinearLayout {651ad26 VE。 .... ........ 0,0-800,1464} D/FragmentManager:
mInnerView = android.widget.LinearLayout {651ad26 VE ..... ........ 0,0-800,1464} D /片段管理器:兒童 片段管理器{4ec7d67 in FragmentB {53c7c68}}:D/FragmentManag ER:
FragmentManager其它國家:d/FragmentManager:
[email protected]a76 d/FragmentManager:
[email protected] d/FragmentManager:mParent = FragmentB {53c7c68#2 ID = 0x3} d/FragmentManager:mCurState = 5 mStateSaved =假mDestroyed =假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 =真mRemoving =假 mFromLayout =假mInLayout =假d/FragmentManager:
mHidden =假mDetached =假mMenuVisible =真mHasMenu =假 d/FragmentManager:mRetainInstance =假mRetaining =假 mUserVisibleHint =真d/FragmentManager:
mFragmentManager = FragmentManager {aa7a54d在FragmentA {6948911}} d/FragmentManager:
[email protected]a76 d/FragmentManager:mParentFragment = FragmentA {6948911 #0 id = 0x7f0b0056} D/FragmentManager:
mArguments = Bundle [{TEXT = This is Fragm D/FragmentManager:
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其它狀態: d/FragmentManager:
mHost = [email protected] d/FragmentManager:
[email protected] d/FragmentManager:mParent = FragmentA {6948911#0 ID = 0x7f0b0056 } D/FragmentManager:mCurS泰特= 5 mStateSaved =假mDestroyed =假d/FragmentManager:添加 片段:d/FragmentManager:#0:FragmentA {6948911#0 ID = 0x7f0b0056} d/FragmentManager:FragmentManager其它狀態: d/FragmentManager:
[email protected]a76 D/FragmentManager:
mContainer = android.support.v4.app。FragmentActivity $ HostCallbacks @ 327ba76 D/FragmentManager:mCurState = 5 mStateSaved = false mDestroyed = false I/art:部分代碼緩存收集,代碼= 30KB,數據= 27KB I/art: 代碼緩存收集後,代碼= 29KB ,數據= 27KB I/art:增加 代碼緩存容量爲128KB D/FragmentManager:查看分層結構: D/FragmentManager:com.android.internal.policy.DecorView {99b75b2 VE .... ... 0,0 -2560,1800} D/FragmentManager:
android.widget.LinearLayout {eb98903 VE .... ... 0,0-2560,1704} D/FragmentManager:android.view.ViewStub {8107080 GE ... ... 0,0-0,0#10203ef android:id/action_mode_bar_stub} D/FragmentManager:
andro id.widget.FrameLayout {44716b9 VE .... ... 0,48-2560,1704} D/FragmentManager:
android.support.v7.widget.ActionBarOverlayLayout {7473afe VE .... ... 0,0-2560,1656#7f0b0044 app:id/decor_content_parent} D/FragmentManager:
android.support.v7.widget.ContentFrameLayout {bc1b25f VE .... ... 0,128-2560,1656#1020002 android :ID /內容} d/FragmentManager:
android.widget.RelativeLayout {a4c14ac VE .... ... 0,0-2560,1528

7f0b0055應用:ID/activity_main} d/FragmentManager:機器人。 widget.FrameLayout {ffe8877 VE .... ... 128,32-2432,1496

7f0b0056應用:ID/fragmentA} d/FragmentManager:android.widget.LinearLayout {ffe8ce4 VE .... ... 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 VE ....。 .. -19,0-781,1464} W/ResourceType:獲取資源名稱時沒有包標識符 number 0x00000001 D/FragmentManager:
android.widget.FrameLayout {c93513 VE .... ... 0, 0-800,1464#1} d/FragmentManager:
android.widget.LinearLayout {3899350 VE .... ... 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 VE .... ... 781,0-1581 ,1464} W/ResourceType:獲取資源名稱時沒有包標識符 number 0x00000002 D/FragmentManager:
android.widget.FrameLayout {67c947c VE .... ... 0,0-800,1464#2} D/FragmentManager:
android.widget.LinearLayout {c313105 VE .... ... 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 VE .... ... 1581,0-2381,1464} W/ResourceType:獲取資源名稱時沒有包標識符 number 0x00000003 D/FragmentManager:
android.widget.FrameLayout {918d881 VE .... ... 0,0-800,1464#3} D/FragmentManager:
android.widget.LinearLayout {651ad26 VE .... ... 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 VE ....。 .. 0,0-2560,128

7f0b0046應用程式: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 VE .... ... 2544,0-2544,128} D/FragmentManager:
android.support.v7.widget.ActionBarContextView {460f9b0 GE .... ... 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:關閉VM E/AndroidRuntime:致命異常:主要 進程:example.com .demo,PID:8156 java.lang.IllegalArgumentException:未找到針對片段FragmentB {30cad9b的ID爲0x4(未知)的視圖#3 = ID處android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1107) 爲0x4} 在android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1295) 在機器人。 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) 從目標VM,地址斷開連接: '本地主機:8616',運輸: '插座'

的2個主類是FragmentAAdapter和FragmentB(你可以看到其他類,如果你需要在混帳回購協議):

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

}

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

}

全碼:https://github.com/checklist/NestedFragmentsRecycler

謝謝!

+0

產生內部'onCreateViewHolder'新的ID,而不是'onBindViewHolder':你只需要儘可能多的ID作爲持有多/你有 – pskink

+0

已經嘗試過,並且在任何滾動之前得到相同的異常 – checklist

+0

,該命令的輸出是什麼:'adb shell dumpsys activity top'? – pskink

回答

1

經過大量的靈魂搜索之後,我可以確認無法在碎片中生成ID。如果你這樣做,Android在渲染UI和應用程序崩潰時會感到困惑。

我已經在另一個項目中嘗試過這種方式,我們爲單選按鈕和動態生成並放置在片段和相同行爲中的組生成了id。有兩種解決方案: - 不編程方式創建,因此您不需要生成的ID - 不使用片段