【问题标题】:all Fragment recreating when a switching through fragments using tablayout使用 tablayout 切换片段时重新创建所有片段
【发布时间】:2018-02-28 20:39:18
【问题描述】:

我正在使用 tablayout 创建一个基于选项卡的应用程序。我没有使用 viewpager。我的逻辑是用户可以创建片段(选项卡),例如在 chrome 中添加选项卡,以便每当用户单击添加按钮时,都会使用片段创建一个新选项卡。现在我需要在共享首选项中保存每个片段创建时间的唯一时间戳,以便每当我移动到一个片段时,我都可以使用该共享参考时间戳值来执行针对该特定片段的唯一功能。

但我不知道在哪里保存该时间戳。我试图在 Fragment 的 Oncreate 函数中获取时间(以毫秒为单位),但是每当我在每次 onCreate 调用时在选项卡之间切换时,每次我在选项卡之间切换时,共享首选项值都会随着我在 Fragments 中的 onCreate 中添加它而改变。

我的逻辑是,它应该只在用户单击添加时创建片段后才创建,并且必须能够在片段中使用它。

每次我切换到其他片段时,它都会重新初始化所有视图并调用 onCreate。所以我无法在 oncreate 中设置时间戳..

请帮帮我

我的活动代码是:

public class TabActivity extends AppCompatActivity{
    public static TabActivity instance;
    private FragmentChild fragmentOne;

    private TabLayout allTabs;
    ImageView add;
    ImageView imageButtonAdd2;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.tab_activity);

        getAllWidgets();
        bindWidgetsWithAnEvent();
        setupTabLayout();

    }
    public static TabActivity getInstance() {
        return instance;
    }
    private void getAllWidgets() {
        allTabs = (TabLayout) findViewById(R.id.simpleTabLayout);
        add = findViewById(R.id.addButton);
        imageButtonAdd2 = findViewById(R.id.imageButtonAdd2);
    }
    private void setupTabLayout() {
        allTabs.addTab(allTabs.newTab().setText("ONE"),true);
        add.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                allTabs.addTab(allTabs.newTab().setText("NEW_TAB"),true);
                bindWidgetsWithAnEvent();
            }
        });
        imageButtonAdd2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /*Bundle bundle = new Bundle();
                bundle.putString("data", String.valueOf(0));
                fragmentSecond = new SecondFragment();
                fragmentSecond.setArguments(bundle);
                replaceFragment(fragmentSecond,"SecondFragment");*/
            }
        });
    }
    private void bindWidgetsWithAnEvent()
    {
        allTabs.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                setCurrentTabFragment(tab.getPosition());
            }
            @Override
            public void onTabUnselected(TabLayout.Tab tab) {
            }
            @Override
            public void onTabReselected(TabLayout.Tab tab) {
            }
        });
    }
    private void setCurrentTabFragment(int tabPosition)
    {
        Bundle bundle = new Bundle();
        bundle.putString("data", String.valueOf(tabPosition));
        fragmentOne = new FragmentChild();
        fragmentOne.setArguments(bundle);
        replaceFragment(fragmentOne,"FirstFragment");
    }
    public void replaceFragment(Fragment fragment, String fragmentName) {
        long time= System.currentTimeMillis();
        FragmentManager fm = getSupportFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        ft.replace(R.id.simpleFrameLayout, fragment,fragmentName);
        //ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
        ft.commit();
    }
    public void backStackFragment(Fragment fragment, String fragmentName) {
        FragmentManager fm = getSupportFragmentManager();
        FragmentTransaction ft = fm.beginTransaction();
        ft.replace(R.id.simpleFrameLayout, fragment,fragmentName);
        ft.addToBackStack(null);
        //ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
        ft.commit();
    }
    @Override
    public void onBackPressed(){
        FragmentManager fm = getSupportFragmentManager();
        if (fm.getBackStackEntryCount() > 0) {
            Log.i("MainActivity", "popping backstack");
            fm.popBackStack();
        } else {
            Log.i("MainActivity", "nothing on backstack, calling super");
            super.onBackPressed();
        }
    }
} 

FragmentChild 类:

