我有一个带有RecyclerView
和自定义Adapter
的应用,它可以从解析后端获取。
我的适配器包含一些TextView
,一个Button
,一个小ImageView
。我的TextView
中的某些Adapter
需要在onBindViewHolder()
的{{1}}中使用函数(计算upvote计数和类似内容)来获取数据。
我注意到由于onBindViewHolder()
中调用的函数,我的滚动速度非常慢且滞后。
我应该在哪里设置数据并调用我的函数才能顺利滚动?
编辑1:
这是我的适配器代码:
public class PostAdapter extends RecyclerView.Adapter<PostAdapter.ViewHolder> {
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView postName;
public ImageView postCatIcon;
public TextView postDays;
public TextView postDaysLabel;
public TextView postHours;
public TextView postHoursLabel;
public TextView postMinutes;
public TextView postMinutesLabel;
public TextView postDistance;
public TextView postLikes;
public TextView postAuthor;
public LikeButton likepost;
private Post post;
public ViewHolder(View itemView) {
super(itemView);
postName = (TextView) itemView.findViewById(R.id.post_name);
postCatIcon = (ImageView) itemView.findViewById(R.id.post_cat_icon);
postDays = (TextView) itemView.findViewById(R.id.post_days);
postDaysLabel = (TextView) itemView.findViewById(R.id.post_days_label);
postHours = (TextView) itemView.findViewById(R.id.post_hours);
postHoursLabel = (TextView) itemView.findViewById(R.id.post_hours_label);
postMinutes = (TextView) itemView.findViewById(R.id.post_minutes);
postMinutesLabel = (TextView) itemView.findViewById(R.id.post_minutes_label);
postDistance = (TextView) itemView.findViewById(R.id.post_distance);
likePost = (LikeButton) itemView.findViewById(R.id.like_the_post);
postAuthor = (TextView) itemView.findViewById(R.id.post_author);
postLikes = (TextView) itemView.findViewById(R.id.post_likes);
}
public void setData(Post post){
this.post = post;
updateTimeRemaining(System.currentTimeMillis());
}
public void updateTimeRemaining(long currentTime) {
long diff = post.getDate().getTime() - currentTime;
int minutes = (int) ((diff / (1000*60)) % 60);
int hours = (int) ((diff / (1000*60*60)) % 24);
int days = (int) (diff / (1000*60*60*24));
String strgMinutes = "00";
String strgHours = "00";
String strgDays = "00";
if(minutes < 10)
strgMinutes = "0" + String.valueOf(minutes);
else
strgMinutes = String.valueOf(minutes);
if(hours < 10)
strgHours = "0" + String.valueOf(hours);
else
strgHours = String.valueOf(hours);
if(days < 10){
strgDays = "0" + String.valueOf(days);
}else
strgDays = String.valueOf(days);
postDays.setText(strgDays);
postHours.setText(strgHours);
postMinutes.setText(strgMinutes);
}
}
public static class ProgressViewHolder extends PostAdapter.ViewHolder {
public ProgressBar progressBar;
public ProgressViewHolder(View v) {
super(v);
progressBar = (ProgressBar) v.findViewById(R.id.progressBar);
}
}
private List<Post> mPosts;
private Context mContext;
private ListFragment mFragment;
private final int VIEW_ITEM = 1;
private final int VIEW_PROG = 0;
ArrayList<PostAdapter.ViewHolder> viewHoldersList;
private Handler handler = new Handler();
private Runnable updateRemainingTimeRunnable = new Runnable() {
@Override
public void run() {
long currentTime = System.currentTimeMillis();
synchronized (viewHoldersList) {
for (PostAdapter.ViewHolder holder : viewHoldersList) {
holder.updateTimeRemaining(currentTime);
}
}
handler.postDelayed(this, 60000);
}
};
// The minimum amount of items to have below your current scroll position before loading more.
private int visibleThreshold = 2;
private int lastVisibleItem, totalItemCount;
private boolean loading;
private OnLoadMoreListener onLoadMoreListener;
public PostAdapter(List<Post> posts, Context context, ListFragment fragment, RecyclerView recyclerView) {
mContext = context;
mPosts = posts;
mFragment = fragment;
if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) {
final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
totalItemCount = linearLayoutManager.getItemCount();
lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
if (!loading && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
// End has been reached
// Do something
if (onLoadMoreListener != null) {
onLoadMoreListener.onLoadMore();
}
loading = true;
}
}
});
}
viewHoldersList = new ArrayList<>();
startUpdateTimer();
}
public PostAdapter(List<Post> posts, Context context, RecyclerView recyclerView) {
mContext = context;
mPosts = posts;
if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) {
final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
totalItemCount = linearLayoutManager.getItemCount();
lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
if (!loading && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
// End has been reached
// Do something
if (onLoadMoreListener != null) {
onLoadMoreListener.onLoadMore();
}
loading = true;
}
}
});
}
viewHoldersList = new ArrayList<>();
startUpdateTimer();
}
private void startUpdateTimer() {
handler.postDelayed(updateRemainingTimeRunnable,60000);
}
public PostAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
View postView;
ViewHolder viewHolder;
if (viewType == VIEW_ITEM) {
postView = inflater.inflate(R.layout.list_item, parent, false);
viewHolder = new ViewHolder(postView);
} else {
postView = inflater.inflate(R.layout.loading_item, parent, false);
viewHolder = new ProgressViewHolder(postView);
}
return viewHolder;
}
public void onBindViewHolder(final PostAdapter.ViewHolder viewHolder, final int position) {
if (viewHolder instanceof ViewHolder) {
final Post post = mPosts.get(position);
if(post != null){
synchronized (viewHoldersList) {
viewHolder.setData(post);
viewHoldersList.add(viewHolder);
}
Category cat = post.getCategory();
TextView nameTextView = viewHolder.postName;
TextView authorTextView = viewHolder.postAuthor;
final TextView likesTextView = viewHolder.postLikes;
ImageView CatIconView = viewHolder.postCatIcon;
final LikeButton likeButtonView = viewHolder.likePost;
TextView postDistance = viewHolder.postDistance;
ParseUser postAuthor = null;
if(mFragment != null) {
if (mFragment.getIfFilteredByDistance()) {
postDistance.setVisibility(View.VISIBLE);
Location postLocation = new Location("Post location");
if(post.getLocation() != null){
postLocation.setLongitude(post.getLocation().getLongitude());
postLocation.setLatitude(post.getLocation().getLatitude());
GPSTracker gpsTracker = new GPSTracker(mContext);
if (gpsTracker.canGetLocation()) {
Location myLocation = new Location("My location");
myLocation.setLatitude(gpsTracker.getLatitude());
myLocation.setLongitude(gpsTracker.getLongitude());
postDistance.setText((Math.round(myLocation.distanceTo(postLocation)) / 1000) + " km");
} else
gpsTracker.showSettingsAlert();
}
} else
postDistance.setVisibility(View.INVISIBLE);
}
try{
postAuthor = post.getAuthor().fetchIfNeeded();
}catch (ParseException e){
Log.e("Parse:", e.getMessage());
}
saveActivitiesToLocalDatastore(post);
final int likeCount = ((PostApplication)mContext).getPostLikeCount(post);
likesTextView.setText(String.valueOf(likeCount));
likeButtonView.setLiked(((PostApplication)mContext).getIfLiked(post));
viewHolder.itemView.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
Intent intent = new Intent(mContext, DetailActivity.class);
intent.putExtra("PostID",post.getObjectId());
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);
}
});
likeButtonView.setOnLikeListener(new OnLikeListener() {
@Override
public void liked(LikeButton likeButton) {
if(((PostApplication)mContext).likePost(post))
likesTextView.setText(String.valueOf(Integer.parseInt(likesTextView.getText().toString()) + 1));
}
@Override
public void unLiked(LikeButton likeButton) {
if(((PostApplication)mContext).unlikePost(post))
likesTextView.setText(String.valueOf(Integer.parseInt(likesTextView.getText().toString()) -1));
}
});
nameTextView.setText(post.getTitle());
authorTextView.setText(post.getAuthor().getUsername());
CatIconView.setImageDrawable(ContextCompat.getDrawable(mContext,mContext.getResources().getIdentifier(cat.getIconName()+"_18dp","drawable",mContext.getPackageName())));
}
} else {
((ProgressViewHolder) viewHolder).progressBar.setIndeterminate(true);
}
}
public int getItemCount() {
return mPosts.size();
}
private void saveActivitiesToLocalDatastore(final Post post){
// Saves Likes to Parse local datastore
}
@Override
public int getItemViewType(int position) {
return mposts.get(position) != null ? VIEW_ITEM : VIEW_PROG;
}
public void setLoaded() {
loading = false;
}
public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) {
this.onLoadMoreListener = onLoadMoreListener;
}
public interface OnLoadMoreListener {
void onLoadMore();
}
编辑2:
我按照这个来修复我倒计时的闪烁:
Recyclerview with multiple countdown timers causes flickering
编辑3:
我尝试运行应用程序而没有像saveActivitiesInBackgroud这样的附加方法,而且听众也很顺利
答案 0 :(得分:2)
如果你想使用RecyclerView你需要使用onBindViewHolder。它与OnBindViewHolder没有问题。问题是你的意大利面条代码,你也没有存储信息,所以这导致你的recyclerview滞后
答案 1 :(得分:1)
尽量不要在ViewHolder
之外更改onBindViewHolder()
州。 ViewHolder
表示屏幕上的视图,但不代表数据本身。 RecyclerView
会在屏幕上显示不可见时重复使用视图,因此会重复使用附加到该视图的ViewHolder
视图。
永远不要存储ViewHolder
- RecyclerView
负责管理它们。
如果您仅在60 sec
仅notifyDataSetChanges
更新计时器,而不是直接更新ViewHolder
。并在适当的时间更新onBindViewHolder
中的视图状态。