我正在尝试显示一个自定义列表视图,显示一个人的图像和每行的名字。用户列表在我的项目中保存为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类中获取图像......
我该如何解决这个问题?
答案 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);
}
}
}