我遇到了ListView的问题。当应用程序启动时,它会从网上加载10个帖子并显示它们。当你到达ListView的底部时,我开始加载下一个10帖子并在列表末尾添加它们。当我调用notifyDataSetChanged()
时,ListView将重绘不会改变的元素。这会导致奇怪的图像闪烁。
我读过hasStableIds()
可以提供帮助,并试图在两个值中设置它,但它没有帮助。
这是我的适配器代码:
public class PostListAdapter extends BaseAdapter {
Context context;
ArrayList<Post> posts;
LayoutInflater inflater;
View.OnClickListener onClickListener;
public PostListAdapter(Context context, ArrayList<Post> posts, View.OnClickListener onClickListener){
this.posts = posts; this.context = context; inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.onClickListener = onClickListener;
}
@Override
public int getCount() {
return posts.size();
}
@Override
public Object getItem(int position) {
return posts.get(position);
}
@Override
public long getItemId(int position) {
return (long)posts.get(position).id;
}
@Override
public boolean hasStableIds() {
return true;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
System.out.println("draw " + posts.get(position).id);
LinearLayout mainLayout;
if (convertView == null) {
mainLayout = (LinearLayout) inflater.inflate(R.layout.post, null, false);
}else {
mainLayout = (LinearLayout) convertView;
LinearLayout cont = (LinearLayout) mainLayout.findViewById(R.id.image_container);
while (cont.getChildCount() != 0){
cont.removeViewAt(0);
}
}
LinearLayout imageContainer = (LinearLayout) mainLayout.findViewById(R.id.image_container);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
Post post = posts.get(position);
TextView textView = (TextView)mainLayout.findViewById(R.id.postLink);
textView.setText("http://joyreactor.cc/post/" + Integer.toString(post.id));
textView.setPaintFlags(textView.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG);
textView.setOnClickListener(onClickListener);
ArrayList<ImageView> images = new ArrayList<>();
for (int i=0; i<post.images.size(); i++){
ScaleImageView image = new ScaleImageView(context);
image.setPadding(0, 10, 0, 0);
image.setImageBitmap(Bitmap.createBitmap(post.sizes.get(i)[0], post.sizes.get(i)[1], Bitmap.Config.RGB_565));
//image.setImageResource(R.drawable.grill);
image.setLayoutParams(params);
ImageLoader loader = new ImageLoader(image, post, i, context);
loader.execute(post.images.get(i));
post.loaders.add(loader);
imageContainer.addView(image);
}
if (post.images.size() == 0){
ScaleImageView image = new ScaleImageView(context);
image.setLayoutParams(params);
image.setImageBitmap(MainActivity.bmpMissPicture);
imageContainer.addView(image);
}
mainLayout.setTag(post);
return mainLayout;
}
}
在notifyDataSetChanged()
之后,您可以看到适配器重新加载视图的日志,即使我没有滚动它。
05-11 21:00:46.406 4391-4391/com.olleggerr.joyrector I/System.out: draw 3098998
05-11 21:00:46.414 4391-4391/com.olleggerr.joyrector I/System.out: draw 3099753
05-11 21:00:46.416 4391-4391/com.olleggerr.joyrector I/System.out: draw 3098998
05-11 21:00:46.417 4391-4391/com.olleggerr.joyrector I/System.out: draw 3099753
05-11 21:00:49.039 4391-4391/com.olleggerr.joyrector I/System.out: draw 3100202
05-11 21:00:49.172 4391-4391/com.olleggerr.joyrector I/System.out: draw 3100315
05-11 21:00:49.304 4391-4391/com.olleggerr.joyrector I/System.out: draw 3100328
05-11 21:00:49.455 4391-4391/com.olleggerr.joyrector I/System.out: draw 3098651
05-11 21:00:49.755 4391-4391/com.olleggerr.joyrector I/System.out: draw 3100191
05-11 21:00:50.038 4391-4391/com.olleggerr.joyrector I/System.out: draw 3100287
05-11 21:00:51.754 4391-4391/com.olleggerr.joyrector I/System.out: draw 3100348
05-11 21:00:51.838 4391-4391/com.olleggerr.joyrector I/System.out: draw 3100386
05-11 21:00:51.938 4391-4391/com.olleggerr.joyrector I/System.out: draw 3100348
05-11 21:00:52.411 4391-4691/com.olleggerr.joyrector I/System.out: 10 posts load started!
05-11 21:00:56.806 4391-4391/com.olleggerr.joyrector I/System.out: calling notifyDataSetChanged()
05-11 21:00:56.807 4391-4391/com.olleggerr.joyrector I/System.out: Size after load more posts 20
05-11 21:00:56.821 4391-4391/com.olleggerr.joyrector I/System.out: draw 3098998
05-11 21:00:56.821 4391-4391/com.olleggerr.joyrector I/System.out: draw 3099753
05-11 21:00:56.822 4391-4391/com.olleggerr.joyrector I/System.out: draw 3100348
05-11 21:00:56.822 4391-4391/com.olleggerr.joyrector I/System.out: draw 3100386
同样notifyDataSetChanged()
我在MainActivity线程中从处理程序调用:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bmpMissPicture = Bitmap.createBitmap(500, 500, Bitmap.Config.RGB_565);
Canvas c = new Canvas(bmpMissPicture);
Paint p = new Paint();
ListView listView = (ListView) findViewById(R.id.postList);
View.OnClickListener onClickListener = new View.OnClickListener(){
@Override
public void onClick(View v) {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(((TextView) v).getText().toString()));
startActivity(browserIntent);
}
};
adapter = new PostListAdapter(getApplicationContext(), posts, onClickListener);
listView.setAdapter(adapter);
p.setColor(getResources().getColor(R.color.missPicColor));
c.drawRect(0, 0, 500, 500, p);
handler = new Handler(Looper.getMainLooper()){
@Override
public void handleMessage(Message msg) {
System.out.println("calling notifyDataSetChanged()");
if (msg.what == 0) {
((LinearLayout) findViewById(R.id.mainContainer)).removeViewAt(0);
findViewById(R.id.mainContainer).invalidate();
findViewById(R.id.postList).invalidate();
adapter.notifyDataSetChanged();
//System.out.println(posts.size());
final ListView listView = (ListView) findViewById(R.id.postList);
new Thread(new Runnable() {
@Override
public void run() {
while (!stopAskUpdate){
int pos = listView.getLastVisiblePosition();
//Log.d("Inf Scroll", "Pos: " + (pos+1) + " of " + posts.size());
if (pos >= posts.size()-1 && !loadNewPosts){
MainActivity.loadNewPosts = true;
new PageParser("http://joyreactor.cc/" + nextPage, posts, MainActivity.handler, false).start();
}
try{Thread.sleep(1500);}catch (InterruptedException e){}
}
}
}).start();
}else {
adapter.notifyDataSetChanged();
System.out.println("Size after load more posts " + posts.size());
}
}
};
}
所以你能告诉我如何解决这个问题以及为什么它不起作用。
提前感谢您的帮助。
答案 0 :(得分:0)
我猜您遇到的问题是因为您可能会一次又一次地在“活动”类中初始化“适配器”。每次在“数组”中添加新项时,都可能正在初始化适配器,然后在设置适配器后调用“notifyDataSetChanged()”方法。请让您初始化适配器一次。
另外一个建议是尝试使用“Picasso”库进行图像加载。
答案 1 :(得分:0)
我找到了办法。你应该做BasicAdapter应该做的工作,但由于某些原因它没有做到。在使用convertView
中的新数据填充getView()
之前,您应检查convertView
是否已包含该数据。对于我的情况,解决方案看起来像:
@Override
public long getItemId(int position) {
return (long)posts.get(position).id;
}
public View getView(int position, View convertView, ViewGroup parent) {
boolean flag = false;
LinearLayout mainLayout;
if (convertView == null) {
flag = true;
mainLayout = (LinearLayout) inflater.inflate(R.layout.post, null, false);
}else {
mainLayout = (LinearLayout) convertView;
if (((Post)convertView.getTag()).id != getItemId(position)){ //View tag contain link to the post.
flag = true;
LinearLayout cont = (LinearLayout) mainLayout.findViewById(R.id.image_container);
while (cont.getChildCount() != 0){
cont.removeViewAt(0);
}
}
}
if (flag) {
//do some stuff with mainLayout....
mainLayout.setTag(posts.get(position));
}
return mainLayout;
因此,如果convertView
代表getView()
个请求的帖子,我们只会返回它而不做任何更改,否则我们会进行更改以代表新帖子。
由于方法hasStableIds()
我认为适配器是自己做的并且防止无用的getView()
调用,但他没有。
希望它会对某人有所帮助,并感谢您的回答和评论。
答案 2 :(得分:0)
您可以在数组中添加和删除项目,并可以调用notifyItemInserted或notifyitemRemoved,这将使您获得更好的性能。此外,使用毕加索将是一个不错的选择。