【问题标题】:Getting access to the currently shown fragment in fragmentpageradapter访问 fragmentpageradapter 中当前显示的片段
【发布时间】:2017-01-27 10:17:10
【问题描述】:

我有一个带有 fagmentpageradapter 和 viewpager 的 parentfragment。每个页面显示另一个包含图像视图的片段。为了避免内存不足错误,我只希望当前显示的片段将其图像加载到图像视图中。所以我必须在当前显示的片段中加载图像视图,并在未显示的片段中回收图像。

父片段:

public class DatenFragment extends Fragment {

    private List<Data> mData;
    private ViewPaver mViewPager;
    private MyFragmentPagerAdapter mAdapter;

    public DatenFragment() {}

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_daten, container, false);

        mViewPager = (MyViewPager) rootView.findViewById(R.id.view_pager);
        mViewPager.setOnPageChangeListener(this);

        mAdapter = new MyFragmentPagerAdapter(getChildFragmentManager(),mData);

        mViewPager.setAdapter(mAdapter);

        return rootView;
    }

    @Override
    public void onPageSelected(int position) {
        mAdapter.setCurrentPosition(position);
        mAdapter.loadFotos();
    }
}

片段页面适配器:

public class MyFragmentPagerAdapter extends FragmentPagerAdapter {

    private int mPos = -1;
    private List<Data> mData;

    public MyFragmentPagerAdapter(FragmentManager fm, List<Data> data) {
        super(fm);
        mData = data;
    }

    public void loadFotos(){
        EingabeFragment currentFragment;
        currentFragment = (EingabeFragment) getItem(mPos);
        currentFragment.loadFoto();
        currentFragment = (EingabeFragment) getItem(mPos-1);
        currentFragment.unloadFoto();
        currentFragment = (EingabeFragment) getItem(mPos+1);
        currentFragment.unloadFoto();
    }

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

    @Override
    public Fragment getItem(int position) {
        return EingabeFragment.createFrom(mData.get(position),position);
    }

    public void setCurrentPosition(int position) { mPos = position; }

}

viewpager 显示的片段:

public class EingabeFragment extends Fragment {

    private int mPos;
    private Data mData;
    private ImageView mImageView;

    public EingabeFragment() { }

    public void loadFoto(){
        if(mData.hasFoto()) {
            mImageView.setImageBitmap(Utils.loadFoto(mData.getFoto()));
            Log.d("DEBUG", "Foto loaded for " + mData.getId());
        }
    }
    public void unloadFoto(){
        if(mData.hasFoto()) {
            Drawable drawable = mImageView.getDrawable();
            if (drawable instanceof BitmapDrawable) {
                BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
                Bitmap bitmap = bitmapDrawable.getBitmap();
                bitmap.recycle();
                Log.d("DEBUG","Foto unloaded for " + mData.getId());
            } 
        } 
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_eingabe, container, false);

        mImageView = (ImageView) rootView.findViewById(R.id.image_view);

        return rootView;
    }

    public int getPosition() { return mPos; }

    static public EingabeFragment createFrom(Data data, int fragmentPosition){
        EingabeFragment eingabeFragment = new EingabeFragment();
        eingabeFragment.mData = data;
        eingabeFragment.mPos = fragmentPosition;
        return eingabeFragment;
    }

}

在适配器的 loadFotos() 函数中,getItem() 函数返回显示的片段的新实例。所以视图尚未创建,并且 mImageView 为空。我需要一种方法来访问分页器中显示的片段,以在该片段中加载图像。

从我的 ViewPager 中选择的 OnPage:

@Override
public void onPageSelected(int position) {

    EingabeFragment f = (EingabeFragment) mAdapter.getItem(mAdapter.getCurrentPosition());
    f.onPauseFragment();

    EingabeFragment f2 = (EingabeFragment)  mAdapter.getItem(position);
    f2.onResumeFragment();

    mAdapter.setCurrentPosition(position);
}

