Sự khác biệt giữa add (), thay thế () và addToBackStack ()


300

Sự khác biệt chính giữa việc gọi các phương thức này là gì:

fragmentTransaction.addToBackStack(name);
fragmentTransaction.replace(containerViewId, fragment, tag);
fragmentTransaction.add(containerViewId, fragment, tag);

Việc thay thế một đoạn đã có nghĩa là gì và thêm một đoạn vào trạng thái hoạt động và thêm một hoạt động vào ngăn xếp phía sau?

Thứ hai, với findFragmentByTag(), tìm kiếm này cho thẻ được thêm bởi phương thức add()/ replace()hoặc addToBackStack()phương thức?

Câu trả lời:


331

1) fragmentTransaction.addToBackStack(str);

Mô tả - Thêm giao dịch này vào ngăn xếp phía sau. Điều này có nghĩa là giao dịch sẽ được ghi nhớ sau khi được cam kết và sẽ đảo ngược hoạt động của nó khi sau đó bật ra khỏi ngăn xếp.

2) fragmentTransaction.replace(int containerViewId, Fragment fragment, String tag)

Mô tả - Thay thế một đoạn hiện có đã được thêm vào một thùng chứa. Điều này về cơ bản giống như gọi remove (Fragment) cho tất cả các đoạn hiện được thêm vào cùng với containerViewId và sau đó thêm (int, Fragment, String) với cùng các đối số được đưa ra ở đây.

3) fragmentTransaction.add(int containerViewId, Fragment fragment, String tag)

Mô tả - Thêm một đoạn vào trạng thái hoạt động. Đoạn này có thể tùy chọn cũng có chế độ xem của nó (nếu Fragment.onCreateView trả về giá trị không null) vào chế độ xem của hoạt động.

Điều đó có nghĩa gì khi thay thế một đoạn đã có sẵn và thêm một đoạn vào trạng thái hoạt động và thêm một hoạt động vào ngăn xếp phía sau?

Có một ngăn xếp trong đó tất cả các hoạt động trong trạng thái chạy được giữ. Những mảnh vỡ thuộc về hoạt động. Vì vậy, bạn có thể thêm chúng để nhúng chúng vào một hoạt động.

Bạn có thể kết hợp nhiều phân đoạn trong một hoạt động để xây dựng giao diện người dùng nhiều ngăn và sử dụng lại một đoạn trong nhiều hoạt động. Điều này về cơ bản là hữu ích khi bạn đã xác định thùng chứa mảnh vỡ của mình ở các bố cục khác nhau. Bạn chỉ cần thay thế bằng bất kỳ mảnh nào khác trong bất kỳ bố cục.

Khi bạn điều hướng đến bố cục hiện tại, bạn có id của container đó để thay thế nó bằng đoạn bạn muốn.

Bạn cũng có thể quay lại đoạn trước trong backStack bằng popBackStack()phương thức. Cho rằng bạn cần thêm đoạn đó vào ngăn xếp bằng cách sử dụng addToBackStack()và sau đó commit()để phản ánh. Điều này là theo thứ tự ngược lại với hiện tại trên đầu trang.

findFragmentByTag tìm kiếm thẻ này được thêm bằng phương thức add / thay thế hoặc phương thức addToBackStack?

Nếu phụ thuộc vào cách bạn thêm thẻ. Sau đó, nó chỉ tìm thấy một đoạn bằng thẻ của nó mà bạn đã xác định trước khi được thổi phồng từ XML hoặc như được cung cấp khi được thêm vào trong một giao dịch.

Tài liệu tham khảo: FragmentTransaction


2
Vì vậy, tôi có thể thêm đoạn bằng phương pháp thay thế khi bắt đầu hoạt động không?
Yohanes AI

(Không có đoạn nào được thêm vào trước đó)
Yohanes AI

2
Một thùng chứa mảnh có thể chứa nhiều hơn một mảnh, Nếu có hơn phương thức thay thế () sẽ hành xử như thế nào. Nếu nó thay thế tất cả các frgaments trong container hoặc android api đó có một phương thức chấp nhận ba đối số, đó là frgamentContainer, đoạn mới và với ai để thay thế.
ved

1
@ved Không, nó sẽ thay thế tất cả các mảnh hiện có trong container bằng cái hiện tại.
reubenjohn

