使用自定义数组适配器从错误的线程调用

时间:2015-02-13 03:49:39

标签: android listview android-asynctask android-arrayadapter

我正在尝试显示一个自定义列表视图,显示一个人的图像和每行的名字。用户列表在我的项目中保存为JSON,图片为图片网址的String

要获取实际图像,我尝试在使用Async Task时解析JSON图像,如下所示:

public class PersonArrayAdapter extends ArrayAdapter<PersonData>
{
    PersonCell personCell;
    PersonData personData;

    public PersonArrayAdapter(Context context, List<PersonData> objects)
    {
        super(context, 0, objects);
    }

    public View getView(int position, View convertView, ViewGroup parent)
    {
        personCell = new PersonCell();

        LayoutInflater inflater = LayoutInflater.from(getContext());
        convertView = inflater.inflate(R.layout.person_data, parent, false);

        personCell.imageView= (ImageView) convertView.findViewById(R.id.imageURL);
        personCell.usernameText = (TextView) convertView.findViewById(R.id.usernameText);


        personData = getItem(position);

        personCell.usernameText.setText(personData.username);
        new LoadProfileImage(personCell.imageView).execute(personData.userImage);

        return convertView;
    }

     private class LoadProfileImage extends AsyncTask<String, Void, Bitmap> {
        ImageView bmImage;

        public LoadProfileImage(ImageView bmImage) {
            this.bmImage = bmImage;
        }

        protected Bitmap doInBackground(String... urls) {
            Bitmap bitmap=null;

            try {
                bitmap = BitmapFactory.decodeStream((InputStream) new URL(personData.userImage).getContent());
                personCell.imageView.setImageBitmap(bitmap);
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return bitmap;
        }

        protected void onPostExecute(Bitmap result) {
            bmImage.setImageBitmap(result);
        }
    }


    private static class PersonCell
    {
        TextView usernameText;
        ImageView imageView;
    }
}

但是我收到错误android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.所以我想问题是我只能在Activity中运行AsyncTask而不是在Adapter类中运行。但是我需要在我的Adapter类中获取图像......

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

  

所以我想问题是我只能运行AsyncTask   活动而不是适配器类。

原因是您可以在Adapter类中运行AsyncTask。您的问题是您在doInBackground()方法中访问视图,该方法在另一个线程中运行。

ListView或类似的东西加载图片在Android中并不容易,我建议您使用Volly来完成工作。请在此处参阅“8.制作图像请求”:

http://www.androidhive.info/2014/05/android-working-with-volley-library-1/

<强>更新

您的问题可以通过删除行personCell.imageView.setImageBitmap(bitmap);来解决,因为您没有重用convertView,但您的实现可能会导致效率问题,我不确定这是否是您真正想要的:

答案 1 :(得分:1)

以下是适配器的代码片段,它以异步方式加载图像:

public class LazyImageLoadAdapter extends BaseAdapter implements OnClickListener{

    private Activity activity;
    private String[] data;
    private static LayoutInflater inflater=null;
    public ImageLoader imageLoader; 

    public LazyImageLoadAdapter(Activity a, String[] d) {
        activity = a;
        data=d;
        inflater = (LayoutInflater)activity.
                            getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        // Create ImageLoader object to download and show image in list
        // Call ImageLoader constructor to initialize FileCache
        imageLoader = new ImageLoader(activity.getApplicationContext());
    }

    public int getCount() {
        return data.length;
    }

    public Object getItem(int position) {
        return position;
    }

    public long getItemId(int position) {
        return position;
    }

    /********* Create a holder Class to contain inflated xml file elements *********/
    public static class ViewHolder{

        public TextView text;
        public TextView text1;
        public TextView textWide;
        public ImageView image;

    }

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

        View vi=convertView;
        ViewHolder holder;

        if(convertView==null){

            /****** Inflate tabitem.xml file for each row ( Defined below ) *******/
            vi = inflater.inflate(R.layout.listview_row, null);

            /****** View Holder Object to contain tabitem.xml file elements ******/

            holder = new ViewHolder();
            holder.text = (TextView) vi.findViewById(R.id.text);
            holder.text1=(TextView)vi.findViewById(R.id.text1);
            holder.image=(ImageView)vi.findViewById(R.id.image);

           /************  Set holder with LayoutInflater ************/
            vi.setTag( holder );
        }
        else 
            holder=(ViewHolder)vi.getTag();


        holder.text.setText("Company "+position);
        holder.text1.setText("company description "+position);
        ImageView image = holder.image;

        //DisplayImage function from ImageLoader Class
        imageLoader.DisplayImage(data[position], image);

        /******** Set Item Click Listner for LayoutInflater for each row ***********/
        vi.setOnClickListener(new OnItemClickListener(position));
        return vi;
    }

    @Override
    public void onClick(View arg0) {
        // TODO Auto-generated method stub

    }


    /********* Called when Item click in ListView ************/
    private class OnItemClickListener  implements OnClickListener{           
        private int mPosition;

       OnItemClickListener(int position){
             mPosition = position;
        }

        @Override
        public void onClick(View arg0) {
            MainActivity sct = (MainActivity)activity;
            sct.onItemClick(mPosition);
        }               
    }   
}