Eingabfragment:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_eingabe, container, false);
    mRootView = rootView;

    imageViewFoto = (ImageView) rootView.findViewById(R.id.imageView_foto);

    //Load other UI...

    mInitialized = true;

    return rootView;
}

@Override
public void onPauseFragment() {
    Log.d("DEBUG",mMessung.getId().toString() + " Pause");
    if(mInitialized) {
        unloadFoto();
        Log.d("DEBUG",mMessung.getId().toString() + " Unloaded Foto");
    } else {
        Log.d("DEBUG",mMessung.getId().toString() + " View is null");
    }
}

@Override
public void onResumeFragment() {
    Log.d("DEBUG",mMessung.getId().toString() + " Resume");
    if(mInitialized) {
        loadFoto();
        Log.d("DEBUG",mMessung.getId().toString() + " Unloaded Foto");
    } else {
        Log.d("DEBUG",mMessung.getId().toString() + " View is null");
    }
}

现在我的日志在左右滑动后给了我以下信息:

104 Pasue
104 View is null
105 Resume
105 View is null
105 Pause
105 View is null
104 Resume 
104 View is null

为正确的片段调用了暂停和恢复,但 mImageView 为空

【问题讨论】:

    标签: android android-fragments android-viewpager android-bitmap fragmentpageradapter


    【解决方案1】:

    有一些解决方法,

    如果您的 Fragment 扩展 android.support.v4.app.Fragment

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (isVisibleToUser) {
            //fragment is visible do what ever you want to do..
        }else {
           // handle here
        }
    }
    

    或者对于其他解决方案,您可以关注this这个链接,创建一个接口和回调,以便您现在可以知道哪个片段在onResume()中。

    对于第二种解决方案,onResume() 第一次在onCreateView 之前调用,因此您需要在片段中进行布尔检查,例如lodingFirstTime = true,在您的加载方法检查中全局设置它

    (!lodingFirstTime) {
      //loadfoto method
    }
    

    在你的第一个片段的 onCreateView 中

    (lodingFirstTime) {
          lodingFirstTime = false;
          //loadfoto method
        }
    

    【讨论】:

    • (!isVisibleToUser)有小错误,请重新检查。
    • 打开 parentfragment:3 次是调用的 setUserVisibleHint:-可见为假-mImageView 为空 1 次是调用的 setUserVisibleHint:-可见为真-mImageView 为空当前片段滑动上不显示图像到下一个片段,图像在调用函数之前可见 1 次调用 setUserVisibleHint:-可见为假-mImageView 不为空 1 次调用 setUserVisibleHint:-可见为真-imageview 不为空 => 加载图像当我滑动到下一个时,我得到了内存不足错误
    • 抱歉有些不便,因为它是在Fragment中的onCreateView之前调用的,所以你需要用小技巧来处理它。看到这个帖子stackoverflow.com/questions/24161160/…或者你可以点击我在回答中提到的链接。
    • 通过链接尝试解决方案,我尝试后会给出反馈
    • 从您的第一个链接尝试了解决方案。现在在显示片段之前调用加载函数,并在用户不再可见时调用卸载函数。但现在的问题是,调用加载/卸载函数时,mImageView 引用为空。
    【解决方案2】:

    在您的寻呼机中实现 ViewPager.OnPageChangeListener 并在 OnPageChangeListener 的 onPageSelected() 方法的片段中加载图像

        @Override
        public void onPageSelected(int position) {
            //show image
            ((Your Fragment) mFragments.get(position)).loadImage();
        }
    

    【讨论】:

    • 与 junaid hafeez 的 answere 中的链接相同的解决方案,但在他的 answere 中, loadImage() 函数是通过接口调用的。我实现了它,现在加载/卸载函数被正确调用。 unload 在片段不再可见后调用,而在片段可见时调用 load。但现在的问题是我的 mImageView 为空。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多