330

Một sự khác biệt quan trọng hơn giữa addreplacelà:

replaceloại bỏ các mảnh hiện có và thêm một mảnh mới. Điều này có nghĩa là khi bạn nhấn nút quay lại, đoạn được thay thế sẽ được tạo với nó onCreateViewđược gọi. Trong khi đó addgiữ lại các đoạn hiện có và thêm một đoạn mới có nghĩa là đoạn hiện tại sẽ hoạt động và chúng sẽ không ở trạng thái 'tạm dừng' do đó khi nhấn nút quay lại onCreateViewkhông được gọi cho đoạn hiện tại (đoạn đó đã ở đó trước đoạn mới thêm).

Trong điều kiện của sự kiện vòng đời mảnh của onPause, onResume, onCreateViewvà các sự kiện chu kỳ sống khác sẽ được áp dụng trong trường hợp replacenhưng họ sẽ không được áp dụng trong trường hợp add.

Chỉnh sửa : Mọi người nên cẩn thận nếu cô ấy đang sử dụng một loại thư viện xe buýt sự kiện như Eventbus của Greenrobot và sử dụng lại cùng một đoạn để xếp đoạn này lên trên đoạn khác add. Trong trường hợp này, mặc dù bạn tuân theo thực tiễn tốt nhất và đăng ký xe buýt sự kiện onResumevà hủy đăng ký onPause, xe buýt sự kiện vẫn sẽ hoạt động trong từng trường hợp của đoạn được thêm vào vì addđoạn không gọi một trong hai phương thức vòng đời mảnh này. Kết quả là người nghe xe buýt sự kiện trong mỗi phiên bản hoạt động của đoạn sẽ xử lý cùng một sự kiện có thể không phải là điều bạn muốn.


1
Tôi nghĩ rằng một cách tiếp cận có thể là xử lý sự kiện trong phần lớn nhất và gọi hủyEventDelivery () sau khi xử lý xong. Bạn có thể tìm hiểu thêm về các phương thức hủyEventDelivery () tại đây github.com/greenrobot/EventBus/blob/master/ mẹo
Jeevan

6
+1 từ tôi. Rất quan trọng để biết rằng thay thế đoạn hiện tại bằng đoạn mới, có nghĩa là đoạn trước đó sẽ được tạo lại để lấy lại khi bật lại từ ngăn xếp mảnh.
AndaluZ

onPause, onResume được liên kết chặt chẽ với Hoạt động máy chủ. Và họ đã không gọi khi thay thế mảnh vỡ.
Zar E Ahmer 8/8/2016

Chỉ cần thêm vào điều này, nếu bạn đang sử dụng EventBus, bạn có thể thêm đoạn bằng Thẻ và chuyển từ đoạn đó sang sự kiện đó và kiểm tra xem, tất cả sự kiện sẽ được gọi, bạn chỉ cần xác định cái nào sẽ thực thi
user2582318

Bạn phải đề cập rằng bạn đang gọi phương thức addToBackStack () cùng với các phương thức add () hoặc thay thế ().
rahil008

99

Ví dụ một hoạt động có 2 phân đoạn và chúng tôi sử dụng FragmentManagerđể thay thế / thêm addToBackstacktừng phân đoạn vào bố cục trong hoạt động

Sử dụng thay thế

Đi mảnh1

Fragment1: onAttach
Fragment1: onCreate
Fragment1: onCreateView
Fragment1: onActivityCreated
Fragment1: onStart
Fragment1: onResume

Đi mảnh2

Fragment2: onAttach
Fragment2: onCreate
Fragment1: onPause
Fragment1: onStop
Fragment1: onDestroyView
Fragment2: onCreateView
Fragment2: onActivityCreated
Fragment2: onStart
Fragment2: onResume

Mảnh vỡ Pop2

Fragment2: onPause
Fragment2: onStop
Fragment2: onDestroyView
Fragment2: onDestroy
Fragment2: onDetach
Fragment1: onCreateView
Fragment1: onStart
Fragment1: onResume

Mảnh vỡ Pop1

Fragment1: onPause
Fragment1: onStop
Fragment1: onDestroyView
Fragment1: onDestroy
Fragment1: onDetach

Sử dụng thêm

