1

我创建了一个包含行的片段列表,每行都有一张图片、姓名和电话号码。完成了有关适配器和列表加载器的所有内容...我首先使用默认图像成功加载了列表,然后在加载并将其显示到屏幕后我想从网络加载联系人图像,所以我创建了一个扩展 asynctask 的类,而创建我执行这个类的每一行。问题是,假设我们有一个电话号码“1234”,我希望有这个号码的行有一张特定的照片,我快速向下滚动列表,许多行的照片发生了变化。有什么帮助吗?这是我的代码:

适配器类:

package Adapters;


import java.util.List;

import com.inneed.R;

import Classes.Contacts;
import Classes.LoadImage;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;

public class ContactsAdapter extends ArrayAdapter<Contacts> {
    private final LayoutInflater mInflater;
    public ContactsAdapter(Context context) {
        super(context, android.R.layout.simple_list_item_2);
        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }
    public void setData(List<Contacts> data){
        clear();
        if (data!=null) {
            for (Contacts appEntry : data){
                add(appEntry);
            }
        }
    }
    @Override
    public View getView (int position, View convertView, ViewGroup parent){
        View view;
        if (convertView == null){
            view = mInflater.inflate(R.layout.contactrow, parent,false);
        }else {
            view = convertView;
        }
        Contacts item = getItem(position);
        TextView Name = (TextView) view.findViewById(R.id.CRName);
        Name.setText(item.getName());
        TextView Mobile = (TextView) view.findViewById(R.id.CRNumber);
        Mobile.setText(item.getMobile());
        if (Mobile.getText().equals("1234"))
        {
            Log.i("MobileXXX",item.getMobile());
            new LoadImage(view).execute("http://image10.bizrate-images.com/resize?sq=60&uid=2216744464");
        }
        if (position%2==0)
        {
            view.setBackgroundResource(R.drawable.list_background);
        }
        else view.setBackgroundResource(R.drawable.list_background2);
        return view;
    }
}

加载 Image 类 asynctask:

package Classes;

import java.io.InputStream;

import com.inneed.R;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.view.View;
import android.widget.ImageView;

public class LoadImage extends AsyncTask<String, Void, Bitmap>{
        private View view;
      public LoadImage(View view) {
          this.view = view;
      }

      protected Bitmap doInBackground(String... urls) {
          String urldisplay = urls[0];
          Bitmap mIcon11 = null;
          try {
            InputStream in = new java.net.URL(urldisplay).openStream();
            mIcon11 = BitmapFactory.decodeStream(in);
          } catch (Exception e) {
              e.printStackTrace();
          }
          return mIcon11;
      }

      protected void onPostExecute(Bitmap result) {
          ImageView Img = (ImageView) view.findViewById(R.id.imageView1);
          Img.setImageBitmap(result);
          this.cancel(true);
      }

}

ListFragment 类:

import java.util.List;
import Adapters.ContactsAdapter;
import Adapters.FavContactsDataListLoader;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.view.View;
import android.widget.ListView;
import Classes.Contacts;

public class FavContactsTab extends ListFragment implements LoaderManager.LoaderCallbacks<List<Contacts>>  {
    ContactsAdapter mAdapter;
    @Override
    public void onActivityCreated(Bundle savedInstanceState){
        super.onActivityCreated(savedInstanceState);
        mAdapter = new ContactsAdapter(getActivity());
        setListAdapter(mAdapter);
        setListShown(false);
        getLoaderManager().initLoader(0, null, this);
    }
    @Override
    public Loader<List<Contacts>> onCreateLoader(int arg0, Bundle arg1) {
        // TODO Auto-generated method stub
        return new FavContactsDataListLoader(getActivity());
    }
    @Override
    public void onLoadFinished(Loader<List<Contacts>> arg0, List<Contacts> data) {
        mAdapter.setData(data);
        if (!isResumed()) {
            getLoaderManager().restartLoader(0, null, this);
            setListShown(true);
            setListShownNoAnimation(true);
        }
        else {
            setListShown(true);
            setListShownNoAnimation(true);
        }

    }
    @Override
    public void onLoaderReset(Loader<List<Contacts>> arg0) {
        mAdapter.setData(null);

    }
    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        // Insert desired behavior here.
    }
}
4

1 回答 1

0

Android 正在重用 ListViews 中的视图。它通常只创建 n+1 个视图,其中 n 是屏幕上可见的视图数。当您滚动时,消失的视图将被重新用作下一个可见视图。至少当您在 getView() 方法中使用 convertView 时会发生这种情况,而这正是您正在做的事情。

现在,当这种情况发生并且您的 LoadImage AsyncTask 仍在运行时,它将修改最初映射到视图中另一个位置的视图。更糟糕的是,您将启动第二个 LoadImage,这两个将修改相同的视图,但使用不同的图像。

您需要做的是不使用 convertView 或阻止 LoadImage 在完成后修改视图。一种简单的方法是在视图上使用 view.setTag(position)。LoadImage 可以在其构造函数中读取并保存位置标记,然后在修改视图之前再次检查视图的位置。如果它已经改变,那么视图被重新用于不同的位置并且不应该被修改。我敢肯定还有很多其他方法可以实现相同的,也许更聪明的方法,但这应该会给你一些想法。

于 2013-04-26T02:43:44.750 回答