【问题标题】:Destroy FragmentStatePagerAdapter instance with parent Fragment使用父 Fragment 销毁 FragmentStatePagerAdapter 实例
【发布时间】:2017-01-02 06:07:07
【问题描述】:

我不知道怎么问这个。我试过in here,但我想我还不够清楚。所以,我想我只是写一个小App来描述这种情况。请注意,该应用使用谷歌SlidingTabLayout

长话短说,在任何时候,如果我单击 Button1,FrameLayout 应该包含 Fragment1,删除 Fragment2(如果存在)。因此,FragmentViewPager 也应该被销毁为Fragment2。但是,即使我改变了设备的方向,我也会得到在FragmentViewPageronCreate() 方法中定义的 Toast。

为什么即使Fragment2 被暂停/销毁,FragmentViewPager 的 onCreate 也会被调用?是不是Fragment2被销毁时,FragmentViewPager的Toast就不会显示了?

MainActivity:

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

【问题讨论】:

    标签: android android-fragments android-viewpager fragmentstatepageradapter


    【解决方案1】:

    当你在另一个片段中使用片段时。您使用 getChildFragmentManager() 而不是 getFragmentManager。您可以从 onCreateView() 或 onActivityCreated() 为 ViewPager 调用 setAdapter()

    了解更多详情。看看吧

    Why it is not possible to use ViewPager within a Fragment? It actually is

    【讨论】:

    • 谢谢,我对 getChildFragmentManager() 做了一些研究,看起来它应该真的有效。但不幸的是,事实并非如此。即使我使用 getChildFragmentManager(),子片段也不会被父片段破坏。
    • 那么您应该跟踪子片段并手动删除它们。正如我在这里所读到的..它解释了您面临的同样问题。旋转时初始化片段stackoverflow.com/questions/30551939/…
    • 作为记录,只要我在添加到框架布局时不将父片段添加到 backstack,它实际上就可以正常工作。所以,我会说它解决了我的问题,谢谢。我必须找到一种方法让它与 addtobackstack() 功能一起使用,但这是一个单独的问题。
    【解决方案2】:

    对于每次点击,您的OnClickListener 都会创建Fragment2 的实例,但不会创建Fragment1。那是因为View#getTag的误用。

    MainActivity#onCreate中,将onClickListener定义中的if改成这个(使用this answer):

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

    在您的代码中,在单击时检查的if 中(例如在单击button1 之后)android 向v(单击的View)询问其标签 - 但因为没有使用@ 设置987654323@ - 它返回null 当然不等于为“button1”创建的String 对象,因此if 每次都恢复为else

    【讨论】:

    • 感谢您的评论。实际上,我已经为 xml 文件中的按钮正确设置了标签(此处未显示)。而且我可以确保按钮按预期工作(使用 logcat 确保)。但是,我必须说,你的建议更好,我正在改变,但最终结果保持不变。
    猜你喜欢
    • 2017-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-30
    • 2019-02-22
    • 2019-02-19
    • 1970-01-01
    相关资源
    最近更新 更多