18

我创建了一个FragmentStatePagerAdapter用于提供小画廊的活动。但是,当活动恢复时(例如,从其他活动回来后),我无法让它刷新。每次前两张图片都是空白的,只有在我将两张图片滑到一边后,它们才会刷新。我找到的答案都没有(尤其是压倒一切的getItemPosition()

我是这样设置的:

mPagerAdapter = new PhotosPagerAdapter(getSupportFragmentManager());
mPager = (ViewPager) findViewById(R.id.photosViewPager);
mPager.setAdapter(mPagerAdapter);

然后我有 FragmentStatePagerAdapter 类:

private class PhotosPagerAdapter extends FragmentStatePagerAdapter{

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

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

    @Override
    public Fragment getItem(int position) {
        ImageFragment f = new ImageFragment(position);
        return f;
    }

    @Override
    public int getItemPosition(Object object) {
        throw new RuntimeException();
        //return POSITION_NONE;
    }

}

您可能已经注意到,我在 getItemPosition 中抛出 RuntimeException,因为我想检查它何时被调用。直到我添加一些包含我的图片的列表时才会调用它。然后 ImageFragment 类:

public class ImageFragment extends Fragment{

    int position;
    Bitmap mBitmap;
    int width;
    int height;
    ImageView img;

    public ImageFragment(){
    }

    public ImageFragment(int position){
        this.position = position;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

        img = new ImageView(container.getContext());
        img.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
        width = container.getWidth();
        height = container.getHeight();

        loadBitmap();

        return img;
    }       

    public void loadBitmap(){
        if (img == null){
            return;
        }
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(photos.get(position), options);
        options.inSampleSize = calculateInSampleSize(options, width/2, height/2);
        options.inJustDecodeBounds = false;
        mBitmap = BitmapFactory
                .decodeFile(photos.get(position), options);         

        img.setImageBitmap(mBitmap);
    }


    @Override
    public void onDestroyView() {
        mBitmap.recycle();
        super.onDestroyView();
    }       
}

在我尝试修复它之后代码有点乱......但是:删除onDestroyView()不起作用。我已经放置mPagerAdapter.notifyDataSetChanged()了几个必须调用的地方(如onResume()),但没有结果。我对此有点绝望。

4

4 回答 4

37

处理片段寻呼机适配器可以是 PITA。

以下是一些有用的提示:

ViewPager PagerAdapter 不更新视图

动态更新 ViewPager?

一般来说,这个工作99%的时间......

像这样覆盖 PagerAdapter 中的 getItemPosition:

@Override
public int getItemPosition(Object object) {
    return POSITION_NONE;
}

有时即使那些不起作用,我必须使用“蛮力”方法并再次重新创建整个视图(从 onCreate 开始)......

于 2012-12-04T04:12:38.323 回答
4

我遇到了与您类似的问题,经过一些研究,我创建了一个不错的脚本,可以避免重新创建已经存在的片段,但同时允许您更新所有可见/已启动的片段。

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

import java.util.WeakHashMap;

/**
 * Created by TheCobra on 9/17/15.
 */
public abstract class FragmentAdvanceStatePagerAdapter extends FragmentStatePagerAdapter
{
    private WeakHashMap<Integer, Fragment> mFragments;

    public FragmentAdvanceStatePagerAdapter(FragmentManager fm)
    {
        super(fm);
        mFragments = new WeakHashMap<Integer, Fragment>();
    }

    @Override
    public Fragment getItem(int position)
    {
        Fragment item = getFragmentItem(position);
        mFragments.put(Integer.valueOf(position), item);
        return item;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object)
    {
        super.destroyItem(container, position, object);
        Integer key = Integer.valueOf(position);
        if (mFragments.containsKey(key))
        {
            mFragments.remove(key);
        }
    }

    @Override
    public void notifyDataSetChanged()
    {
        super.notifyDataSetChanged();
        for (Integer position : mFragments.keySet())
        {
            //Make sure we only update fragments that should be seen
            if (position != null && mFragments.get(position) != null && position.intValue() < getCount())
            {
                updateFragmentItem(position, mFragments.get(position));
            }
        }
    }

    @Override
    public int getItemPosition(Object object)
    {
        //If the object is a fragment, check to see if we have it in the hashmap
        if (object instanceof Fragment)
        {
            int position = findFragmentPositionHashMap((Fragment) object);
            //If fragment found in the hashmap check if it should be shown
            if (position >= 0)
            {
                //Return POSITION_NONE if it shouldn't be display
                return (position >= getCount()? POSITION_NONE : position);
            }
        }

        return super.getItemPosition(object);
    }

    /**
     * Find the location of a fragment in the hashmap if it being view
     * @param object the Fragment we want to check for
     * @return the position if found else -1
     */
    protected int findFragmentPositionHashMap(Fragment object)
    {
        for (Integer position : mFragments.keySet())
        {
            if (position != null &&
                mFragments.get(position) != null &&
                mFragments.get(position) == object)
            {
                return position;
            }
        }

        return -1;
    }

    public abstract Fragment getFragmentItem(int position);
    public abstract void updateFragmentItem(int position, Fragment fragment);
}

将该代码复制到文件名“FragmentAdvanceStatePagerAdapter.java”中。现在在您的适配器中,从这个扩展并覆盖“getFragmentItem()”和“updateFragmentItem()”。每当您调用 notifydatachange() 时,将调用 updateFragmentItem() 并创建所有片段。当适配器需要创建新的片段时,会调用 getFragmentItem()。

我希望拯救和帮助很多人:)

祝你好运,编程愉快!!!

PS如果你使用这个类,你的适配器“getItem()”应该是“getFragmentItem()”。

于 2015-09-17T21:00:49.293 回答
1

POSITION_NONE您可以按照我在这里的建议进行操作,而不是再次返回和创建所有片段:动态更新 ViewPager?

于 2013-07-25T10:42:04.297 回答
1

永远不要只使用 POSITION_NONE 使用

if(fragmentManager.getFragments().contains(object))
    return POSITION_NONE;
else
    return POSITION_UNCHANGED;

避免致命异常:java.lang.IllegalStateException Fragment {} 当前不在 FragmentManager

于 2014-09-23T23:04:03.207 回答