在 ListView 上通过 URI 重新加载 ImageView
Posted
技术标签:
【中文标题】在 ListView 上通过 URI 重新加载 ImageView【英文标题】:Reload ImageView by URI on ListView 【发布时间】:2016-02-16 19:37:02 【问题描述】:我有一个由ImageView 组成的元素的ListView。我使用AsyncTask 获得了一个新图像,在onPostExecute(Object result) 方法中我使用setImageUri(Uri uri) 设置了图像,但它没有得到更新。
如果我更改活动或在应用程序之间更改,图像会完美显示,但我想立即显示图像。
我尝试使用ImageView
、扩展BaseAdapter
、父ListView
的所有组合调用invalidate()
,但没有任何效果。我尝试了许多其他技术,例如调用setImageResource(0)
、setImageUri(null)
,但没有结果...
已编辑:
这里,部分代码:
public class ThingItemAdapter extends BaseAdapter
protected List<Thing> things;
LayoutInflater inflater;
public ThingItemAdapter(Context context, List<Thing> things)
this.things = things;
this.inflater = LayoutInflater.from(context);
@Override
public int getCount()
return things.size();
@Override
public Thing getItem(int position)
return things.get(position);
@Override
public long getItemId(int position)
return things.get(position).getId();
@Override
public View getView(int position, View convertView, ViewGroup parent)
final int pos = position;
final ViewHolder holder;
if (convertView == null)
holder = new ViewHolder();
convertView = this.inflater.inflate(R.layout.thing_list_item, parent, false);
holder.thingImageView = (ImageView) convertView.findViewById(R.id.thing_preview);
holder.button = (ImageButton) convertView.findViewById(R.id.apply_button);
convertView.setTag(holder);
else
holder = (ViewHolder) convertView.getTag();
final Thing thing = things.get(position);
final long thingId = thing.getId();
final Uri thingUri = thing.getPicture();
holder.thingImageView.setImageURI(thingUri);
holder.button.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
// generate new file
final TypedFile typedFile = new TypedFile("multipart/form-data", new File(thingUri.getPath()));
new ReadAndStorePictureTask()
.execute(new Object[] typedFile, holder.thingImageView, thing );
);
// item detailed view listener
holder.thingImageView.setOnClickListener(new View.OnClickListener()
@Override
public void onClick(View v)
Intent intent = new Intent((ThingApplication) ThingApplication.getContext(), ThingActivity.class);
intent.putExtra(ThingActivity.EXTRA_THING_ID, thingId);
context.startActivity(intent);
);
return convertView;
private class ViewHolder
ImageView thingImageView;
ImageButton button;
private class ReadAndStorePictureTask extends AsyncTask<Object, Void, Void>
ImageView imageView;
Thing thing;
ViewGroup parent;
protected Void doInBackground(Object... params)
final TypedFile typedFile = (TypedFile) params[0];
imageView = (ImageView) params[1];
thing = (Thing) params[2];
((ThingApplication) ThingApplication.getContext()).getClient().apply(typedFile,
new Callback<Response>()
@Override
public void failure(RetrofitError error)
...
@Override
public void success(Response nothing, Response response)
try
byte[] bytes = ThingApplication.getBytesFromStream(response.getBody().in());
Uri newImageURI = Uri.parse("uri://valid_uri"); // whatever, it exists in real code
thing.setPicture(newImageURI);
File file = ((ThingApplication) ThingApplication.getContext())
.getFileFromURI(newImageURI); // this method works
ThingApplication.saveBytesToFile(bytes, file.getAbsolutePath());
thingService.storeThing(thing);
catch (Exception e)
...
);
return null;
@Override
protected void onPostExecute(Void result)
imageView.setImageURI(thing.getPicture());
// force redraw. FIXME not working
/*
* ANSWER HERE, PLEASE
*/
如何在 onPostExecute(Object result)
方法中立即显示更新后的 URI?
【问题讨论】:
我想,你已经使用了 notifyDataSetChanged();,那么你应该展示一些你的代码,以便我可以帮助你 @androider 代码已添加。 【参考方案1】:onPostExecute 更新链接到 ListView 适配器的图像列表,然后通过调用通知适配器您更改了列表中的项目:
adapter.notifyDataSetChanged();
【讨论】:
如果您粘贴适配器,我会尽力帮助您【参考方案2】:你可以这样做:
-更改异步任务调用中的第三个参数。
new ReadAndStorePictureTask().execute(
new Object[] typedFile, holder.thingImageView, pos );
-然后,修改asynctask里面的列表项并刷新。
private class ReadAndStorePictureTask extends AsyncTask<Object, Void, Void>
ImageView imageView;
int position;
ViewGroup parent;
protected Void doInBackground(Object... params)
final TypedFile typedFile = (TypedFile) params[0];
imageView = (ImageView) params[1];
position = (Integer) params[2];
((ThingApplication) ThingApplication.getContext()).getClient().apply(typedFile,
new Callback<Response>()
@Override
public void failure(RetrofitError error)
...
@Override
public void success(Response nothing, Response response)
try
byte[] bytes = ThingApplication.getBytesFromStream(response.getBody().in());
Uri newImageURI = Uri.parse("uri://valid_uri"); // whatever, it exists in real code
things.get(position).setPicture(newImageURI);
File file = ((ThingApplication) ThingApplication.getContext())
.getFileFromURI(newImageURI); // this method works
ThingApplication.saveBytesToFile(bytes, file.getAbsolutePath());
thingService.storeThing(things.get(position));
catch (Exception e)
...
);
return null;
@Override
protected void onPostExecute(Void result)
notifyDataSetChanged();
祝你好运!
【讨论】:
不工作。如果你看到,它是一样的,我正在传递一个从该位置提取的“东西”。在 AsyncTask 外部或内部获取它是一样的。 postExecute() 可能在 doInbackground() 完成之前运行,因为方法 new Callback以上是关于在 ListView 上通过 URI 重新加载 ImageView的主要内容,如果未能解决你的问题,请参考以下文章
Flutter StreamBuilder ListView在流数据更改时不会重新加载
通过 uri / 通过它包含的数据获取 ListView 项目位置
setState 方法重新加载列表视图。我怎样才能阻止它?扑