재개() 및 일시 중지()의 조각이 백스택에서 호출되지 않음
활동에 여러 개의 조각이 있습니다.버튼을 클릭하면 새 조각을 시작하여 백스택에 추가합니다.나는 당연히 예상했습니다.onPause() 및 current fragment의 onResume()새로운 프래그먼트가 호출됩니다.글쎄요, 그런 일은 일어나지 않습니다.
LoginFragment.java
public class LoginFragment extends Fragment{
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.login_fragment, container, false);
final FragmentManager mFragmentmanager = getFragmentManager();
Button btnHome = (Button)view.findViewById(R.id.home_btn);
btnHome.setOnClickListener(new View.OnClickListener() {
public void onClick(View view){
HomeFragment fragment = new HomeFragment();
FragmentTransaction ft2 = mFragmentmanager.beginTransaction();
ft2.setCustomAnimations(R.anim.slide_right, R.anim.slide_out_left
, R.anim.slide_left, R.anim.slide_out_right);
ft2.replace(R.id.middle_fragment, fragment);
ft2.addToBackStack("");
ft2.commit();
}
});
}
@Override
public void onResume() {
Log.e("DEBUG", "onResume of LoginFragment");
super.onResume();
}
@Override
public void onPause() {
Log.e("DEBUG", "OnPause of loginFragment");
super.onPause();
}
}
HomeFragment.java
public class HomeFragment extends Fragment{
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.login_fragment, container, false);
}
@Override
public void onResume() {
Log.e("DEBUG", "onResume of HomeFragment");
super.onResume();
}
@Override
public void onPause() {
Log.e("DEBUG", "OnPause of HomeFragment");
super.onPause();
}
}
내가 기대했던 것은,
- 버튼을 클릭하면 LoginFragment가 HomeFragment로 바뀝니다.
onPause()LoginFragment(로그인 조각) 및onResume()of HomeFragment가 호출됩니다. - 뒤로를 누르면 HomeFragment가 팝업되고 LoginFragment가 표시됩니다.
onPause()홈 프래그먼트와onResume()의 LoginFragment가 호출됩니다.
내가 얻는 것은,
- 버튼을 클릭하면 HomeFragment가 LoginFragment를 올바르게 대체하고 있으며 HomeFragment의 Resume()는 호출되지만 LoginFragment의 Pause()는 호출되지 않습니다.
- 다시 누르면 HomeFragment가 올바르게 팝업되어 LoginFragment가 표시되고 HomeFragment의 Pause()는 호출되지만 LoginFragment의 Resume()는 호출되지 않습니다.
이게 정상적인 행동입니까? 왜?onResume()뒤로 버튼을 누르면 LoginFragment가 호출되지 않습니다.
단편들은 편들입니다.onResume()또는onPause()활동이 있을 때만 호출됩니다.onResume()또는onPause()이 호출됩니다.그것들은 그것들에 단단히 결합되어 있습니다.Activity.
이 문서의 단편 라이프사이클 처리 섹션을 읽어보십시오.
- 이 이한후를 에.
ft2.replace(),FragmentTransaction.remove()메서드가 호출되고Loginfragment제거됩니다.이것을 참고하세요. 그래서.onStop()LoginFragment대신 호출됩니다.onPause()(새로운 조각이 이전 조각을 완전히 대체하기 때문에). - 하지만 당신이 또한 사용했기 때문에.
ft2.addtobackstack()의Loginfragment되며 다에서뒤버클튼릭번에서 하면 에 저장됩니다.HomeFragment,onViewStateRestored()다음으로 호출됩니다.onStart()LoginFragment결국에는 ㅠㅠㅠㅠㅠㅠㅠonResume()호출되지 않습니다.
Gor의 답변에 대한 나의 더 강력한 버전은 다음과 같습니다(fragments.size()를 사용하는 것은 fragment가 팝업된 후 크기가 줄어들지 않기 때문에 신뢰할 수 없습니다).
getFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
@Override
public void onBackStackChanged() {
if (getFragmentManager() != null) {
Fragment topFrag = NavigationHelper.getCurrentTopFragment(getFragmentManager());
if (topFrag != null) {
if (topFrag instanceof YourFragment) {
//This fragment is being shown.
} else {
//Navigating away from this fragment.
}
}
}
}
});
그리고 'getCurrentTopFragment' 메서드는 다음과 같습니다.
public static Fragment getCurrentTopFragment(FragmentManager fm) {
int stackCount = fm.getBackStackEntryCount();
if (stackCount > 0) {
FragmentManager.BackStackEntry backEntry = fm.getBackStackEntryAt(stackCount-1);
return fm.findFragmentByTag(backEntry.getName());
} else {
List<Fragment> fragments = fm.getFragments();
if (fragments != null && fragments.size()>0) {
for (Fragment f: fragments) {
if (f != null && !f.isHidden()) {
return f;
}
}
}
}
return null;
}
다른 조각 내부의 조각을 바꾸려면 중첩된 조각을 사용해야 합니다.
코드에서 교체해야 합니다.
final FragmentManager mFragmentmanager = getFragmentManager();
와 함께
final FragmentManager mFragmentmanager = getChildFragmentManager();
getFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
@Override
public void onBackStackChanged() {
List<Fragment> fragments = getFragmentManager().getFragments();
if (fragments.size() > 0 && fragments.get(fragments.size() - 1) instanceof YoureFragment){
//todo if fragment visible
} else {
//todo if fragment invisible
}
}
});
하지만 두 개 이상의 파편이 보이는 경우에는 주의하십시오.
귀하의 코드와 매우 유사한 코드가 있으며 일시 중지() 및 재개()에서 작동하는지 여부를 확인합니다.프래그먼트를 변경하면 이러한 기능이 각각 활성화됩니다.
조각난 코드:
@Override
public void onResume() {
super.onResume();
sensorManager.registerListener(this, proximidad, SensorManager.SENSOR_DELAY_NORMAL);
sensorManager.registerListener(this, brillo, SensorManager.SENSOR_DELAY_NORMAL);
Log.e("Frontales","resume");
}
@Override
public void onPause() {
super.onPause();
sensorManager.unregisterListener(this);
Log.e("Frontales","Pause");
}
fragment 변경 시 기록:
05-19 22:28:54.284 2371-2371/madi.cajaherramientas E/Frontales: resume
05-19 22:28:57.002 2371-2371/madi.cajaherramientas E/Frontales: Pause
05-19 22:28:58.697 2371-2371/madi.cajaherramientas E/Frontales: resume
05-19 22:29:00.840 2371-2371/madi.cajaherramientas E/Frontales: Pause
05-19 22:29:02.248 2371-2371/madi.cajaherramientas E/Frontales: resume
05-19 22:29:03.718 2371-2371/madi.cajaherramientas E/Frontales: Pause
CreateView의 조각:
View rootView;
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.activity_proximidad, container, false);
ButterKnife.bind(this,rootView);
inflar();
setTextos();
return rootView;
}
펄스백할 때의 동작(조각을 로드하는 활동):
@Override
public void onBackPressed() {
int count = getFragmentManager().getBackStackEntryCount();
if (count == 0) {
super.onBackPressed();
} else {
getFragmentManager().popBackStack();
}
}
활동에 사용 - KOTLIN
supportFragmentManager.addOnBackStackChangedListener {
val f = supportFragmentManager.findFragmentById(R.id.fragment_container)
if (f?.tag == "MyFragment")
{
//doSomething
}
}
하위 조각에서 수행할 작업:
@Override
public void onDetach() {
super.onDetach();
ParentFragment pf = (ParentFragment) this.getParentFragment();
pf.onResume();
}
그런 다음 ParentFragment에서 Resume를 재정의합니다.
XML에서 fragment를 추가하면 동적으로 전환할 수 없습니다.무슨 일이 일어나는지는 너무 지나쳐서 사람들이 예상하는 것처럼 사건이 발생하지 않습니다.이 문제는 이 질문에 설명되어 있습니다.FragmenManager 대체 오버레이
middle_fragment를 FrameLayout으로 바꾸고 아래와 같이 로드하면 이벤트가 실행됩니다.
getFragmentManager().beginTransation().
add(R.id.middle_fragment, new MiddleFragment()).commit();
이거 한번 해보세요.
1단계: 활동에서 Tab 선택한 방법을 재정의합니다.
@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
// When the given tab is selected, switch to the corresponding page in
// the ViewPager.
try {
if(MyEventsFragment!=null && tab.getPosition()==3)
{
MyEvents.fragmentChanged();
}
}
catch (Exception e)
{
}
mViewPager.setCurrentItem(tab.getPosition());
}
2단계: 정적 방법을 사용하여 조각에서 원하는 것을 수행합니다.
public static void fragmentChanged()
{
Toast.makeText(actvity, "Fragment Changed", Toast.LENGTH_SHORT).show();
}
onPause()메소드는 활동 클래스에서 작동하며 사용할 수 있습니다.
public void onDestroyView(){
super.onDestroyView
}
같은 목적으로..
@Gor의 대답을 바탕으로 나는 코틀린에서 비슷한 글을 썼습니다.이 코드 배치 위치onCreate()활동의표시되는 하나의 조각에 대해 작동합니다.가지고 계신다면,ViewPager파편과 함께, 그것은 부를 것입니다.ViewPager의 파편이지, 이전 것이 아닙니다.
supportFragmentManager.addOnBackStackChangedListener {
supportFragmentManager.fragments.lastOrNull()?.onResume()
}
https://medium.com/ @elye.project/filename-stack-pop-cause-on-filename-8b947c5c07c6을 읽고 많은 상황에서 새로운 fragment를 첨부하는 것이 더 낫다는 것을 알았습니다.replace,것은 아니다.add그래서 필요한 것은onResume어떤 경우에는 사라질 것입니다.
나에게, 원인은 navGraph를 사용하여 fragment 간을 전환하는 것이었습니다.
app:navGraph
(코틀린에서) 이렇게 fragment를 만든 다음 모든 라이프사이클 함수를 호출합니다.
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.nav_host_fragment, fragment)
transaction.addToBackStack(null)
transaction.commit()
조각에 조각을 추가할 수 없습니다.이 작업은 조각 작업에서 수행해야 합니다.Fragment Activity에서 LoginFragment를 만들고 있다고 가정합니다. 따라서 이 작업을 수행하려면 로그인이 닫힐 때 Fragment Activity를 통해 HomeFragment를 추가해야 합니다.
일반적으로 각 Fragment를 Fragment Manager에 추가하는 Fragment Activity 클래스가 필요합니다.Fragment 클래스 내에서는 이 작업을 수행할 수 없습니다.
조각은 항상 활동에 포함되어야 하며 조각의 수명은 호스트 활동의 수명에 직접적인 영향을 받습니다.예를 들어 활동이 일시 중지되면 해당 활동의 모든 조각이 일시 중지되고, 활동이 삭제되면 모든 조각도 일시 중지됩니다.
다음 단계를 수행하면 필요한 답변을 얻을 수 있습니다.
1 - 두 조각 모두에 대해 새 추상 부모 조각을 만듭니다.
2 - 둘 다 구현해야 하는 사용자 정의 추상화 방법을 추가합니다.
3 - 두 번째 인스턴스로 바꾸기 전에 현재 인스턴스에서 호출합니다.
부르기ft.replace(교체된 fragment의) onPause(일시 중지) 및 resume(교체된 fragment의) onResume(재개)를 트리거해야 합니다.
당신의 코드가 부풀려져 있다는 것을 알아챘습니다.login_fragment또한 CreateView의 보기를 반환하지 않습니다.만약 이것들이 오타라면, 당신의 활동 내에서 이 조각들이 어떻게 호출되는지 보여줄 수 있습니까?
조각이 나타나거나 사라질 때 호출되도록 보장하는 두 가지 재정의 방법이 있습니다.
oncreateview/ondestroyview - fragment 가시성이 변경될 때마다 호출됩니다.
onpause/onresume - 외부에서 앱을 닫거나 fragment replace를 사용할 때 호출됩니다.
만약 당신이 나처럼 후크를 만들기를 원한다면, 당신은 조각이 닫힐 때마다 알림을 통해 어떤 상황을 포착할 수 있고, 때때로 둘 다 호출될 수 있는 것처럼 중복된 호출을 만들지 않아도 됩니다.
fragment 클래스를 확장하고 두 오버라이드 모두에 부울 플래그를 추가하여 중복 없이 열린 상태와 닫힌 상태를 확실히 포착합니다.
코틀린
requireFragmentManager().addOnBackStackChangedListener {
val fragments: List<Fragment> = requireFragmentManager().fragments
if (fragments.isNotEmpty() && fragments[fragments.size - 1] is YOUR_FRAGMENT) {
//todo if fragment visible
} else {
//todo if fragment invisible
}
}
조각 트랜잭션을 만드는 동안 다음 코드를 추가해야 합니다.
// Replace whatever is in the fragment_container view with this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.fragment_container, newFragment);
transaction.addToBackStack(null);
또한 트랜잭션을 백스택에 추가한 후 커밋해야 합니다.
언급URL : https://stackoverflow.com/questions/11326155/fragment-onresume-onpause-is-not-called-on-backstack
'programing' 카테고리의 다른 글
| 내부자를 보내려면 어떻게 해야 합니까?내부자를 보내려면 어떻게 해야 합니까?부모의 밑바닥까지부모의 밑바닥까지? (0) | 2023.09.02 |
|---|---|
| Android에서 특정 Wi-Fi 네트워크에 프로그래밍 방식으로 연결하려면 어떻게 해야 합니까? (0) | 2023.09.02 |
| 판다 데이터 프레임 열을 int가 아닌 문자열로 가져오기 (0) | 2023.09.02 |
| 클릭 시 jquery 내의 ajax 게시물 (0) | 2023.08.28 |
| ExecuteReader: 연결 속성이 초기화되지 않았습니다. (0) | 2023.08.28 |