我已经实现了水平滚动Gridview 。我想在每个项目中使用 Horizontal ProgressBar ,因此我将一个线程绑定到适配器的 getView 中的每个项目。问题是当我滚动我的gridview时,某些项目中的进度条显示出奇怪的行为,有时它们中的一些会交换它们的位置。我知道gridview Recycles 中的查看,我已解决了这个问题,但仍然在getView中绑定线程导致问题。
适配器
public View getView(final int position, View convertView, ViewGroup parent) {
final Handler handler = new Handler();
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final ViewHolder holder;
if (convertView == null) {
convertView = inflater
.inflate(R.layout.item_grid_now_playing, null);
// set image based on selected text
holder = new ViewHolder();
holder.image = (ImageView) convertView.findViewById(R.id.image);
holder.title = (TextView) convertView.findViewById(R.id.text);
holder.channel_icon = (ImageView) convertView
.findViewById(R.id.channel_icon);
holder.progress = (ProgressBar) convertView
.findViewById(R.id.progress);
holder.progressBar = (ProgressBar) convertView
.findViewById(R.id.progressBar);
holder.layout = (LinearLayout) convertView
.findViewById(R.id.MainLayout);
holder.progressBar.setMax(Scheduler
.getMaxValueOfProgressBar(tvShows.get(position)));
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
new Thread(new Runnable() {
@Override
public void run() {
end = Scheduler.getMaxValueOfProgressBar(tvShows
.get(position));
mProgressStatus = Scheduler
.getProgressedValueOfProgressBar(tvShows
.get(position));
flags[position] = true;
while (mProgressStatus < end) {
// mProgressStatus += 1;
// Update the progressBar bar and display the
// current value in the text view
handler.post(new Runnable() {
public void run() {
mProgressStatus = Scheduler
.getProgressedValueOfProgressBar(tvShows
.get(position));
holder.progressBar.setProgress(mProgressStatus);
}
});
try {
// Sleep for 200 milliseconds.
// Just to display the progressBar slowly
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
holder.title.setText(tvShows.get(position).getTv_title());
return convertView;
}
答案 0 :(得分:0)
首先:请考虑使用AsynkTask而不是Thread。 第二:在处理程序内部,您必须检查持有者是否仍然绑定到该线程,例如:
if(holder.position==position){
mProgressStatus = Scheduler
.getProgressedValueOfProgressBar(tvShows
.get(position));
holder.progressBar.setProgress(mProgressStatus);
}
PS:在创建线程之前设置holder.position
:
holder.position=position;
答案 1 :(得分:0)
首先,我部分同意@Spotlight的答案,你应该盲目地开始这样的新线程。它们需要时间,消耗资源,使滚动速度变慢。
此外,您的所有线程确实在做的是从Scheduler
获取当前值,然后向UI线程发送new Runnable
并休眠。因此,在GridView上进行非常轻柔的操作后,您会有几十个线程一直在睡眠并一直触发new
个对象,这一切都是完全错误的。考虑通过调用Runnables
让视图安排postDelayed
。可能Runnable
应属于Holder
。
您的观点混淆的原因是,即使您创建了new Thread
,并且在绑定到该getView
的旧{s}期间新线程绑定到视图视图仍然绑定到它。它仍然在相同的视图上调用setProgress
。
这样的事情可能会更好:
Holder h;
if(convertView == null){
// init
} else{
// grab reference
}
// stop previous calls
holder.progressBar.removeCallbacks(holder.runnable);
// update position
holder.position = position;
// run the update
holder.runnable.run();
然后这个runnable
内部持有人就像
runnable = new Runnable(){
public void run() {
end = Scheduler.getMaxValueOfProgressBar(tvShows.get(position));
mProgressStatus = Scheduler.getProgressedValueOfProgressBar(tvShows.get(position));
// re-schedule if nedded
if(mProgressStatus < end){
progressBar.postDelayed(holder.runnable, 200);
}
}
}
这样你就可以保证每个视图只有1个runnable,你不需要为sleep(time)
答案 2 :(得分:0)
下载源代码,您可以使用此源代码作为参考: