Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/217.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android Viewpager:如果页面被删除,则下一页内容将获得删除的页面内容_Android_Adapter_Android Fragments_Android Viewpager - Fatal编程技术网

Android Viewpager:如果页面被删除,则下一页内容将获得删除的页面内容

Android Viewpager:如果页面被删除,则下一页内容将获得删除的页面内容,android,adapter,android-fragments,android-viewpager,Android,Adapter,Android Fragments,Android Viewpager,(如果有人需要更多信息或更好的描述,请告诉我) 您好,我在我的项目中包括了viewPagerLibrary from here:today 不,我遇到了一个非常奇怪的问题: 如果我添加一个站点或页面(在接下来的几行中我们称之为站点)并再次删除它,一切都正常。但是如果我尝试添加一个不同的页面(这些页面是实现BaseFragment类的不同Fragements),则会显示第一个页面的内容。 如果我在这些页面之间添加几页并删除其中一页,也会发生同样的情况。删除页面之后的页面现在显示已删除页面的内容 此

(如果有人需要更多信息或更好的描述,请告诉我)

您好,我在我的项目中包括了viewPagerLibrary from here:today

不,我遇到了一个非常奇怪的问题: 如果我添加一个站点或页面(在接下来的几行中我们称之为站点)并再次删除它,一切都正常。但是如果我尝试添加一个不同的页面(这些页面是实现BaseFragment类的不同Fragements),则会显示第一个页面的内容。 如果我在这些页面之间添加几页并删除其中一页,也会发生同样的情况。删除页面之后的页面现在显示已删除页面的内容

此错误的示例: 现在的问题是。如果我在FragmentB之后添加FragmentA,那么我将删除FragmentA,FragmentB将获得FragmentA的视图/内容。奇怪的是,对象是正确的(因此适配器返回正确的对象),标题也是正确的

在我的主页中,我通过以下方式创建寻呼机、指示器和适配器:

    Cfg.mAdapter = new FragmentAdapter(getSupportFragmentManager());

    Cfg.mPager = (ViewPager)findViewById(R.id.pager);
    Cfg.mPager.setAdapter(Cfg.mAdapter);

    Cfg.mIndicator = (TabPageIndicator)findViewById(R.id.indicator);
    Cfg.mIndicator.setViewPager(Cfg.mPager);

    //We set this on the indicator, NOT the pager
    Cfg.mIndicator.setOnPageChangeListener(TabHelper.onPageChangeListener);
(Cfg是一个静态文件,用于存储这些内容以供使用)

我的BaseFragment如下所示:

public class BaseFragment extends Fragment{

    public static int FILE_FRAGMENT = 0;
    public static int FTP_FRAGMENT = 1;
    public static int ADDFTP_FRAGMENT = 2;
    public static int PREVIEW_FRAGMENT = 3;
    public static int CSS_FRAGMENT = 4;
    public static int BOOKS_FRAGMENT = 5;
    public static int SNIPPETS_FRAGMENT = 6;

    //private int id;
    private int typ;
    private String title;

    public int getTyp() {
        return typ;
    }

    public void setTyp(int typ) {
        this.typ = typ;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}
其中一个片段看起来像这样(我认为其他片段没有区别):

这就是适配器:

public class FragmentAdapter extends FragmentPagerAdapter implements TitleProvider{
    public List<BaseFragment> fragments = new LinkedList<BaseFragment>();

    private int actPage;

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


    public void setActPage(int actPage) {
        Lg.d("setActPage: " + actPage + " : " + fragments.get(actPage).toString());
        this.actPage = actPage; 
    }

    public void addItem(BaseFragment fragment)
    {
        Lg.d("addItem: " + fragment.toString());
        fragments.add(fragment);
    }

    public void removeItem(int index)
    {
        if(index < getCount()){
            Lg.d("RemoveItem: " + index + " : " + fragments.get(index).toString());
            fragments.remove(index);
        }
    }

    public BaseFragment getActFragment()
    {
        return getItem(getActPage());
    }

    public int getActPage() {
        return actPage;
    }

    @Override
    public BaseFragment getItem(int position) {
        if(position < getCount())
        {
            Lg.v("getItem: " + fragments.get(position));
            return fragments.get(position);
        }
        else
            return null;
    }

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

