gridview的每个项目中的线程

时间:2014-08-04 11:34:13

标签: android android-gridview android-progressbar

我已经实现了水平滚动Gridview 。我想在每个项目中使用 Horizo​​ntal 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;
    }

3 个答案:

答案 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)

下载源代码,您可以使用此源代码作为参考:

https://github.com/nostra13/Android-Universal-Image-Loader