Đi mảnh1

Fragment1: onAttach
Fragment1: onCreate
Fragment1: onCreateView
Fragment1: onActivityCreated
Fragment1: onStart
Fragment1: onResume

Đi mảnh2

Fragment2: onAttach
Fragment2: onCreate
Fragment2: onCreateView
Fragment2: onActivityCreated
Fragment2: onStart
Fragment2: onResume

Mảnh vỡ Pop2

Fragment2: onPause
Fragment2: onStop
Fragment2: onDestroyView
Fragment2: onDestroy
Fragment2: onDetach

Mảnh vỡ Pop1

Fragment1: onPause
Fragment1: onStop
Fragment1: onDestroyView
Fragment1: onDestroy
Fragment1: onDetach

Dự án mẫu


1
không onPause()phải được gọi trước đây onStop()trên mọi hành động Pop ?
iCantC

câu trả lời tuyệt vời để phân biệt giữa 'add ()' và 'thay thế ()', mặc dù thiếu về addToBackStack (). Upvote
Shirish Herwade

@ShirishHerwade Tôi tin rằng anh ấy đã chứng minh sự khác biệt giữa thêm và thay thế bằng addToBackStack trên cả hai trường hợp.
CyberShark

38

Mặc dù đây là một câu hỏi cũ đã được trả lời, nhưng có lẽ những ví dụ tiếp theo có thể bổ sung cho câu trả lời được chấp nhận và chúng có thể hữu ích cho một số lập trình viên mới trong Android như tôi.

Tùy chọn 1 - "addToBackStack ()" không bao giờ được sử dụng

Trường hợp 1A - thêm, xóa và nhấp vào nút Quay lại

Activity :      onCreate() - onStart() - onResume()                             Activity is visible
add Fragment A :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment A is visible
add Fragment B :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment B is visible
add Fragment C :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment C is visible
remove Fragment C :     onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Fragment B is visible
(Back button clicked)
Activity :      onPause() - onStop() - onDestroy()
Fragment A :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()
Fragment B :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               App is closed, nothing is visible

Trường hợp 1B - thêm, thay thế và nhấp vào nút Quay lại

Activity :      onCreate() - onStart() - onResume()                             Activity is visible
add Fragment A :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment A is visible
add Fragment B :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment B is visible
(replace Fragment C)    
Fragment B :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               
Fragment A :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()
Fragment C :        onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment C is visible
(Back button clicked)
Activity :      onPause() - onStop() - onDestroy()
Fragment C :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               App is closed, nothing is visible

Tùy chọn 2 - "addToBackStack ()" luôn được sử dụng

Trường hợp 2A - thêm, xóa và nhấp vào nút Quay lại

Activity :      onCreate() - onStart() - onResume()                             Activity is visible
add Fragment A :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment A is visible
add Fragment B :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment B is visible
add Fragment C :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment C is visible
remove Fragment C :     onPause() - onStop() - onDestroyView()                              Fragment B is visible
(Back button clicked)
Fragment C :        onCreateView() - onActivityCreated() - onStart() - onResume()                   Fragment C is visible
(Back button clicked)
Fragment C :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Fragment B is visible
(Back button clicked)
Fragment B :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Fragment A is visible
(Back button clicked)
Fragment A :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Activity is visible
(Back button clicked)
Activity :      onPause() - onStop() - onDestroy()                              App is closed, nothing is visible

Trường hợp 2B - thêm, thay thế, xóa và nhấp vào nút Quay lại

Activity :      onCreate() - onStart() - onResume()                             Activity is visible
add Fragment A :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment A is visible
add Fragment B :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment B is visible
(replace Fragment C)    
Fragment B :        onPause() - onStop() - onDestroyView()  
Fragment A :        onPause() - onStop() - onDestroyView() 
Fragment C :        onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment C is visible
remove Fragment C :     onPause() - onStop() - onDestroyView()                              Activity is visible
(Back button clicked)
Fragment C :        onCreateView() - onActivityCreated() - onStart() - onResume()                   Fragment C is visible
(Back button clicked)
Fragment C :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               
Fragment A :        onCreateView() - onActivityCreated() - onStart() - onResume()   
Fragment B :        onCreateView() - onActivityCreated() - onStart() - onResume()                   Fragment B is visible
(Back button clicked)
Fragment B :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Fragment A is visible
(Back button clicked)
Fragment A :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Activity is visible
(Back button clicked)
Activity :      onPause() - onStop() - onDestroy()                              App is closed, nothing is visible