    @Override
    public String getTitle(int position) {
        Lg.v("Get Title: " + fragments.get(position).getTitle());
        return fragments.get(position).getTitle();
    }

}
公共类FragmentAdapter扩展FragmentPagerAdapter实现TitleProvider{
public List fragments=new LinkedList();
私人网页;
公共碎片适配器(碎片管理器fm){
超级(fm);
}
公共无效setActPage(内部actPage){
Lg.d(“setActPage:+actPage+:”+fragments.get(actPage.toString());
this.actPage=actPage;
}
public void addItem(BaseFragment片段)
{
Lg.d(“addItem:+fragment.toString());
片段。添加(片段);
}
公共void removietem(int索引)
{
if(索引
是的,我希望有人能帮我

如果我忘了什么,让我知道

提前感谢,, Mike

在您的答案中(由mikepenz编写),您不需要再次设置适配器。您可以调用notifyDataSetChanged

public static void deleteActTab(){

        //We set this on the indicator, NOT the pager
        int act = Cfg.mPager.getCurrentItem();
        Cfg.mAdapter.removeItem(act);        


        if(act > 0)
        {
            Cfg.mPager.setCurrentItem(act-1);
            Cfg.mIndicator.setCurrentItem(act-1);
        }
       //Also add conditions to check if there are any remaining fragments


        Cfg.mIndicator.notifyDataSetChanged();
}

您是否考虑过使用< HashMap > <代码>或<代码> ArrayAdapter <代码>来改进性能或已经使用它?


另外,为什么在BaseFragment中使用静态方法?请考虑使用MAT或LogCAT检查内存使用情况,如果这些内存泄漏。

< P> OK,我现在已经用一种杂乱无章的方式解决了我的问题,但它是有效的。如果有人能改进我的解决方案,请让我知道。对于我的新解决方案,我现在使用CustomFragmentStatePagerAdapter,但它并没有像应该的那样保存状态,而是将所有片段存储在一个列表中。如果用户有超过50个片段,这可能会导致内存问题,就像正常的FragmentPagerAdapter一样。如果有人能够在不删除我的修复程序的情况下将状态添加回我的解决方案,那就太好了。谢谢

下面是我的CustomFragmentStatePagerAdapter.java

package com.tundem.webLab.Adapter;

import java.util.ArrayList;

import android.os.Bundle;
import android.os.Parcelable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.PagerAdapter;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;

public abstract class CustomFragmentStatePagerAdapter extends PagerAdapter {
    private static final String TAG = "FragmentStatePagerAdapter";
    private static final boolean DEBUG = false;

    private final FragmentManager mFragmentManager;
    private FragmentTransaction mCurTransaction = null;

    public ArrayList<Fragment.SavedState> mSavedState = new ArrayList<Fragment.SavedState>();
    public ArrayList<Fragment> mFragments = new ArrayList<Fragment>();
    private Fragment mCurrentPrimaryItem = null;

    public CustomFragmentStatePagerAdapter(FragmentManager fm) {
        mFragmentManager = fm;
    }

    /**
     * Return the Fragment associated with a specified position.
     */
    public abstract Fragment getItem(int position);

    @Override
    public void startUpdate(ViewGroup container) {}

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        // If we already have this item instantiated, there is nothing
        // to do. This can happen when we are restoring the entire pager
        // from its saved state, where the fragment manager has already
        // taken care of restoring the fragments we previously had instantiated.

        // DONE Remove of the add process of the old stuff
        /* if (mFragments.size() > position) { Fragment f = mFragments.get(position); if (f != null) { return f; } } */

        if (mCurTransaction == null) {
            mCurTransaction = mFragmentManager.beginTransaction();
        }

        Fragment fragment = getItem(position);
        if (DEBUG)
            Log.v(TAG, "Adding item #" + position + ": f=" + fragment);
        if (mSavedState.size() > position) {
            Fragment.SavedState fss = mSavedState.get(position);
            if (fss != null) {
                try // DONE: Try Catch
                {
                    fragment.setInitialSavedState(fss);
                } catch (Exception ex) {
                    // Schon aktiv (kA was das heißt xD)
                }
            }
        }
        while (mFragments.size() <= position) {
            mFragments.add(null);
        }
        fragment.setMenuVisibility(false);
        mFragments.set(position, fragment);
        mCurTransaction.add(container.getId(), fragment);

        return fragment;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        Fragment fragment = (Fragment) object;

        if (mCurTransaction == null) {
            mCurTransaction = mFragmentManager.beginTransaction();
        }
        mCurTransaction.remove(fragment);

        /*if (mCurTransaction == null) { mCurTransaction = mFragmentManager.beginTransaction(); } if (DEBUG) Log.v(TAG, "Removing item #" + position + ": f=" + object + " v=" + ((Fragment)
         * object).getView()); while (mSavedState.size() <= position) { mSavedState.add(null); } mSavedState.set(position, mFragmentManager.saveFragmentInstanceState(fragment));
         * mFragments.set(position, null); mCurTransaction.remove(fragment); */
    }

    @Override
    public void setPrimaryItem(ViewGroup container, int position, Object object) {
        Fragment fragment = (Fragment) object;
        if (fragment != mCurrentPrimaryItem) {
            if (mCurrentPrimaryItem != null) {
                mCurrentPrimaryItem.setMenuVisibility(false);
            }
            if (fragment != null) {
                fragment.setMenuVisibility(true);
            }
            mCurrentPrimaryItem = fragment;
        }
    }

    @Override
    public void finishUpdate(ViewGroup container) {
        if (mCurTransaction != null) {
            mCurTransaction.commitAllowingStateLoss();
            mCurTransaction = null;
            mFragmentManager.executePendingTransactions();
        }
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return ((Fragment) object).getView() == view;
    }

    @Override
    public Parcelable saveState() {
        Bundle state = null;
        if (mSavedState.size() > 0) {
            state = new Bundle();
            Fragment.SavedState[] fss = new Fragment.SavedState[mSavedState.size()];
            mSavedState.toArray(fss);
            state.putParcelableArray("states", fss);
        }
        for (int i = 0; i < mFragments.size(); i++) {
            Fragment f = mFragments.get(i);
            if (f != null) {
                if (state == null) {
                    state = new Bundle();
                }
                String key = "f" + i;
                mFragmentManager.putFragment(state, key, f);
            }
        }
        return state;
    }

    @Override
    public void restoreState(Parcelable state, ClassLoader loader) {
        if (state != null) {
            Bundle bundle = (Bundle) state;
            bundle.setClassLoader(loader);
            Parcelable[] fss = bundle.getParcelableArray("states");
            mSavedState.clear();
            mFragments.clear();
            if (fss != null) {
                for (int i = 0; i < fss.length; i++) {
                    mSavedState.add((Fragment.SavedState) fss[i]);
                }
            }
            Iterable<String> keys = bundle.keySet();
            for (String key : keys) {
                if (key.startsWith("f")) {
                    int index = Integer.parseInt(key.substring(1));
                    Fragment f = mFragmentManager.getFragment(bundle, key);
                    if (f != null) {
                        while (mFragments.size() <= index) {
                            mFragments.add(null);
                        }
                        f.setMenuVisibility(false);
                        mFragments.set(index, f);
                    } else {
                        Log.w(TAG, "Bad fragment at key " + key);
                    }
                }
            }
        }
    }
}
package com.tundem.webLab.Adapter;

import java.util.LinkedList;
import java.util.List;

import android.support.v4.app.FragmentManager;

import com.tundem.webLab.fragments.BaseFragment;
import com.viewpagerindicator.TitleProvider;

public class FragmentAdapter extends CustomFragmentStatePagerAdapter implements TitleProvider {
    public List<BaseFragment> fragments = new LinkedList<BaseFragment>();

    private int actPage;

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

    public void setActPage(int actPage) {
        this.actPage = actPage;
    }

    public void addItem(BaseFragment fragment) {
        // TODO if exists don't open / change to that tab
        fragments.add(fragment);
    }

    public BaseFragment getActFragment() {
        return getItem(getActPage());
    }

    public int getActPage() {
        return actPage;
    }

    @Override
    public BaseFragment getItem(int position) {
        if (position < getCount()) {
            return fragments.get(position);
        } else
            return null;
    }

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

    @Override
    public String getTitle(int position) {
        return fragments.get(position).getTitle();
    }

    @Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }
}
Cfg的描述。事情我将对这些对象的引用保存在一个cfg类中,这样我就可以始终使用它们,而无需特殊的Factory.java

嗯。我希望我能帮上忙。请随意改进,但请让我知道,这样我也可以改进我的代码

谢谢

如果我遗漏了任何代码,请告诉我


我以前的答案也适用,但前提是你有不同的片段。FileFragment,WebFragment。。。如果您两次使用其中一种碎片类型,则不会

我现在的工作是假的。这是一个非常肮脏的解决方案,我仍在寻找更好的解决方案。请帮忙

我更改了代码,将其中的一个选项卡删除为:

   public static void deleteActTab()
        {   
            //We set this on the indicator, NOT the pager
            int act = Cfg.mPager.getCurrentItem();
            Cfg.mAdapter.removeItem(act);
            List<BaseFragment> frags = new LinkedList<BaseFragment>();
            frags = Cfg.mAdapter.fragments;

            Cfg.mPager = (ViewPager)Cfg.act.findViewById(R.id.pager);
            Cfg.mPager.setAdapter(Cfg.mAdapter);
            Cfg.mIndicator.setViewPager(Cfg.mPager);

            Cfg.mAdapter.fragments = frags;

            if(act > 0)
            {
                Cfg.mPager.setCurrentItem(act-1);
                Cfg.mIndicator.setCurrentItem(act-1);
            }

            Cfg.mIndicator.notifyDataSetChanged();
        }
公共静态void deleteActTab()
{   
//我们是在指示灯上设置的,不是在传呼机上
int act=Cfg.mPager.getCurrentItem();
Cfg.mAdapter.removietem(法案);
List frags=newlinkedlist();
frags=Cfg.mAdapter.fragments;
Cfg.mPager=(ViewPager)Cfg.act.findViewById(R.id.pager);
Cfg.mPager.setAdapter(Cfg.mAdapter);
Cfg.mIndicator.setViewPager(Cfg.mPager);
Cfg.mAdapter.fragments=碎片;
如果(动作>0)
{
Cfg.mPager.setCurrentItem(act-1);
Cfg.mIndicator.setCurrentItem(act-1);
}
Cfg.mIndicator.notifyDataSetChanged();
}
如果有人可以改进此代码,请告诉我。如果有人能告诉我们这个问题的真正答案。请加在这里。很多人都经历过这个问题。我为解决这个问题的人增加了50的声望。我也可以为解决问题的人捐款


谢谢

要避免此问题,您必须从backbackback中删除指定的片段。每次从列表中删除片段时,它都会保留在backstack中,因此内容将保留。在从列表中删除片段之前,必须使用FragmentTransaction删除页面。那么代码可能是这样的

public void removePage(int currentPage) {
    for (int i = pageFragmentList.size() - 1; i >= currentPage; i--) {
        ((MainActivity) context).getSupportFragmentManager().beginTransaction()
                .remove(pageFragmentList.get(i)).commit();
    }
    pageFragmentList.remove(currentPage);
}
如果不删除在
    int act = Cfg.mPager.getCurrentItem();
    Cfg.mPager.removeAllViews();
    Cfg.mAdapter.mFragments.remove(act);
    try {
        Cfg.mAdapter.mSavedState.remove(act);
    } catch (Exception ex) {/* Already removed */}
    try {
        Cfg.mAdapter.fragments.remove(act);
    } catch (Exception ex) {/* Already removed */}

    Cfg.mAdapter.notifyDataSetChanged();
    Cfg.mIndicator.notifyDataSetChanged();
   public static void deleteActTab()
        {   
            //We set this on the indicator, NOT the pager
            int act = Cfg.mPager.getCurrentItem();
            Cfg.mAdapter.removeItem(act);
            List<BaseFragment> frags = new LinkedList<BaseFragment>();
            frags = Cfg.mAdapter.fragments;

            Cfg.mPager = (ViewPager)Cfg.act.findViewById(R.id.pager);
            Cfg.mPager.setAdapter(Cfg.mAdapter);
            Cfg.mIndicator.setViewPager(Cfg.mPager);

            Cfg.mAdapter.fragments = frags;

            if(act > 0)
            {
                Cfg.mPager.setCurrentItem(act-1);
                Cfg.mIndicator.setCurrentItem(act-1);
            }

            Cfg.mIndicator.notifyDataSetChanged();
        }
public void removePage(int currentPage) {
    for (int i = pageFragmentList.size() - 1; i >= currentPage; i--) {
        ((MainActivity) context).getSupportFragmentManager().beginTransaction()
                .remove(pageFragmentList.get(i)).commit();
    }
    pageFragmentList.remove(currentPage);
}