public class FragmentChild extends Fragment {
    String childname;
    TextView textViewChildName;
    EditText editText;
    private GridView mGridView;
    private ListItem mListItem;
    private ListView mListview;
    private ProgressBar mProgressBar;
    private ProductViewAdapter mGridAdapter;
    private ListViewAdapter mListAdapter = null;
    private ArrayList<GridItem> mGridData;
    private ArrayList<ListItem> mListData = null;
    ListView listView;
    CheckInterNetConnection check ;
    Boolean isInternetPresent = false;
    PreferenceHelper prefs;
    private TabLayout tabLayout;
    private ViewPagerAdapter adapter;
    public static ViewPager viewPager;
    String posid = "";
    int page =0;
    String title  = "";
    TabLayout allTabs;
    int tab_position = 0;
    long time=0;
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        //GlobalBus.getBus().register(this);
        View view = inflater.inflate(R.layout.fragment_child, container, false);
        Bundle bundle = getArguments();
        childname = bundle.getString("data");
        Log.e("onCreateView","onCreateView");
        getIDs(view);
        setEvents();
        return view;
    }


    // Store instance variables based on arguments passed
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
         time= System.currentTimeMillis();
        page = getArguments().getInt("someInt", 0);
        title = getArguments().getString("someTitle");
        Log.e("onCreate","onCreate");
    }
    private void getIDs(View view) {
        //textViewChildName = (TextView) view.findViewById(R.id.textViewChild);
        //textViewChildName.setText(childname);
        //editText = (EditText) view.findViewById(R.id.editText);
        //editText.setText("");
    }

    private void setEvents() {

    }
    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        Log.e("onViewCreated","onViewCreated");

    }
    @Override
    public void onDestroyView() {
        super.onDestroyView();
        // Unregister the registered event.
        EventBus.getDefault().unregister(this);
    }
    public static FragmentChild newInstance(int page, String title) {
        FragmentChild fragmentFirst = new FragmentChild();
        Bundle args = new Bundle();
        args.putInt("someInt", page);
        args.putString("someTitle", title);
        fragmentFirst.setArguments(args);
        return fragmentFirst;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        Log.e("onActivityCreated","onActivityCreated");
        allTabs = (TabLayout) getActivity().findViewById(R.id.simpleTabLayout);
        mGridView = (GridView) getView().findViewById(R.id.gridView);
        prefs = new PreferenceHelper(getActivity());
        mGridData = new ArrayList<>();
        mGridAdapter = new ProductViewAdapter(getActivity(), R.layout.grid_product_layout, mGridData);
        mGridView.setAdapter(mGridAdapter);

        mListview = (ListView) getView().findViewById(R.id.list);
        mListData = new ArrayList<>();
        mListAdapter = new ListViewAdapter(getActivity(), R.layout.list_row, mListData);
        mListview.setAdapter(mListAdapter);
        adapter = new ViewPagerAdapter(getFragmentManager(), getActivity(), viewPager, tabLayout);
    }
    @Override
    public void onStart() {
        super.onStart();
        Log.e("onStart","onStart");
        EventBus.getDefault().register(this);
        tab_position=allTabs.getSelectedTabPosition();
        //Log.e("TAB ID",String.valueOf(tab_position));
        prefs.save(String.valueOf(tab_position),"tab-"+time);
        check = new CheckInterNetConnection(getActivity());
        isInternetPresent = check.isConnectingToInternet();
        if (isInternetPresent) {
            fetchProducts(tab_position);
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        Log.e("onResume","onResume");
    }

    @Override
    public void onPause() {
        EventBus.getDefault().unregister(this);
        Log.e("onPause","onPause");
        super.onPause();
    }

    @Subscribe
    public void onEvent(GlobalBus event){
        posid = event.getMessage();
        //Toast.makeText(getActivity(), event.getMessage(), Toast.LENGTH_SHORT).show();
    }

    public void fetchProducts(int tabPosition){
        String tabid = prefs.getString(String.valueOf(tabPosition),"0");
        Fragment fragment = getFragmentManager().findFragmentById(R.id.simpleFrameLayout);
        String tag = (String) fragment.getTag();
        //Log.e("URL","http://35.184.41.163/phpmyadmin/app/demo/products.php?tabid="+tabid+"&tab_position="+tabPosition);
        RestClientHelper.getInstance().get("http://35.184.41.163/phpmyadmin/app/demo/products.php", new RestClientHelper.RestClientListener() {
            @Override
            public void onSuccess(String response) {
                parseResult(response);
                mGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                    public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
                        try {
                            ListItem items;
                            GridItem item = (GridItem) parent.getItemAtPosition(position);
                            items = new ListItem();
                            items.setName(item.getTitle());
                            items.setType(item.getDescription());
                            mListData.add(items);
                        }
                        catch(Exception e){

                        }
                        finally {
                            mListAdapter.setGridData(mListData);
                        }
                    }
                });
            }

            @Override
            public void onError(String error) {

            }
        });
    }

    private void parseResult(String result) {
        try {
            JSONObject response = new JSONObject(result);
            JSONArray posts = response.optJSONArray("products");
            GridItem item;
            if(posts.length() <= 0){
                RelativeLayout ly = (RelativeLayout) getView().findViewById(R.id.noOps);
                ly.setVisibility(View.VISIBLE);
            }
            else {
               // RelativeLayout ly = (RelativeLayout)  getView().findViewById(R.id.noOps);
                //ly.setVisibility(View.INVISIBLE);
                mGridData.clear();
                mGridAdapter.setGridData(mGridData);
                for (int i = 0; i < posts.length(); i++) {
                    JSONObject post = posts.optJSONObject(i);
                    String id = post.optString("id");
                    String title = post.optString("name");
                    String description = post.optString("description");
                    String image = post.optString("image");
                    String qty = post.optString("qty");
                    String quantityin = post.optString("quantityin");
                    String price = post.optString("price");

                    item = new GridItem();
                    item.setId(id);
                    item.setTitle(title);
                    item.setDescription(description);
                    item.setImage(image);
                    item.setQuantity(qty);
                    item.setQuantityIn(quantityin);
                    item.setUnitprice(price);
                    mGridData.add(item);
                }
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
        finally {
            mGridAdapter.setGridData(mGridData);
        }
    }
}

更新 @Larry Hsiao 建议的

public class TabActivity extends AppCompatActivity{
    public static TabActivity instance;
    private FragmentChild fragmentOne;
    PreferenceHelper prefs;
    private TabLayout allTabs;
    ImageView add;
    ImageView imageButtonAdd2;
    private final List<Fragment> fragments = new ArrayList<>(); // maintain the instance for switching
    private int currentIndex = 0;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.tab_activity);
        prefs = new PreferenceHelper(TabActivity.this);
        getAllWidgets();
        //bindWidgetsWithAnEvent();
        setupTabLayout();
        bindWidgetsWithAnEvent();

    }
    public static TabActivity getInstance() {
        return instance;
    }
    private void getAllWidgets() {
        allTabs = (TabLayout) findViewById(R.id.simpleTabLayout);
        add = findViewById(R.id.addButton);
        add.performClick();
        imageButtonAdd2 = findViewById(R.id.imageButtonAdd2);
    }
    private void setupTabLayout() {
        int locfirst = allTabs.getSelectedTabPosition();
        locfirst = locfirst+1;
        allTabs.addTab(allTabs.newTab().setText("TAB"+locfirst),true);
        /*long time= System.currentTimeMillis();
        prefs.save("tab_"+locfirst,"tab_"+time);*/
        fragments.add(newFragment(0));
        addFragment(fragments.get(0));
        add.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int loc = allTabs.getSelectedTabPosition();
                loc = loc+1;
                allTabs.addTab(allTabs.newTab().setText("TAB"+loc),true);
                fragments.add(newFragment(loc));
                addFragment(fragments.get(loc));
                /*bindWidgetsWithAnEvent();
                long time= System.currentTimeMillis();
                prefs.save("tab_"+loc,"tab_"+time);*/
            }
        });
        imageButtonAdd2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                /*Bundle bundle = new Bundle();
                bundle.putString("data", String.valueOf(0));
                fragmentSecond = new SecondFragment();
                fragmentSecond.setArguments(bundle);
                replaceFragment(fragmentSecond,"SecondFragment");*/
            }
        });
    }

    private Fragment newFragment(int position) {
        Fragment fragment = new FragmentChild();
        Bundle bundle = new Bundle();
        bundle.putString("position", String.valueOf(position));
        fragment.setArguments(bundle);
        return fragment;
    }


    private void addFragment(Fragment fragment) {
        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        transaction.add(R.id.simpleFrameLayout, fragment);
        transaction.commit();
    }

    private void changingTab(Fragment fragment) {
        FragmentManager manager = getSupportFragmentManager();
        FragmentTransaction transaction = manager.beginTransaction();
        transaction.hide(fragments.get(currentIndex));
        if (manager.getFragments().contains(fragment)) {
            transaction.show(fragment);
        }else {
            transaction.add(R.id.simpleFrameLayout,fragment);
        }
        transaction.commit();
    }

    private void bindWidgetsWithAnEvent()
    {
        allTabs.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                int nextPageIndex = (currentIndex + 1) % 2; // only two fragment switching
                changingTab(fragments.get(nextPageIndex));
                currentIndex = nextPageIndex;
                //setCurrentTabFragment(tab.getPosition());
            }
            @Override
            public void onTabUnselected(TabLayout.Tab tab) {
            }
            @Override
            public void onTabReselected(TabLayout.Tab tab) {
            }
        });
    }
    \
    @Override
    public void onBackPressed(){
        FragmentManager fm = getSupportFragmentManager();
        if (fm.getBackStackEntryCount() > 0) {
            Log.i("MainActivity", "popping backstack");
            fm.popBackStack();
        } else {
            Log.i("MainActivity", "nothing on backstack, calling super");
            super.onBackPressed();
        }
    }
}