Tùy chọn 3 - "addToBackStack ()" không được sử dụng luôn (trong các ví dụ dưới đây, w / o chỉ ra rằng nó không được sử dụng)

Trường hợp 3A - thêm, xóa và nhấp vào nút Quay lại

Activity :      onCreate() - onStart() - onResume()                             Activity is visible
add Fragment A :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment A is visible
add Fragment B w/o:     onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment B is visible
add Fragment C w/o:     onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment C is visible
remove Fragment C :     onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Fragment B is visible
(Back button clicked)
Fragment B :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               
Fragment A :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Activity is visible
(Back button clicked)
Activity :      onPause() - onStop() - onDestroy()                              App is closed, nothing is visible

Trường hợp 3B - thêm, thay thế, xóa và nhấp vào nút Quay lại

Activity :      onCreate() - onStart() - onResume()                             Activity is visible
add Fragment A :    onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment A is visible
add Fragment B w/o:     onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment B is visible
(replace Fragment C)    
Fragment B :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()   
Fragment A :        onPause() - onStop() - onDestroyView() 
Fragment C :        onAttach() - onCreate() - onCreateView() - onActivityCreated() - onStart() - onResume()     Fragment C is visible
remove Fragment C :     onPause() - onStop() - onDestroyView()                              Activity is visible
(Back button clicked)
Fragment C :        onCreateView() - onActivityCreated() - onStart() - onResume()                   Fragment C is visible
(Back button clicked)
Fragment C :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               
Fragment A :        onCreateView() - onActivityCreated() - onStart() - onResume()                   Fragment A is visible
(Back button clicked)
Fragment A :        onPause() - onStop() - onDestroyView() - onDestroy() - onDetach()               Activity is visible
(Back button clicked)
Activity :      onPause() - onStop() - onDestroy()                              App is closed, nothing is visible

1
Đủ kỹ lưỡng Nỗ lực tốt!
bột giấy_fict

Vì vậy, chúng ta có thể nói rằng trong khi làm việc với nút back Fragment hoạt động theo kiểu tương tự như hàm FragmentManager.popBackStack () không?
Tintin

Câu trả lời tuyệt vời, không thể tốt hơn. Điều này nên được chấp nhận câu trả lời.
Shirish Herwade

25

Sự khác biệt cơ bản giữa add()replace()có thể được mô tả là:

  • add() được sử dụng để chỉ cần thêm một đoạn vào một số phần tử gốc.
  • replace() hành xử tương tự nhưng lúc đầu nó loại bỏ các đoạn trước và sau đó thêm đoạn tiếp theo.

Chúng ta có thể thấy sự khác biệt chính xác khi chúng ta sử dụng addToBackStack()cùng với add()hoặc replace().

Khi chúng ta nhấn nút quay lại sau trong trường hợp add()... onCreateView không bao giờ được gọi, nhưng trong trường hợp replace(), khi chúng ta nhấn nút quay lại ... oncreateView được gọi mỗi lần.


1
Vì vậy, add () dẫn đến gánh nặng nhiều hơn về bộ nhớ Android, vì chế độ xem của đoạn trước không bị phá hủy?
Derekyy

@Derekyy Vâng, tôi nghĩ vậy.
Arpit J.

là những gì tôi đang tìm kiếm
parvez rafi

2

Khi chúng tôi thêm đoạn đầu tiên -> Đoạn thứ hai bằng phương thức add ()

 btn_one.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(getActivity(),"Click First 
Fragment",Toast.LENGTH_LONG).show();

                Fragment fragment = new SecondFragment();
                getActivity().getSupportFragmentManager().beginTransaction()
                        .add(R.id.fragment_frame, fragment, fragment.getClass().getSimpleName()).addToBackStack(null).commit();
//                        .replace(R.id.fragment_frame, fragment, fragment.getClass().getSimpleName()).addToBackStack(null).commit();

            }
        });

Khi chúng ta sử dụng add () trong đoạn

