我创建了一个使用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()
),但没有结果。我对此非常不满。
答案 0 :(得分:37)
处理片段寻呼机适配器可以是PITA。
以下是一些有用的提示:
ViewPager PagerAdapter not updating the View
一般来说,这个有99%的时间都有效......
在PagerAdapter中覆盖getItemPosition,如下所示:
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
有时即使那些不起作用,我也必须使用'强力'方法并再次重新创建整个视图(从onCreate开始)......
答案 1 :(得分: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()”&amp; “updateFragmentItem()”。每当调用notifydatachange()时,将调用updateFragmentItem()并使用已创建的所有片段。当适配器需要创建一个新片段时,将调用getFragmentItem()。
我希望拯救并帮助很多人:)
祝你好运,快乐编程!!!
P.S。如果你使用这个类,你的适配器“getItem()”应该是“getFragmentItem()”。
答案 2 :(得分:1)
您可以按我在此处的建议执行操作,而不是返回POSITION_NONE
并再次创建所有片段:Update ViewPager dynamically?
答案 3 :(得分:1)
永远不要只使用POSITION_NONE使用
if(fragmentManager.getFragments().contains(object))
return POSITION_NONE;
else
return POSITION_UNCHANGED;
避免致命异常:java.lang.IllegalStateException Fragment {}当前不在FragmentManager中