1

我知道以前有人问过这个问题,我已经对此进行了很多搜索,但无法就我的问题得到任何正确的答案。

我创建了一个列表,列表中填充了来自JSON. 现在在getView()方法内部,我正在用数据膨胀我的自定义行。每行包含一个Thumbnail,我正在从不同的线程创建每个缩略图。

现在的问题是,在我不滚动列表之前,一切都很顺利。当我滚动我的列表时,我的getView()方法被连续调用,并且所有缩略图都被重新创建并且它的位置被打乱了。创建缩略图后,我不想重新创建它们,而且我想保持缩略图的顺序。

你们能帮我解决这个问题吗?

任何帮助将不胜感激。

我的getView()方法是:

@Override
public View getView(final int position, View convertView,
                ViewGroup parent) {

            ViewHolder viewHolder = new ViewHolder();
            if (convertView == null) {
                inflater = getLayoutInflater();
                convertView = inflater.inflate(R.layout.list_item_row, parent,
                        false);
                viewHolder.titleText = (TextView) convertView
                        .findViewById(R.id.titleText);
                viewHolder.thumbImage = (ImageView) convertView
                        .findViewById(R.id.thumbnail);
                convertView.setTag(viewHolder);
            } else {
                viewHolder = (ViewHolder) convertView.getTag();
            }

            final String thumbnailURLString = mPostsList.get(position).get(
                    "thumb");
            createBitmapThread = (Thread) getLastNonConfigurationInstance();
            createBitmapThread = new MyThread(thumbnailURLString,
                    viewHolder.thumbImage);
            createBitmapThread.start();
            viewHolder.titleText.setText(title);

            return convertView;
        }

Thread班级:

public class MyThread extends Thread {

        String mThumbURLString = null;
        ImageView mImageView = null;

        public MyThread(String thumbnailURLString, ImageView imageView) {
            mThumbURLString = thumbnailURLString;
            mImageView = imageView;
        }

        @Override
        public void run() {

                try {
                    URL newurl = null;
                    try {
                        newurl = new URL(mThumbURLString);
                    } catch (MalformedURLException e) {
                        e.printStackTrace();
                    }
                    try {
                        // Options opts = new Options();
                        /*
                         * opts.inDither = true; opts.inInputShareable = true;
                         * opts.inJustDecodeBounds = true; opts.inPurgeable =
                         * true;
                         */
                        Log.e("", "INSIDE IMAGE DOINBG");
                        mBitmap = BitmapFactory
                                .decodeStream((InputStream) newurl.getContent());
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    mHandler.post(new MyRunnable(mImageView));
                } finally {

                }


    }

    public class MyRunnable implements Runnable {

        ImageView mImageView = null;

        public MyRunnable(ImageView imageView) {
            mImageView = imageView;
        }

        public void run() {
            mImageView.setImageBitmap(mBitmap);
        }
    }
4

2 回答 2

1

好的,我在这里做了类似的事情:

对于每个 getView ,创建一个新的 Fetching 类并将其放入并发/同步堆栈中。同时,将视图的位图设置为空(或您希望的任何其他内容)。您也可以改用缓存。

该类将包含有关如何加载数据的信息(例如,位图的 url)、要更新的视图和获取结果(例如,位图本身)。

现在,回到 getView,创建并执行一个 asyncTask,它将在堆栈上使用一个循环,每次它从堆栈中获取一个 Fetching 类实例(一旦它为空,asyncTask 将打破循环并完成),检查视图需要更新仍然需要数据(使用它的 viewHolder)加载位图,将结果设置到 Fetching 类中,并通过 publishProgress() 函数传递。

在 onProgressUpdate 方法中,执行与使用 Fetching 类实例和 viewHolder 之前相同的检查。如果一切顺利,更新视图以获取获取的位图。

可以在此处找到如何处理相同问题的一个很好但很复杂的示例。

于 2012-08-15T22:58:32.563 回答
1

我遇到了同样的问题,上面的建议效果很好,终于 - 谢谢!下面的代码片段:

我的异步任务:

protected class LoadImageTask extends AsyncTask<String, Void, String> {
    private View v;

    public LoadImageTask(View v) {
        super();
        this.v = v;
    }

    @Override
    protected void onPostExecute(String result) {
        Log.d(TAG, "<onPostExecute> load image complete. ");            
    }

    @Override
    protected String doInBackground(String... addresses) {
        String response = "";
        Bitmap bm = null;
        for (String address : addresses) {
            ViewHolder holder = (ViewHolder) v.getTag();
            String name = getNameFromMDN(address);
            if (name != null && name.length() > 0) {
                // get contact ID from name
                long id = getContactID(name);

                if (id != 0) {
                    bm = getThumbnailForId(id);
                    if (bm != null && bm.getHeight() > 0) {
                        bm = resizeBitmap(bm);
                        holder.icon.setImageBitmap(bm);
                        Log.d(TAG, "set thumbnail for " + name + ", id: " + id);

                    }   
                }
            }

            // default icon
            if (bm == null) {
                Log.d(TAG, "using default icon for mdn: " + address + ", name: " + name);
                holder.icon.setImageResource(R.drawable.contact_big);


                /*String s = getContactNameByContactId(person, address);
                s = s.substring(0, 2);
                if (s.length() > 0 && !MDNUtil.isNumber(s)) {
                    Log.d(TAG, "using dynamic icon for person: " + person + ", mdn: " + address + ", name: " + s);

                    icon.setBackgroundColor(Color.BLUE);                    
                    iconText.setText(s);
                    iconText.setTextColor(Color.WHITE);
                    iconText.setVisibility(View.VISIBLE);

                } else {
                    // use generic icon
                    holder.icon.setImageResource(R.drawable.contact_big);
                }*/

            }



        }
        return "";
    }

然后在我的 CustomCursorAdapter 的 bindVew() 中:

LoadImageTask load = new LoadImageTask(v);
load.doInBackground(address);

更新:最后的工作是阻止在我的自定义光标适配器中回收列表视图中的视图:

       @Override
    public int getItemViewType(int position) {
        return position;
    }

    @Override
    public int getViewTypeCount() {
        return 500;
    }
于 2012-08-16T01:55:21.410 回答