E/Keshav SecondFragment: onAttach
E/Keshav SecondFragment: onCreate
E/Keshav SecondFragment: onCreateView
E/Keshav SecondFragment: onActivityCreated
E/Keshav SecondFragment: onStart
E/Keshav SecondFragment: onResume

Khi chúng ta sử dụng thay thế () trong đoạn

chuyển đến đoạn đầu tiên đến đoạn thứ hai trong phương thức First -> Thứ hai bằng cách sử dụng thay thế ()

 btn_one.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(getActivity(),"Click First Fragment",Toast.LENGTH_LONG).show();

                Fragment fragment = new SecondFragment();
                getActivity().getSupportFragmentManager().beginTransaction()
//                        .add(R.id.fragment_frame, fragment, fragment.getClass().getSimpleName()).addToBackStack(null).commit();
                        .replace(R.id.fragment_frame, fragment, fragment.getClass().getSimpleName()).addToBackStack(null).commit();

            }
        });

E/Keshav SecondFragment: onAttach
E/Keshav SecondFragment: onCreate

E/Keshav FirstFragment: onPause -------------------------- FirstFragment
E/Keshav FirstFragment: onStop --------------------------- FirstFragment
E/Keshav FirstFragment: onDestroyView -------------------- FirstFragment

E/Keshav SecondFragment: onCreateView
E/Keshav SecondFragment: onActivityCreated
E/Keshav SecondFragment: onStart
E/Keshav SecondFragment: onResume

Trong trường hợp Thay thế mảnh vỡ đầu tiên, phương thức này được gọi thêm (onPause, onStop, onDestroyView được gọi thêm)

E / Keshav FirstFragment: onPause

E / Keshav FirstFragment: onStop

E / Keshav FirstFragment: onDestroyView


0

Chức năng thêm và thay thế chức năng của FragmentManger có thể được mô tả như sau 1. thêm nghĩa là nó sẽ thêm đoạn trong ngăn xếp lại đoạn và nó sẽ hiển thị ở khung đã cho mà bạn đang cung cấp

getFragmentManager.beginTransaction.add(R.id.contentframe,Fragment1.newInstance(),null)

2.replace có nghĩa là bạn đang thay thế đoạn này bằng đoạn khác ở khung đã cho

getFragmentManager.beginTransaction.replace(R.id.contentframe,Fragment1.newInstance(),null)

Tiện ích chính giữa hai thứ đó là khi bạn quay lại, việc thay thế sẽ làm mới đoạn đó nhưng thêm sẽ không làm mới đoạn trước đó.


0

Điều quan trọng cần chú ý:

Sự khác biệt giữa Thay thế và Thay thế bằng backstack là bất cứ khi nào chúng ta chỉ sử dụng thay thế thì đoạn bị hủy (ondestroy () được gọi) và khi chúng ta sử dụng thay thế bằng backstack thì các đoạn trênDestroy () không được gọi (nghĩa là khi nút quay lại được gọi là đoạn với onCreateView ())


0

Dưới đây là hình ảnh cho thấy sự khác biệt giữa add()replace()

nhập mô tả hình ảnh ở đây

Vì vậy, add()phương thức tiếp tục thêm các đoạn trên đầu đoạn trước trong FragmentContainer.

Trong khi replace()các phương thức xóa tất cả các Fragment trước đó khỏi Container và sau đó thêm nó vào FragmentContainer.

AddToBackStack là gì

addtoBackStackphương thức có thể được sử dụng với phương thức add () và thay thế. Nó phục vụ một mục đích khác trong API Fragment.

Mục đích là gì?

API phân mảnh không giống như API hoạt động không đi kèm với điều hướng Nút quay lại theo mặc định. Nếu bạn muốn quay lại Fragment trước thì chúng tôi sử dụng phương thức addToBackStack () trong Fragment. Hãy hiểu cả hai

Trường hợp 1:

getSupportFragmentManager()
            .beginTransaction()
            .add(R.id.fragmentContainer, fragment, "TAG")
            .addToBackStack("TAG")
            .commit();

nhập mô tả hình ảnh ở đây

Trường hợp 2:

getSupportFragmentManager()
            .beginTransaction()
            .add(R.id.fragmentContainer, fragment, "TAG")
            .commit();

nhập mô tả hình ảnh ở đây

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.