我正在使用兼容性库中的ViewPager。我已经成功地让它显示几个视图,我可以通过页面。

但是,我很难弄清楚如何用一组新的视图更新ViewPager。

我已经尝试了各种各样的事情,比如调用mAdapter.notifyDataSetChanged(), mviewpage .invalidate(),甚至在每次我想使用新的数据列表时创建一个全新的适配器。

没有任何帮助,textviews保持不变,从原始数据。

更新: 我做了一个小测试项目,我几乎能够更新视图。我将在下面粘贴这个类。

然而,似乎没有更新的是第二个视图,“B”仍然存在,它应该在按下更新按钮后显示“Y”。

public class ViewPagerBugActivity extends Activity {

    private ViewPager myViewPager;
    private List<String> data;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        data = new ArrayList<String>();
        data.add("A");
        data.add("B");
        data.add("C");

        myViewPager = (ViewPager) findViewById(R.id.my_view_pager);
        myViewPager.setAdapter(new MyViewPagerAdapter(this, data));

        Button updateButton = (Button) findViewById(R.id.update_button);
        updateButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                updateViewPager();
            }
        });
    }

    private void updateViewPager() {
        data.clear();
        data.add("X");
        data.add("Y");
        data.add("Z");
        myViewPager.getAdapter().notifyDataSetChanged();
    }

    private class MyViewPagerAdapter extends PagerAdapter {

        private List<String> data;
        private Context ctx;

        public MyViewPagerAdapter(Context ctx, List<String> data) {
            this.ctx = ctx;
            this.data = data;
        }

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

        @Override
        public Object instantiateItem(View collection, int position) {
            TextView view = new TextView(ctx);
            view.setText(data.get(position));
            ((ViewPager)collection).addView(view);
            return view;
        }

        @Override
        public void destroyItem(View collection, int position, Object view) {
             ((ViewPager) collection).removeView((View) view);
        }

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

        @Override
        public Parcelable saveState() {
            return null;
        }

        @Override
        public void restoreState(Parcelable arg0, ClassLoader arg1) {
        }

        @Override
        public void startUpdate(View arg0) {
        }

        @Override
        public void finishUpdate(View arg0) {
        }
    }
}

当前回答

我实际上使用notifyDataSetChanged()在ViewPager和CirclePageIndicator和之后,我调用destroyDrawingCache()在ViewPager和它的工作。其他的解决方法对我都不起作用。

其他回答

我知道我迟到了,但还是能帮到别人。我只是扩展了接受的答案,我也添加了评论。

答案本身说明它是低效的

为了让它只在需要时刷新,你可以这样做

private boolean refresh;

public void refreshAdapter() {
    refresh = true;
    notifyDataSetChanged();
}

@Override
public int getItemPosition(@NonNull Object object) {
    if (refresh) {
        refresh = false;
        return POSITION_NONE;
    } else {
        return super.getItemPosition(object);
    }
}

我认为PagerAdapter中没有任何类型的错误。问题是,理解它是如何工作的有点复杂。看看这里解释的解决方案,从我的角度来看,有一个误解,因此实例化视图的使用很差。

在过去的几天里,我一直在使用PagerAdapter和ViewPager,我发现了以下内容:

PagerAdapter上的notifyDataSetChanged()方法只会通知ViewPager底层页面已经更改。例如,如果您动态地创建/删除页面(从列表中添加或删除项目),ViewPager应该负责这些。在这种情况下,我认为ViewPager决定是否应该使用getItemPosition()和getCount()方法删除或实例化一个新视图。

我认为ViewPager,在notifyDataSetChanged()调用后,它的子视图和检查他们的位置与getItemPosition()。如果对于子视图,该方法返回POSITION_NONE, ViewPager会认为该视图已被删除,并调用destroyItem()方法删除该视图。

通过这种方式,如果您只想更新页面的内容,覆盖getItemPosition()以总是返回POSITION_NONE是完全错误的,因为每次调用notifyDatasetChanged()时,以前创建的视图将被销毁,而新的视图将被创建。对于一些textview来说,这似乎没有什么问题,但是当你有复杂的视图时,比如从数据库中填充的listview,这可能是一个真正的问题和资源浪费。

So there are several approaches to efficiently change the content of a view without having to remove and instantiate the view again. It depends on the problem you want to solve. My approach is to use the setTag() method for any instantiated view in the instantiateItem() method. So when you want to change the data or invalidate the view that you need, you can call the findViewWithTag() method on the ViewPager to retrieve the previously instantiated view and modify/use it as you want without having to delete/create a new view each time you want to update some value.

例如,假设您有100个带有100个textview的页面,并且您只想定期更新一个值。使用前面解释的方法,这意味着您在每次更新时删除并实例化100个textview。这没有道理……

好了,伙计们,我用instantiateItem找到了一个解决方案。11年后再看这个视频的人:

 viewModel.mImage.observe(this, imagePath -> {
            int pos = binding.sliderIntro.getCurrentPagePosition();
            adapter.editList(pos, imagePath);
            if (binding.sliderIntro.findViewWithTag("" + pos) != null)
                adapter.instantiateItem(binding.sliderIntro.findViewWithTag("" + pos), pos);
        });

以及您的适配器:

 public void editList(int position, String imagePath) {
        this.sliderItems.set(position, imagePath);
    }

and:

  @Override
    public void onBindViewHolder(IntroSliderAdapterViewHolder viewHolder, final int position) {
            viewHolder.itemView.setTag("" + position);
       
    }

在我的情况下,在我的Viewpager中有一个textView,在mainActivity中单击按钮,我想改变textView的颜色并更新pagerAdapter。在按钮上单击“我在SharedPreference中保存了颜色”,并更新pagerAdapter,它可以更新从共享首选项中获取的颜色。我用下面的方式更新viewPager视图。

btn_purple.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int color = ContextCompat.getColor(mContext, R.color.colorPrimaryDark2);
                editor.putInt("sahittoFontColor", color);
                editor.apply();
                toNotifyDatasetChanged();
            }
        });

现在更新方法:

 private  void  toNotifyDatasetChanged (){
        if(viewPager!=null&& pagerAdapter!=null) {
            viewPager.setAdapter(null);
            viewPager.setAdapter(pagerAdapter);
           
        }

    }

我的pagerAdapter是:

pagerAdapter = new  Sahitto_ViewPagerAdapter (mContext, filenameParameter, 30, lineList);
                        viewPager.setAdapter(pagerAdapter);

并且在instantiateItem was(在PagerAdapter中):

    SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(mContext);
    int   bnfntcolor=settings.getInt("sahittoFontColor", 0);
if (bnfntcolor!=0){
    textView.setTextColor(bnfntcolor);
}

因此,当我点击按钮,颜色立即改变在pagerAdapter的Textview。

快乐的编码。

在我的情况下,每次片段进入onCreateView,我重新启动值处理空值或空值,如:

if (var == null) {
    var = new Something();
}

if (list.isEmpty()) {
    list = new ArrayList<MyItem>();
}

if (myAdapter == null) {
    myAdapter = new CustomAdapter();
    recyclerView.setAdapter(myAdapter);
}

// etc...

Fragment类可以在每次更改时进入onCreateView,并在运行时从UI返回到视图。