写这篇文章,主要是阐述自己遇到的一些问题时的解决方法,小弟才疏学浅,若有说的不对的地方,请批评指正!!!大神勿喷啊!
最近在做App项目,根据客户要求,用了ViewPager来装入Fragment,然后每个Fragment装入一个Listview,当然肯定有可切换的标题头,刚开始做的很顺利,因为都是基础控件的应用,基本上没有什么问题,后来客户修改要求,在App的第一个页面也就是Listview上加一个轮播图的标题头,当然可以了,客户是上帝嘛,而且也简单啊,新建一个ViewPager,里面把需要装入的图片添加进去,然后通过listview.addheadView(view),搞定.轮播图肯定要让图片时刻动起来,常规思想,新建一个线程,每隔几秒钟切换一下,看代码:
//开启线程切换图片
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
SystemClock.sleep(3000);
//切换
handler.post(new Runnable() {
//该方法在主线程中执行
@Override
public void run() {
//获得当前的显示的索引
//headviewpager新建的viewpager
int currentItem = headviewpager.getCurrentItem();
int newItem = 0;
//headdatalist为viewpager的数据集合
if(currentItem == (headdataList.size() -1)){
newItem = 0;
}else{
newItem = currentItem + 1;
}
headviewpager.setCurrentItem(newItem);
}
});
}
}
}).start();
问题出现了,明明是线程睡3秒钟后才自动开始切换
SystemClock.sleep(3000);
但是在当viewpager切换Fragment后,刚开始没感觉,多切换几次,并且每次切换返回主页(就是有headview轮播图的主页),就会发现轮播图切换的时间越来越短,切换速度越来越快!完全没有睡3秒在切换,因为是用AS写的,以为没有编译好,重新编译,重新安装后,问题依然存在.
在网上搜索找了好久没有找到这种问题的说法,后来自己琢磨了一下,写出了和各位大神们请教一下;
原因是:viewpager创建fragment的时候自动创建子线程去切换轮播图,当viewpage左右切换时,fragment会销毁,而切换轮播图的子线程并没有随着一起销毁,还在后台执行,当viewpage再次回到主页(就是有headview轮播图的主页)时,fragment会重新创建,同时会再次新建一个子线程来切换轮播图,这样来回切换几次后,后天就会有很多子线程在切换轮播图,每个子线程启动的时间还不一样,这样累加起来,子线程与子线程之间启动切换轮播图时就没有时间间隔,所以轮播图切换会越来越快.
第一时间解决方法是利用Fragment的生命周期将子线程杀掉:
新建一个类继承Thread,里面放切换代码,然后重写Fragment的on Stop()方法:
通过日志可以看到当viewpage切换Fragment生命后期on Stop()时,直接报错,错误是无法调用threa.destroy()方法;@Override public void onStop() { super.onStop(); thread.destroy(); Log.i("MainActivity", "onStop: 杀死任务");}
这个时候我就懵了,为什么呢?
请教同事后是这样理解的,因为我的子线程执行的是while的死循环睡3秒切换图片,相当于线程没有执行完,所以无法被杀死,那么轮播图要在这样的环境下进行切换,该怎么办呢?
在网上找了很多方法,最后找了一个能解决问题的方法,直接看代码:
//把timer声明称全局变量
timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
handler.post(new Runnable() {
@Override
public void run() {
int cutrrentitem = headviewpager.getCurrentItem();
int newitem = 0;
if (cutrrentitem == (headviewpagedataList.size() -1)) {
newitem = 0;
} else {
newitem = cutrrentitem + 1;
}
headviewpager.setCurrentItem(newitem);
}
});
}
//每间隔两秒执行一次
}, 2000, 2000);
就是新建一个延迟任务,任务的代码就不解释那么多了,可以去查API!
然后还是利用fragment的生命周期;
public void onStop() {
super.onStop();
//调用timer的cancel方法,结束延迟任务
timer.cancel();
Log.i("MainActivity", "onStop: 杀死任务");
}
OK,问题搞定!