Android如何在标签更改时停止刷新片段

时间:2015-02-13 07:36:58

标签: java android android-fragments android-viewpager android-lifecycle

我有以下代码:

MainActivity.java

package com.erc.library;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;

import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.FragmentTransaction;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Environment;
import android.os.StrictMode;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.TextView;
import android.widget.Toast;

import com.erc.sayeghlibrary.adapter.TabsPagerAdapter;

public class MainActivity extends FragmentActivity implements
        ActionBar.TabListener {

    private ViewPager viewPager;
    private TabsPagerAdapter mAdapter;
    private ActionBar actionBar;
    // Tab titles
    private String[] tabs = { "Stories", "Dictionaries", "eBooks"};

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






        int actionBarTitleId = Resources.getSystem().getIdentifier("action_bar_title", "id", "android");
        if (actionBarTitleId > 0) {
            TextView title = (TextView) findViewById(actionBarTitleId);
            if (title != null) {
                title.setTextColor(Color.WHITE);
            }
        }       

        // Initilization
        viewPager = (ViewPager) findViewById(R.id.pager);
        actionBar = getActionBar();
        mAdapter = new TabsPagerAdapter(getSupportFragmentManager());

        viewPager.setAdapter(mAdapter);
        actionBar.setHomeButtonEnabled(false);
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);


        // Adding Tabs
        for (String tab_name : tabs) {
            actionBar.addTab(actionBar.newTab().setText(tab_name)
                    .setTabListener(this));
        }

        /**
         * on swiping the viewpager make respective tab selected
         * */
        viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {

            @Override
            public void onPageSelected(int position) {
                // on changing the page
                // make respected tab selected
                actionBar.setSelectedNavigationItem(position);
            }

            @Override
            public void onPageScrolled(int arg0, float arg1, int arg2) {
            }

            @Override
            public void onPageScrollStateChanged(int arg0) {
            }
        });







    }

    @Override
    public void onTabReselected(Tab tab, FragmentTransaction ft) {
    }

    @Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        // on tab selected
        // show respected fragment view
        viewPager.setCurrentItem(tab.getPosition());


    }

    @Override
    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
    }






       @Override
       public boolean onCreateOptionsMenu(Menu menu) {
         MenuInflater inflater = getMenuInflater();
         inflater.inflate(R.menu.main, menu);
         return true;
       } 




       @Override
       public boolean onOptionsItemSelected(MenuItem item) {
         switch (item.getItemId()) {
         // action with ID action_refresh was selected
         case R.id.Favorites:
           Toast.makeText(this, "Favorites selected", Toast.LENGTH_SHORT)
               .show();
           break;
         // action with ID action_settings was selected

         default:
           break;
         }

         return true;
       } 


}

TabsPagerAdapter.java

package com.erc.library.adapter;

import com.erc.library.Dictionaries;
import com.erc.library.Ebooks;
import com.erc.library.Stories;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;

public class TabsPagerAdapter extends FragmentPagerAdapter {

    public TabsPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int index) {

        switch (index) {
        case 0:

            return new Stories();
        case 1:

            return new Dictionaries();
        case 2:
            // Movies fragment activity
            return new Ebooks();
        }

        return null;
    }

    @Override
    public int getCount() {
        // get item count - equal to number of tabs
        return 3;
    }

}

我正在制作一个库应用程序,其中导航是通过制表符,问题是每次我从第三个选项卡转到第一个或第一个到第三个,选项卡内容是刷新的,我想阻止刷新,请帮忙吗?

7 个答案:

答案 0 :(得分:100)

默认情况下,ViewPager会在您滑动页面时重新创建片段。为了防止这种情况,您可以尝试以下两种方法之一:

1。在您片段的onCreate()中,拨打setRetainInstance(true)

2. 如果片段数量固定且&相对较小,然后在onCreate()添加以下代码:

mViewPager = (ViewPager)findViewById(R.id.pager);
mViewPager.setOffscreenPageLimit(limit);         /* limit is a fixed integer*/

如果我没记错的话,第二种选择更有希望。但我敦促你们两个都试试,看看哪个有效。

