【问题标题】:Refresh images on FragmentStatePagerAdapter on resuming activity在恢复活动时刷新 FragmentStatePagerAdapter 上的图像
【发布时间】:2012-11-21 15:36:58
【问题描述】:

我创建了一个使用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()),但没有结果。我对此感到有些绝望。

【问题讨论】:

    标签: android android-fragments android-viewpager fragmentpageradapter


    【解决方案1】:

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

    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() 并创建所有片段。当适配器需要创建一个新的fragment时,会调用getFragmentItem()。

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

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

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

    【讨论】:

      【解决方案2】:

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

      以下是一些有用的提示:

      ViewPager PagerAdapter not updating the View

      Update ViewPager dynamically?

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

      像这样覆盖 PagerAdapter 中的 getItemPosition:

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

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

      【讨论】:

      • 对应适配器的 notifyDataSetChanged() 调用工作。
      【解决方案3】:

      永远不要只使用 POSITION_NONE 使用

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

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

      【讨论】:

        【解决方案4】:

        不要返回POSITION_NONE 并再次创建所有片段,您可以按照我在这里的建议进行操作:Update ViewPager dynamically?

        【讨论】:

          猜你喜欢
          • 2013-02-14
          • 1970-01-01
          • 2016-11-06
          • 2010-10-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多