Уничтожить экземпляр FragmentStatePagerAdapter с родительским фрагментом

Я не знаю, как спросить об этом. Я попробовал здесь, но я думаю, что я был недостаточно ясен. Итак, я подумал, что просто напишу небольшое приложение, чтобы описать ситуацию. Обратите внимание, что Приложение использует файлы Google SlidingTabLayout.

Короче говоря, в любой момент, если я нажму Button1, FrameLayout должен содержать Fragment1, удаляя Fragment2 (если существует). Следовательно, FragmentViewPager также следует уничтожить как Fragment2. Однако даже тогда, если я изменю ориентацию своего устройства, я получу Toast, который определен в методе onCreate() для FragmentViewPager.

Почему onCreate FragmentViewPager вызывается, даже если Fragment2 приостановлено/уничтожено? Возможно ли, что тост FragmentViewPager не будет отображаться, когда Fragment2 будет уничтожен?

Основная активность:

package com.abdfahim.testproject;

import android.app.Fragment;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button button1 = (Button) findViewById(R.id.button1);
        button1.setOnClickListener(onClickListener);

        Button button2 = (Button) findViewById(R.id.button2);
        button2.setOnClickListener(onClickListener);
    }


    private View.OnClickListener onClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Fragment fragment;
            switch (v.getId()){
                case R.id.button1:
                    fragment = new Fragment1();
                    break;
                case R.id.button2:
                    fragment = new Fragment2();
                    break;
                default:
                    return;
            }
            getFragmentManager().beginTransaction().replace(R.id.frame_container, fragment, v.getTag().toString()).addToBackStack(null).commit();
        }
    };
}

Фрагмент1

package com.abdfahim.testproject;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class Fragment1 extends Fragment {

    public Fragment1(){}

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment1,container,false);
        setHasOptionsMenu(true);

        return rootView;
    }
}

Фрагмент2

package com.abdfahim.testproject;

import android.app.Fragment;
import android.app.FragmentManager;
import android.os.Bundle;
import android.support.v13.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class Fragment2 extends Fragment {

    public Fragment2(){}

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment2,container,false);
        setHasOptionsMenu(true);

        CharSequence titles[]= {"Tab A", "Tab B"};

        // Creating The ViewPagerAdapter
        ViewPagerAdapter adapter =  new ViewPagerAdapter(getActivity().getFragmentManager(), titles, titles.length);
        ViewPager pager = (ViewPager) rootView.findViewById(R.id.pager);
        pager.setAdapter(adapter);

        // Assigning the Sliding Tab Layout View
        SlidingTabLayout tabs = (SlidingTabLayout) rootView.findViewById(R.id.tabs);

        // Setting the ViewPager For the SlidingTabsLayout
        tabs.setViewPager(pager);

        return rootView;
    }

    static class ViewPagerAdapter extends FragmentStatePagerAdapter {

        private CharSequence titles[];
        private int numbOfTabs;

        public ViewPagerAdapter(FragmentManager fm, CharSequence mTitles[], int mNumbOfTabs) {
            super(fm);

            this.titles = mTitles;
            this.numbOfTabs = mNumbOfTabs;

        }

        @Override
        public int getItemPosition(Object object) {
            return POSITION_NONE;
        }

        @Override
        public Fragment getItem(int position) {
            Bundle bundle = new Bundle();
            bundle.putString("displayText", "Inside Fragment 2, " + titles[position]);
            FragmentViewPager fragment = new FragmentViewPager();
            fragment.setArguments(bundle);
            return fragment;
        }

        // This method return the titles for the Tabs in the Tab Strip

        @Override
        public CharSequence getPageTitle(int position) {
            return titles[position];
        }

        // This method return the Number of tabs for the tabs Strip

        @Override
        public int getCount() {
            return numbOfTabs;
        }

    }
}

FragmentViewPager

package com.abdfahim.testproject;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;

public class FragmentViewPager extends Fragment {

    public FragmentViewPager(){}

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_view_pager,container,false);
        setHasOptionsMenu(true);

        Bundle bundle = this.getArguments();
        TextView textView = (TextView) rootView.findViewById(R.id.tabText);
        textView.setText(bundle.getString("displayText"));

        return rootView;
    }

    @Override
    public void onStart() {
        super.onStart();
        Toast.makeText(getActivity(), "This is View Pager Fragment", Toast.LENGTH_SHORT).show();
    }
}

person abdfahim    schedule 02.01.2017    source источник


Ответы (2)


когда вы используете фрагмент внутри другого фрагмента. вы используете getChildFragmentManager() вместо getFragmentManager. Вы можете вызвать setAdapter() для ViewPager из onCreateView() или onActivityCreated().

для более подробной информации. Посмотри на это

Почему нельзя использовать ViewPager внутри фрагмента? На самом деле

person Abdullah Raza    schedule 09.01.2017
comment
Спасибо, я провел небольшое исследование о getChildFragmentManager(), и мне показалось, что это действительно должно работать. Но, к сожалению, это не так. Даже если я использую getChildFragmentManager(), дочерние фрагменты не уничтожаются вместе с родительским. - person abdfahim; 09.01.2017
comment
тогда вы должны отслеживать дочерние фрагменты и удалять их вручную. Как я читал здесь .. это объясняет ту же проблему, с которой вы столкнулись. инициализация фрагментов при вращении ком/вопросы/30551939/ - person Abdullah Raza; 09.01.2017
comment
Для справки, он действительно работает нормально, пока я не добавляю родительский фрагмент в стопку при добавлении в макет кадра. Итак, я бы сказал, что это решило мою проблему, спасибо. Мне нужно найти способ заставить его работать с функциональностью addtobackstack(), но это отдельный вопрос. - person abdfahim; 12.01.2017

Для каждого клика ваш OnClickListener создает экземпляр Fragment2 и не создает Fragment1. Это связано с неправильным использованием View#getTag.

В MainActivity#onCreate измените if в определении onClickListener на это (используя этот ответ):

switch (v.getId()){
        case R.id.button1:
            fragment = new Fragment1();
            break;
        case R.id.button2:
            fragment = new Fragment2();
            break;
        default:
            return;
    }

В вашем коде в if, который проверяется при щелчке (например, после нажатия button1), андроид запрашивает v (щелкнутый View) для своего тега, но поскольку ни один из них не был установлен с помощью View#setTag — возвращает null, который, конечно, не равен объекту String создан для «кнопки1», поэтому if каждый раз возвращается к else.

person et_l    schedule 02.01.2017
comment
Спасибо за ваш комментарий. На самом деле у меня правильно установлен тег для кнопок в файле xml (который здесь не показан). И я могу заверить, что кнопки работают по назначению (обеспечено с помощью logcat). Тем не менее, я должен сказать, что ваше предложение лучше, и я перехожу к нему, НО конечный результат остается прежним. - person abdfahim; 02.01.2017