添加/删除页面时,Android FragmentStatePagerAdapter无法正确更新ViewPager

时间:2018-07-09 16:11:20

标签: java android android-viewpager fragmentstatepageradapter

我正在尝试创建一个带有标签的浏览器,您可以轻松地在其中添加,删除和滑动这些标签。目前,我有一个ViewPager,每个分页的片段都包含一个WebView和一些按钮。

问题是添加或删除标签后,我似乎无法可靠地更新ViewPager。我相信这部分是由FragmentStatePagerAdapter中的错误引起的,但是解决方法似乎不适用于我的用例,或者我无法实现它们(我是Android + Java noob)。

理想情况下,添加和删除选项卡不会导致不必要地重新加载任何页面/选项卡中的WebView。至少它们需要恢复到以前的状态。

当前,存在两个具体问题:

  • 在特定位置添加选项卡会在最后一页上显示空白片段。如果我在末尾添加了新标签,就可以了。

  • 正确删除标签页会更新标签页,但是如果之后添加新标签页,我会在最后一页看到完全空白的片段。

这是我的适配器代码:

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.app.FragmentTransaction;
import android.view.ViewGroup;

import java.util.ArrayList;

public class BrowserTabRepository extends FragmentStatePagerAdapter {

public Browser browser;

public ArrayList<BrowserTabFragment> mFragmentList = new ArrayList<BrowserTabFragment>();
public boolean removing;

public BrowserTabRepository(FragmentManager fm, Browser browser) {
    super(fm);
    this.browser = browser;
}

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

@Override
public BrowserTabFragment getItem(int position) {
    return mFragmentList.get(position);
}

public boolean hasItem(int position) {
    return position < mFragmentList.size();
}

public void clearAllItems() {
    mFragmentList.clear();
    this.notifyDataSetChanged();
}

public void updateItem(int position, BrowserTabFragment fragment) {
    mFragmentList.set(position, fragment);
    notifyDataSetChanged();
}

@Override
public int getItemPosition(Object object) {
    // if(removing)return POSITION_NONE; workaround/hack I found. Tabs don't get messed up but the adapter incorrectly returns the state of the fragment that has just been deleted instead of the one replacing it
    if (mFragmentList.contains(object)) {
        final int index = mFragmentList.indexOf(object);
        return index;
    }
    return POSITION_NONE;
}

public void removeBrowserTab(int position, BrowserTabViewPager viewPager) {
    BrowserTabFragment fragment = mFragmentList.get(position);
    if (fragment != null) {
        removing = true;
        //fragment.isBeingRemoved = true;
        mFragmentList.remove(fragment);
        destroyFragmentView(viewPager, position, fragment);

        notifyDataSetChanged();
        removing = false;
    }
    ;
}

protected void destroyFragmentView(ViewGroup container, int position, Object object) {
    FragmentManager manager = ((Fragment) object).getFragmentManager();
    FragmentTransaction trans = manager.beginTransaction();
    trans.remove((Fragment) object);
    trans.commit();
}

@Override
public int getCount() {
    return mFragmentList.size();
}

public void addBrowserTab(BrowserTabFragment fragment, int positionToAdd) {
    mFragmentList.add(positionToAdd, fragment);
    notifyDataSetChanged();
}

public void addBrowserTab(BrowserTabFragment fragment) {
    mFragmentList.add(fragment);
    notifyDataSetChanged();
}
}

以下是在我的主要活动中创建adapter + viewpager的代码:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_browser);
    browserTabRepository = new BrowserTabRepository(this.getSupportFragmentManager(), this);
    viewPager = (BrowserTabViewPager) findViewById(R.id.viewPagerContainer);
    viewPager.setAdapter(browserTabRepository);
    viewPager.setSaveFromParentEnabled(false);
    viewPager.setOffscreenPageLimit(2); // how many tabs can be held in memory!
}

以下是该片段中可能相关的生命周期代码:

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
}

@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
    super.onSaveInstanceState(outState);
    webView.saveState(outState); // save state of web view when it is  paused (in background, rotated etc)
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    rootView = inflater.inflate(R.layout.fragment_browser, container, false);
    webView = (CustomWebView) rootView.findViewById(R.id.activity_main_webview);
    // ... load tab buttons, configure web view and other stuff ...
    if(startingPageAddress!=null){
        goToAddressOrSearchString(startingPageAddress);
        startingPageAddress = null;
    }else if(savedInstanceState!=null) {
        webView.restoreState(savedInstanceState); // restore state of bundle
    }
    return rootView;
}

1 个答案:

答案 0 :(得分:0)

我最终放弃了这种方法,因为它是FragmentStatePagerAdapter的一个长期存在的错误,我无法修复100%的高度动态制表符。

我发现一个更好的解决方案是切换到使用RecyclerView + PagerSnapHelper + RecyclerView.Adapter,因为它的工作原理与消除错误的方式几乎相同