ViewPager的刷新
最近有个需求涉及到viewpager的刷新问题,需求是这样的:一进入界面即发起数据请求,请求到数据后,根据数据的对象个数加载对应数目的fragment,并把相应的对象传递给fragment,进行数据的显示。但是当网络速度慢的时候就会出现一段时间的界面空白,用户体验不好。处理办法是,一开始先先加载一个fragment,显示默认数据,等网络请求到数据后再刷新显示,就类似listview的空数据处理。
Listview 的刷新很常见,也很简单,就是listview绑定的adapter设置新的数据,然后`adapter.notifyDataSetChanged();`一下 就可以刷新整个列表。
但是viewpager就稍微麻烦一些。有些人 可能会再要刷新的时候重新设置一下适配器,也能达到刷新的目的。但某些情况下会出现问题(具体什么情况,偶也不不清楚~~)
这里只是记录一下我的解决方案
我的解决方案有两种:
1.预加载几个空的fragment,比如说6个,然后获取到新数据后,再将对应得数据传给对应得fragment,以达到刷新的目的。但是这样有个弊端就是我无法得知新数据的长度,如果预加载的fragment 少于新数据的长度,就无法显示完全,如果多于,就会出现活动到最后出现空界面。
2.这种方法其实是在第一种方法基础上做的修改,即刚开始预加载1个fragment,以至于用户看到的界面不是空的,然后获取到新数据后,就把之前加载的fragment移除,根据新数据,重新绘制相应个数的fragment。但是,这样做有一个缺点,那就是会造成不必要的浪费,会影响性能。还有就是必须使用一个 List 缓存所有的 Fragment,这也得占用不少内存…,如果需求不是很复杂,可以考虑如果不是很理解,看代码:
activity界面布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingTop="@dimen/activity_vertical_margin">
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="#42452389"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:clipChildren="false"></android.support.v4.view.ViewPager>
<Button
android:id="@+id/btn1"
android:layout_width="100dp"
android:layout_height="50dp"
android:text="更新1"
android:layout_below="@+id/viewpager"
android:layout_marginTop="20dp"
android:layout_marginLeft="50dp"/>
<Button
android:id="@+id/btn2"
android:layout_width="100dp"
android:layout_height="50dp"
android:text="更新2"
android:layout_below="@+id/viewpager"
android:layout_marginTop="20dp"
android:layout_marginLeft="200dp"/>
</RelativeLayout>
fragment界面布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:background="#78976540">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="发个红包让我撑过这个月"
android:id="@+id/textView"
android:textSize="24sp"
android:textColor="@android:color/black"/>
<TextView
android:id="@+id/tv_index"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="page 1"
android:layout_marginTop="100dp"
android:textColor="@android:color/holo_red_dark"/>
</LinearLayout>
Activity.java
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private ViewPager viewPager;
private ViewPagerAdapter adapter;
private List<ChildFragment> listFragments = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager)findViewById(R.id.viewpager);
listFragments.add(new ChildFragment());
//listFragments.add(new ChildFragment());
adapter = new ViewPagerAdapter(getSupportFragmentManager(),listFragments);
viewPager.setAdapter(adapter);
Button btn1 = (Button)findViewById(R.id.btn1);
Button btn2 = (Button)findViewById(R.id.btn2);
btn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//这里一定要先清空列表
listFragments.clear();
for (int i = 0; i < 9; i++) {
listFragments.add(ChildFragment.newInstance(i));
}
//更新数据之前,要先把之前预加载的子view全部清除,重新绘制新view,不然adapter.getItem时发现缓存的有fragment,就会拿出来用,而不会重新绘制,达不到刷新的效果
viewPager.removeAllViews();
adapter.setDatas(listFragments);
adapter.notifyDataSetChanged();
viewPager.setCurrentItem(0);
}
});
btn2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listFragments.clear();
for (int i = 0; i < 3; i++) {
listFragments.add(new ChildFragment());
}
viewPager.removeAllViews();
adapter.setDatas(listFragments);
adapter.notifyDataSetChanged();
viewPager.setCurrentItem(0);
}
});
}
}
ViewPagerAdapter.java
//FragmentStatePagerAdapter 和 FragmentPagerAdapter的区别这里不做介绍,有兴趣可以百度一下
public class ViewPagerAdapter extends FragmentStatePagerAdapter{
private List<ChildFragment> listFragments ;
public ViewPagerAdapter(FragmentManager fm,List<ChildFragment> listFragments) {
super(fm);
this.listFragments = listFragments;
}
public void setDatas(List<ChildFragment> listFragments){
this.listFragments = listFragments;
}
@Override
public Fragment getItem(int position) {
if (null == listFragments){
return null;
}else {
return listFragments.get(position);
}
}
@Override
public int getCount() {
return listFragments == null ? 0 : listFragments.size();
}
//getItemPosition() 如果 Item 的位置如果没有发生变化,则返回 POSITION_UNCHANGED。如果返回了 POSITION_NONE,表示该位置的 Item 已经不存在了。默认的实现是假设 Item 的位置永远不会发生变化,而返回 POSITION_UNCHANGED。所以调用notifyDataSetChanged方法不会刷新Fragment。为了让Fragment重新绘制,必须重载PagerAdapter的getItemPositon方法并修改为return POSITION_NONE。这样之前所有的Fragment都会被detach掉。
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
}
ChildFragment.java
public class ChildFragment extends Fragment{
private String[] content = {
"帝高阳之苗裔兮,朕皇考曰伯庸。",
"摄提贞于孟陬兮,惟庚寅吾以降。",
"皇览揆余初度兮,肇锡余以嘉名:",
"名余曰正则兮,字余曰灵均。",
"纷吾既有此内美兮,又重之以修能。",
"扈江离与辟芷兮,纫秋兰以为佩。",
"汨余若将不及兮,恐年岁之不吾与。",
"朝搴阰之木兰兮,夕揽洲之宿莽。",
"日月忽其不淹兮,春与秋其代序。",
};
private static final String KEY = "index";
public static ChildFragment newInstance(int index){
ChildFragment childFragment = new ChildFragment();
Bundle bundle = new Bundle();
bundle.putInt(KEY, index);
childFragment.setArguments(bundle);
return childFragment;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.layout_item,null);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
TextView textView = (TextView) getView().findViewById(R.id.textView);
TextView textViewIndex = (TextView) getView().findViewById(R.id.tv_index);
Bundle bundle = getArguments();
if (null == bundle){
}else {
int index = bundle.getInt(KEY);
textView.setText(content[index]);
textViewIndex.setText("page " + String.valueOf(index + 1));
}
}
}
运行结果:(偶不会截动图,凑合着看吧)
初始界面:
点击按钮 更新1:
第一页
最后一页
是不是达到更新的目的了呢,点击按扭 更新2会更新到初始到初始样子,第一张图
这只是解决了我的需求,viewpager的刷新介绍的并不完善,想知道更多可以参考ViewPager刷新问题详解,我觉得这个写的特别详细,鉴于博主我能力有限,这里只是简单记录一下自己的解决办法,之后遇到能有个方向。