I've got a problem with ListView. When app starts it loads 10 posts from net and show them. When you get to bottom of ListView I start load next 10 post and add them at the end of list. And when I call notifyDataSetChanged()
ListView will redraw elements which doesn't change. And that cause strange blinking of images.
I've read that hasStableIds()
could help, and tried to set it in both values, but it doesn't help.
Here's my Adapter code:
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;
}
}
There's log where you can see that Adapter reload views again just after notifyDataSetChanged()
, even if i doesn't scroll it.
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
Also notifyDataSetChanged()
i call from handler in MainActivity thread:
@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());
}
}
};
}
So can you describe me how to fix this and why it doesn't work.
Thank you in advance for you help.