此力因以下错误而关闭:

FATAL EXCEPTION: main
                                                                 Process: com.eazypos.app, PID: 13624
                                                                 java.lang.IndexOutOfBoundsException: Invalid index 1, size is 1
                                                                     at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
                                                                     at java.util.ArrayList.get(ArrayList.java:308)
                                                                     at com.eazypos.app.TabActivity$3.onTabSelected(TabActivity.java:115)
                                                                     at android.support.design.widget.TabLayout.dispatchTabSelected(TabLayout.java:1165)
                                                                     at android.support.design.widget.TabLayout.selectTab(TabLayout.java:1158)
                                                                     at android.support.design.widget.TabLayout.selectTab(TabLayout.java:1128)
                                                                     at android.support.design.widget.TabLayout$Tab.select(TabLayout.java:1427)
                                                                     at android.support.design.widget.TabLayout.addTab(TabLayout.java:483)
                                                                     at android.support.design.widget.TabLayout.addTab(TabLayout.java:465)
                                                                     at com.eazypos.app.TabActivity$1.onClick(TabActivity.java:62)
                                                                     at android.view.View.performClick(View.java:4780)
                                                                     at android.view.View$PerformClick.run(View.java:19866)
                                                                     at android.os.Handler.handleCallback(Handler.java:739)
                                                                     at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                     at android.os.Looper.loop(Looper.java:135)

