Android: BaseAdapter重绘相同数据
Android: BaseAdapter redraws the same data
我通过扩展 BaseAdapter 创建了一个自定义适配器,并试图显示一个可滚动的列表视图,只要用户一直滚动到底部,该视图就会展开。但是,在更新底层 ArrayList 时,不是为新元素生成新视图并将它们附加到列表视图的底部,而是重绘 ArrayList 中一些已经存在的元素。
我正在从 Wordpress 博客下载 JSON 数据,并希望在列表视图中显示每个 post 的图像和摘录。我在列表视图中实现了一个侦听器,只要用户滚动到底部就会调用该侦听器。当滚动到底部时,将执行下载下三个最近的博客 posts。下载完成后,我更新 BlogPosts blogPosts
的 ArrayList,如下所示并调用 notifyDataSetChanged()
。
我已检查 JSON 数据是否已正确下载:当我切换到存档视图时,会显示前三个最近的 post(见视频)。下载完成后,调用 addToPosts()
。参数 posts
也是正确的,由接下来的三个 post 组成。
list_view.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/archive_page"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ProgressBar
android:id="@+id/loading_panel_archive"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"
android:layout_gravity="center"/>
<ListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</FrameLayout>
list_view_item.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/test"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="@+id/image_view_lv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
/>
<TextView
android:id="@+id/text_view_lv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:textColor="@color/colorPrimary"/>
</LinearLayout>
CustomAdapter.java
public class CustomAdapter extends BaseAdapter {
private Context context;
private ArrayList<BlogPost> blogPosts;
public CustomAdapter(Context context, ArrayList<BlogPost> blogPosts) {
this.blogPosts = blogPosts;
this.context = context;
}
@Override
public int getViewTypeCount() {
return getCount();
}
@Override
public int getCount() {
return blogPosts.size();
}
@Override
public Object getItem(int i) {
return blogPosts.get(i);
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(final int i, View view, ViewGroup viewGroup) {
final ViewHolder holder;
if (view == null) {
holder = new ViewHolder();
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.list_view_item,
viewGroup, false);
holder.tvname = view.findViewById(R.id.text_view_lv);
holder.iv = view.findViewById(R.id.image_view_lv);
final BlogPost currentPost = (BlogPost) getItem(i);
holder.tvname.setText(currentPost.getContent());
if (!currentPost.isAsyncTaskFinished()){
currentPost.setListener(new BlogPost.ChangeListener() {
@Override
public void onChange() {
holder.iv.setImageBitmap(currentPost.getBitmap());
}
});
}else{
holder.iv.setImageBitmap(currentPost.getBitmap());
}
}
return view;
}
public void addToPosts(ArrayList<BlogPost> posts){
this.blogPosts.addAll(posts);
this.notifyDataSetChanged();
}
private class ViewHolder {
protected TextView tvname;
private ImageView iv;
}
}
列表视图和自定义适配器的设置:
ListView lv = findViewById(R.id.list_view);
CustomAdapter adapter = new CustomAdapter(getApplicationContext(),
firstThreePosts);
lv.setAdapter(adapter);
ProgressBar bar = findViewById(R.id.loading_panel_archive);
bar.setVisibility(View.GONE);
//scroll listener...
我预计接下来的三个 post 会附加到列表视图中,
然而这是发生了什么:
https://1drv.ms/v/s!AuPD10kPw_c5ghHaajc4OYFvkV1K?e=iVc2mS
第六个和第五个post画了一遍又一遍,新的post
永远不会被画出来。
也许 getView
中的参数 i
导致了这种行为,但我真的不明白发生了什么。
任何帮助将不胜感激!
试试这个 getView():
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
final ViewHolder holder;
if (view == null) {
holder = new ViewHolder();
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.list_view_item, viewGroup, false);
holder.tvname = view.findViewById(R.id.text_view_lv);
holder.iv = view.findViewById(R.id.image_view_lv);
view.setTag(holder);
} else {
holder = (ViewHolder)view.getTag();
}
final BlogPost currentPost = (BlogPost) getItem(i);
holder.tvname.setText(currentPost.getContent());
if (!currentPost.isAsyncTaskFinished()){
currentPost.setListener(new BlogPost.ChangeListener() {
@Override
public void onChange() {
holder.iv.setImageBitmap(currentPost.getBitmap());
}
});
}else{
holder.iv.setImageBitmap(currentPost.getBitmap());
}
return view;
}
希望对您有所帮助!
我通过扩展 BaseAdapter 创建了一个自定义适配器,并试图显示一个可滚动的列表视图,只要用户一直滚动到底部,该视图就会展开。但是,在更新底层 ArrayList 时,不是为新元素生成新视图并将它们附加到列表视图的底部,而是重绘 ArrayList 中一些已经存在的元素。
我正在从 Wordpress 博客下载 JSON 数据,并希望在列表视图中显示每个 post 的图像和摘录。我在列表视图中实现了一个侦听器,只要用户滚动到底部就会调用该侦听器。当滚动到底部时,将执行下载下三个最近的博客 posts。下载完成后,我更新 BlogPosts blogPosts
的 ArrayList,如下所示并调用 notifyDataSetChanged()
。
我已检查 JSON 数据是否已正确下载:当我切换到存档视图时,会显示前三个最近的 post(见视频)。下载完成后,调用 addToPosts()
。参数 posts
也是正确的,由接下来的三个 post 组成。
list_view.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/archive_page"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ProgressBar
android:id="@+id/loading_panel_archive"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"
android:layout_gravity="center"/>
<ListView
android:id="@+id/list_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</FrameLayout>
list_view_item.xml
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/test"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="@+id/image_view_lv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
/>
<TextView
android:id="@+id/text_view_lv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:textColor="@color/colorPrimary"/>
</LinearLayout>
CustomAdapter.java
public class CustomAdapter extends BaseAdapter {
private Context context;
private ArrayList<BlogPost> blogPosts;
public CustomAdapter(Context context, ArrayList<BlogPost> blogPosts) {
this.blogPosts = blogPosts;
this.context = context;
}
@Override
public int getViewTypeCount() {
return getCount();
}
@Override
public int getCount() {
return blogPosts.size();
}
@Override
public Object getItem(int i) {
return blogPosts.get(i);
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(final int i, View view, ViewGroup viewGroup) {
final ViewHolder holder;
if (view == null) {
holder = new ViewHolder();
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.list_view_item,
viewGroup, false);
holder.tvname = view.findViewById(R.id.text_view_lv);
holder.iv = view.findViewById(R.id.image_view_lv);
final BlogPost currentPost = (BlogPost) getItem(i);
holder.tvname.setText(currentPost.getContent());
if (!currentPost.isAsyncTaskFinished()){
currentPost.setListener(new BlogPost.ChangeListener() {
@Override
public void onChange() {
holder.iv.setImageBitmap(currentPost.getBitmap());
}
});
}else{
holder.iv.setImageBitmap(currentPost.getBitmap());
}
}
return view;
}
public void addToPosts(ArrayList<BlogPost> posts){
this.blogPosts.addAll(posts);
this.notifyDataSetChanged();
}
private class ViewHolder {
protected TextView tvname;
private ImageView iv;
}
}
列表视图和自定义适配器的设置:
ListView lv = findViewById(R.id.list_view);
CustomAdapter adapter = new CustomAdapter(getApplicationContext(),
firstThreePosts);
lv.setAdapter(adapter);
ProgressBar bar = findViewById(R.id.loading_panel_archive);
bar.setVisibility(View.GONE);
//scroll listener...
我预计接下来的三个 post 会附加到列表视图中, 然而这是发生了什么: https://1drv.ms/v/s!AuPD10kPw_c5ghHaajc4OYFvkV1K?e=iVc2mS
第六个和第五个post画了一遍又一遍,新的post
永远不会被画出来。
也许 getView
中的参数 i
导致了这种行为,但我真的不明白发生了什么。
任何帮助将不胜感激!
试试这个 getView():
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
final ViewHolder holder;
if (view == null) {
holder = new ViewHolder();
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.list_view_item, viewGroup, false);
holder.tvname = view.findViewById(R.id.text_view_lv);
holder.iv = view.findViewById(R.id.image_view_lv);
view.setTag(holder);
} else {
holder = (ViewHolder)view.getTag();
}
final BlogPost currentPost = (BlogPost) getItem(i);
holder.tvname.setText(currentPost.getContent());
if (!currentPost.isAsyncTaskFinished()){
currentPost.setListener(new BlogPost.ChangeListener() {
@Override
public void onChange() {
holder.iv.setImageBitmap(currentPost.getBitmap());
}
});
}else{
holder.iv.setImageBitmap(currentPost.getBitmap());
}
return view;
}
希望对您有所帮助!