答案 1 :(得分:21)

首先必须以FragmentPagerAdapter为例,然后.getCount()将返回值 -

应将.getCount() - 1设置为默认的屏幕外限制:

TabsPagerAdapter adapter = new TabsPagerAdapter(getSupportFragmentManager());

/* the ViewPager requires a minimum of 1 as OffscreenPageLimit */
int limit = (adapter.getCount() > 1 ? adapter.getCount() - 1 : 1);

ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(limit);

答案 2 :(得分:4)

您可以通过检查视图是否为空来处理视图重新创建

WhenAll

答案 3 :(得分:3)

在片段的onCreate()中,调用setRetainInstance(true)

答案 4 :(得分:2)

这个问题有点晚了,但感谢Y.S.,了解了ViewPager的工作原理。我正在构建一个带有4个选项卡的应用程序,并且在任何时候都注意到只刷新了两个选项卡,我认为这是默认行为。经过几个小时的调查,我了解Android刷新了多个标签,为用户带来了平滑的滑动性能 - 你可能会注意到你会点击tab2,但是android会为tab3引入数据并保持准备就绪。

虽然这种行为很好,但它有其优点和缺点。优点 - 您可以获得平滑的滑动体验,当您在该选项卡中登陆时,无需从外部服务器加载数据。缺点 - 选项卡中的backstack实现可能需要折腾。当您单击选项卡时,视图寻呼机实际上会调用更平滑的选项卡,如果您的方法是根据单击选项卡中的Backstack中的内容在左上角设置backarrow(home),则最终会遇到大麻烦。

setOffscreenPageLimit就是答案。如果希望自定义backstack框架起作用,并且在单击tab2时不希望调用tab3,则只需将值设置为选项卡数。例如,如果您有4个选项卡,请设置setOffScreePageLimit(4)。这意味着Android最初会刷新所有4个片段,这是一个性能开销(你应该妥善管理)。但是,您的背板和标签切换保持不变。希望这会有所帮助。

答案 5 :(得分:1)

由于活动实现了ActionBar.TabListener,因此一次又一次地调用活动的onCreate()。所以将以下代码放在onResume()方法中:

   // Initilization
    viewPager = (ViewPager) findViewById(R.id.pager);
    actionBar = getActionBar();
    mAdapter = new TabsPagerAdapter(getSupportFragmentManager());

    viewPager.setAdapter(mAdapter);
    actionBar.setHomeButtonEnabled(false);
    actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);


    // Adding Tabs
    for (String tab_name : tabs) {
        actionBar.addTab(actionBar.newTab().setText(tab_name)
                .setTabListener(this));
    }

    /**
     * on swiping the viewpager make respective tab selected
     * */
    viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {

        @Override
        public void onPageSelected(int position) {
            // on changing the page
            // make respected tab selected
            actionBar.setSelectedNavigationItem(position);
        }

        @Override
        public void onPageScrolled(int arg0, float arg1, int arg2) {
        }

        @Override
        public void onPageScrollStateChanged(int arg0) {
        }
    });

答案 6 :(得分:0)

在我的情况下,上述建议不起作用。

限制片段的重新创建,我做了什么:

onCreateView中,您可以将膨胀的视图存储在全局变量中,只有在null时才对其进行初始化,如下所示:

    var root:View?=null
    var apiDataReceived=false
 override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?,
                          savedInstanceState: Bundle?): View? {
    // Inflate the layout for this fragment
    if (root==null)
        root=inflater!!.inflate(R.layout.fragment_layout, container, false)
    return root
}

现在,如果您正在解析某些数据并将其填入RecyclerView或任何其他View

  1. 制作一个全局变量,如上面的代码apiDataReceived

  2. 如果您成功解析数据,请将其设置为true。

  3. 在apiCalls之前设置这样的条件:

    if(!apiDataReceived){ APICALLS() }

  4. 因此,只有在未解析数据时才会调用apiCalls()。

    您的http调用和解析或在onCreateView onStart之后调用的方法中的任何其他内容

    以上代码在kotlin中,如果您遇到任何问题,请在评论中告诉我。