删除标签功能

public void removeTab(int position) {
        Toast.makeText(getActivity(), "REMOVING --> "+position, Toast.LENGTH_SHORT).show();
        prefs.remove("tab_"+position);
        if (allTabs.getChildCount() > 0) {
            allTabs.removeTabAt(position);

        }
    }

【问题讨论】:

    标签: android android-fragments fragmentmanager


    【解决方案1】:

    要只保存一次值.. 在timeStamp 中的shared prefs 中,只需在每个片段中使用它..

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
    
        if (getActivity() == null)
        {
    
            // generate time stamp in miliseconds as you are doing 
            // and save it in shared prefs 
            // this will be called only once..
        }
    }
    

    或者你可以试试:-

    更新 onCreate of fragmentChild

       time= System.currentTimeMillis();
       SharedPreferences sharedPreferences = getActivity().getSharedPreferences("My_prefs_name",Context.MODE_PRIVATE);
            String timeStamp = sharedPreferences.getString("timeStamp","");
    
            if ( timeStamp.isEmpty())
            {
                // SAVE TIME IN SHAREPREFS
                sharedPreferences.edit().putString("timeStamp",time).apply();
    
            }
    

    【讨论】:

    • 您是否尝试将其保存为onCreateView
    • 是的.. onCreateView 在每次用户切换选项卡时调用。 onclick 它创建相同的子片段
    • @KarthikCp 你也可以尝试一件事。if( ! timeStamp_present _in_shared_pref) { save timestamp }
    • 我明白了.. 使用这个逻辑.. 因为我已经更新了.. 如果它有效,请更新@KarthikCp 如果您需要帮助理解.. 我会更新答案.. !!
    • 能否请您更新代码,以便我可以得到清晰的图片
    【解决方案2】:

    您应该维护您已经创建的 Fragment 实例。 (使用 FragmentManager 或仅将其与变量一起保存可能会完成这项工作)

    Activity 中的 setCurrentTabFragment() 方法创建新的 Fragment 会在用户每次点击 tab 时被调用。结果,片段总是通过 onCreate()

    // this method invoke every time user click the tab
    private void setCurrentTabFragment(int tabPosition){
        Bundle bundle = new Bundle();
        bundle.putString("data", String.valueOf(tabPosition));
        fragmentOne = new FragmentChild(); // creating new Fragment
        fragmentOne.setArguments(bundle);
        replaceFragment(fragmentOne,"FirstFragment");
    }
    

    已编辑:

    • 使用 List 来维护我们已经创建的 Fragment 实例。
    • 使用 FragmentManager 提供的 hide()/show() 切换 Fragment,如果之前未将 Fragment 添加到 FragmentManager,则使用 add()。

    示例代码:

    public class MainActivity extends AppCompatActivity {
        private final List<Fragment> fragments = new ArrayList<>();
        private int currentIndex = 0;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            final TabLayout tabLayout = findViewById(R.id.tabLayout);
    
            // initial with one page
            Fragment firstFragment = newFragment(0);
            fragments.add(firstFragment);
            addFragment(firstFragment);
            tabLayout.addTab(tabLayout.newTab().setText("Initial tab"));
    
            // user events
            findViewById(R.id.main_createTab).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    fragments.add(newFragment(tabLayout.getTabCount()));
                    tabLayout.addTab(tabLayout.newTab().setText("Pages " + tabLayout.getTabCount()));
                }
            });
    
            tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
                @Override
                public void onTabSelected(TabLayout.Tab tab) {
                    int nextPageIndex = tab.getPosition();
                    if (currentIndex == nextPageIndex){
                        return;
                    }
                    changingTab(fragments.get(nextPageIndex));
                    currentIndex = nextPageIndex;
                }
                @Override public void onTabUnselected(TabLayout.Tab tab) {}
                @Override public void onTabReselected(TabLayout.Tab tab) {}
            });
        }
    
        private Fragment newFragment(int position) {
            Fragment fragment = new FragmentWithLog();
            Bundle bundle = new Bundle();
            bundle.putString("position", String.valueOf(position));
            fragment.setArguments(bundle);
            return fragment;
        }
    
        private void addFragment(Fragment fragment) {
            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
            transaction.add(R.id.main_fragmentFrame, fragment);
            transaction.commit();
        }
    
        private void changingTab(Fragment fragment) {
            FragmentManager manager = getSupportFragmentManager();
            FragmentTransaction transaction = manager.beginTransaction();
            transaction.hide(fragments.get(currentIndex));
            if (manager.getFragments().contains(fragment)) {
                transaction.show(fragment);
            } else {
                transaction.add(R.id.main_fragmentFrame, fragment);
            }
            transaction.commit();
        }
    }
    

    【讨论】:

    • 没有切换标签的按钮!用户单击选项卡以导航到该选项卡。
    • 在示例代码中,是的,我使用一个按钮来展示它是如何工作的。只需将按钮替换为您的实现即可捕获用户事件。
    • 但是切换标签是使用allTabs.addOnTabSelectedListener捕获的吧?
    • 是的,listeners onTabSelected() invoked when user click the tab, It is similar as Buttons onClick()。顺便说一句,您只需将 onTabSelectedListener 添加到 tabLayout 一次。无需每次创建选项卡时添加监听器。侦听器用于 TabLayout,而不仅仅是选项卡之一。
    • fragments.add(newFragment(0)); 这会创建新的片段,对吗?所以在我的添加按钮 onclick 监听器中,我可以在创建选项卡后添加它?
    猜你喜欢
    • 2019-08-21
    • 2016-02-18
    • 2019-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-07
    • 1970-01-01
    • 2012-04-21
    相关资源
    最近更新 更多