我有一个问题困扰了我好几个星期了。当我更新到新的 Facebook SDK 时,我有一段时间忘记了它,但现在它又回到了我的梦中。
我基本上是在制作一个 Facebook 提要阅读器。它从 API 调用获取 JSON 数据并使用它来填充 ListView。每次自定义适配器调用 getView() 方法时,它都会检查它是什么类型的“状态”。如果是“照片”状态, View 将有两张图片(个人资料图片和状态更新图片)。我使用 nostra13 的 Universal Image Loader 在使用 holder 类膨胀 ImageView 后加载两个图像以帮助回收 View 。这就是我认为存在问题的地方。
当我滚动列表时,所有个人资料图片都可以正常加载并且效果很好。但是当我滚动时,状态照片会做一些事情:
1.) 全部加载相同的图像(我以前没有遇到过这个问题,但我把它交给自己试图修复其他图像)。
2.) 图像跳来跳去,要么消失,要么出现在与预期不同的 View 中。
3.) 如果图像加载正确并且显示的不是同一图像,图像会随着我上下滚动而改变,最终全部变成同一图像。
我将发布我的 getView() 代码(抱歉有点长)。
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
try {
jsonObject = getItem(position);
jsonFrom = jsonObject.getJSONObject("from");
postType = jsonObject.getString("type");
posterName = jsonFrom.getString("name");
posterID = jsonFrom.getString("id");
posterPhoto = "http://graph.facebook.com/" + posterID
+ "/picture?type=square";
if (jsonObject.has("message")) {
posterMessage = jsonObject.getString("message");
} else {
posterMessage = jsonObject.getString("story");
}
} catch (JSONException e) {
e.printStackTrace();
}
if (postType.equals("status")) {
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.status_post_holder,null);
holder = new ViewHolder();
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.posterName = (TextView) convertView.findViewById(R.id.posterName);
holder.posterMessage = (TextView) convertView.findViewById(R.id.posterMessage);
holder.posterProfilePhoto = (ImageView) convertView.findViewById(R.id.posterProfilePic);
if (jsonObject != null) {
holder.posterName.setText(posterName);
if (posterMessage != null) {
holder.posterMessage.setText(posterMessage);
} else {
holder.posterMessage.setText("No message for this post.");
}
profileImageLoader.displayImage(posterPhoto,
holder.posterProfilePhoto);
}
}
else if (postType.equals("photo")) {
if (convertView == null) {
try {
posterImageURL = jsonObject.getString("picture");
} catch (JSONException e) {
e.printStackTrace();
}
LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.photo_post_holder, null);
holder = new ViewHolder();
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.posterName = (TextView) convertView.findViewById(R.id.posterName);
holder.posterMessage = (TextView) convertView.findViewById(R.id.posterMessage);
holder.posterProfilePhoto = (ImageView) convertView.findViewById(R.id.posterProfilePic);
holder.posterImage = (ImageView) convertView.findViewById(R.id.posterImage);
if (jsonObject != null) {
holder.posterName.setText(posterName);
if (posterPhoto != null) {
profileImageLoader.displayImage(posterPhoto,holder.posterProfilePhoto);
}
if (posterImageURL != null) {
pictureImageLoader.displayImage(posterImageURL,holder.posterImage);
}
if (posterMessage != null) {
holder.posterMessage.setText(posterMessage);
} else {
holder.posterMessage.setText("No message for this post.");
}
}
}
else if (postType.equals("link")) {
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.status_post_holder,null);
holder = new ViewHolder();
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.posterName = (TextView) convertView.findViewById(R.id.posterName);
holder.posterMessage = (TextView) convertView.findViewById(R.id.posterMessage);
holder.posterProfilePhoto = (ImageView) convertView.findViewById(R.id.posterProfilePic);
if (jsonObject != null) {
holder.posterName.setText(posterName);
if (posterMessage != null) {
holder.posterMessage.setText(posterMessage);
} else {
holder.posterMessage.setText("No message for this post.");
}
profileImageLoader.displayImage(posterPhoto,holder.posterProfilePhoto);
}
}
else {
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater) activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.status_post_holder,null);
holder = new ViewHolder();
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.posterName = (TextView) convertView.findViewById(R.id.posterName);
holder.posterMessage = (TextView) convertView.findViewById(R.id.posterMessage);
holder.posterProfilePhoto = (ImageView) convertView.findViewById(R.id.posterProfilePic);
if (jsonObject != null) {
holder.posterName.setText(posterName);
if (posterMessage != null) {
holder.posterMessage.setText(postType);
} else {
holder.posterMessage.setText("No message for this post.");
}
profileImageLoader.displayImage(posterPhoto,holder.posterProfilePhoto);
}
}
return convertView;
}
我确定它与 Android 回收 View 和效率有关,但我无法弄清楚我在哪里犯了错误。同样奇怪的是,问题只存在于一个 ImageView 中。任何帮助都会很热。谢谢。
更新:我们发现这是我的 JSON 解析错误。您必须使用 setTag() 来保留特定于该订单项的图像。适配器试图将 null 标记设置到 View ,这导致了 NPE。
再次更新:在进一步挖掘之后,看起来是 ImageView 本身给出了一个空值,就好像它没有找到正确的布局一样。我为不同类型的帖子使用了两种不同的 xml 布局。所以现在看起来最好的解决方案是使用相同的布局,并根据状态类型有条件地在每个 View 中膨胀不同的元素。
最佳答案
请在使用和处理图像加载器类时具体说明。 如果可能,不要创建同一类的更多实例。而不是以不同的方式使用相同的实例。
请参阅下面的适配器类并尝试将其集成到您的案例中。这将帮助你。
private class OrderAdapter extends ArrayAdapter<User> {
private ArrayList<User> items;
Activity a;
public ImageLoader imageLoader;
public OrderAdapter(Context context, int textViewResourceId,ArrayList<User> items) {
super(context, textViewResourceId, items);
this.items = items;
// extra
/*if (Utility.model == null) {
Utility.model = new FriendsGetProfilePics();
}
Utility.model.setListener(this);*/
}
/*@Override
public boolean isEmpty() {
// TODO Auto-generated method stub
super.isEmpty();
return false;
}*/
@Override
public View getView(final int position, View convertView,ViewGroup parent) {
ViewHolder holder;
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.add_buddies_row_new, null);
holder = new ViewHolder();
imageLoader = new ImageLoader(NotificationsActivity.this);
//--------------
//---------------------------------------------------------------------
// for head to head
holder.userName = (TextView) v.findViewById(R.id.txtName);
holder.userPic = (ImageView) v.findViewById(R.id.imgUserPic);
holder.userCity = (TextView) v.findViewById(R.id.txtCity);
holder.userState = (TextView) v.findViewById(R.id.txtstate);
holder.userCountry = (TextView) v.findViewById(R.id.txtContry);
//---------------------------------------------------------------------
v.setTag(holder);
}else{
holder=(ViewHolder)v.getTag();
}
final User o = items.get(position);
holder = (ViewHolder) v.getTag();
if (o != null) {
holder.userName.setText(o.getUserName());
holder.userCity.setText(o.getUserCity()+", ");
holder.userState.setText(o.getUserState()+", ");
holder.userCountry.setText(o.getUserCountry());
System.out.println("PIC: "+o.getUserPic());
holder.userPic.setTag(o.getUserPic());
imageLoader.DisplayImage(o.getUserPic(), a, holder.userPic);
}
return v;
}
}
class ViewHolder {
TextView userName ;
TextView userCity;
TextView userState;
TextView userCountry;
ImageView userPic ;
}
有任何想法给我评论。
注意:您必须根据您的要求对上述代码进行一些更改。
如果您的问题没有解决,请告诉我。
如果您获取的是空数据,也可能会发生这种情况,因此请确认获取数据。
关于Android ListView 通用图像加载器在滚动时更改图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13756474/
如何正确创建Rails迁移,以便将表更改为MySQL中的MyISAM?目前是InnoDB。运行原始执行语句会更改表,但它不会更新db/schema.rb,因此当在测试环境中重新创建表时,它会返回到InnoDB并且我的全文搜索失败。我如何着手更改/添加迁移,以便将现有表修改为MyISAM并更新schema.rb,以便我的数据库和相应的测试数据库得到相应更新? 最佳答案 我没有找到执行此操作的好方法。您可以像有人建议的那样更改您的schema.rb,然后运行:rakedb:schema:load,但是,这将覆盖您的数据。我的做法是(假设
鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende
我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘
我尝试使用不同的ssh_options在同一阶段运行capistranov.3任务。我的production.rb说:set:stage,:productionset:user,'deploy'set:ssh_options,{user:'deploy'}通过此配置,capistrano与用户deploy连接,这对于其余的任务是正确的。但是我需要将它连接到服务器中配置良好的an_other_user以完成一项特定任务。然后我的食谱说:...taskswithoriginaluser...task:my_task_with_an_other_userdoset:user,'an_othe
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("
假设我有一个FireNinja我的数据库中的对象,使用单表继承存储。后来才知道他真的是WaterNinja.将他更改为不同的子类的最干净的方法是什么?更好的是,我很想创建一个新的WaterNinja对象并替换旧的FireNinja在数据库中,保留ID。编辑我知道如何创建新的WaterNinja来self现有FireNinja的对象,我也知道我可以删除旧的并保存新的。我想做的是改变现有项目的类别。我是通过创建一个新对象并执行一些ActiveRecord魔法来替换行,还是通过对对象本身做一些疯狂的事情,或者甚至通过删除它并使用相同的ID重新插入来做到这一点,这是问题的一部分。
我一直致力于让我们的Rails2.3.8应用程序在JRuby下正确运行。一切正常,直到我启用config.threadsafe!以实现JRuby提供的并发性。这导致lib/中的模块和类不再自动加载。使用config.threadsafe!启用:$rubyscript/runner-eproduction'pSim::Sim200Provisioner'/Users/amchale/.rvm/gems/jruby-1.5.1@web-services/gems/activesupport-2.3.8/lib/active_support/dependencies.rb:105:in`co
我有带有Logo图像的公司模型has_attached_file:logo我用他们的Logo创建了许多公司。现在,我需要添加新样式has_attached_file:logo,:styles=>{:small=>"30x15>",:medium=>"155x85>"}我是否应该重新上传所有旧数据以重新生成新样式?我不这么认为……或者有什么rake任务可以重新生成样式吗? 最佳答案 参见Thumbnail-Generation.如果rake任务不适合你,你应该能够在控制台中使用一个片段来调用重新处理!关于相关公司
我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的
我们目前正在为ROR3.2开发自定义cms引擎。在这个过程中,我们希望成为我们的rails应用程序中的一等公民的几个类类型起源,这意味着它们应该驻留在应用程序的app文件夹下,它是插件。目前我们有以下类型:数据源数据类型查看我在app文件夹下创建了多个目录来保存这些:应用/数据源应用/数据类型应用/View更多类型将随之而来,我有点担心应用程序文件夹被这么多目录污染。因此,我想将它们移动到一个子目录/模块中,该子目录/模块包含cms定义的所有类型。所有类都应位于MyCms命名空间内,目录布局应如下所示:应用程序/my_cms/data_source应用程序/my_cms/data_ty