【发布时间】:2016-09-08 07:15:57
【问题描述】:
我有一个应用程序,其中在 RecyclerView 中有多个视图(不同类型的列表项)。从数据库中获取数据后,每个项目都会更新。我在滚动 RecyclerView 中的项目时遇到了粘滞滚动的问题。我确信这是由于数据库访问操作而发生的,我试图解决这个问题。我参考了 StackOverflow 上的几个答案,还阅读了官方的 android 帖子(Making ListView Scrolling Smooth)。正如 android 帖子中所建议的那样,我使用 AsyncTask 将所有数据库访问操作移至后台线程,但仍然没有运气。
下面是我在onBindViewHolder 中编写的代码,用于更新其中一项。
new AsyncTask<RecyclerView.ViewHolder, Void, TaskPhysicalActivity>(){
private RecyclerView.ViewHolder v;
PhysicalActivityItemHolder pAItemHolder;
DBHelper mDbHelper;
User mUser;
@Override
protected TaskPhysicalActivity doInBackground(RecyclerView.ViewHolder... params) {
pAItemHolder = (PhysicalActivityItemHolder)params[0];
Calendar cal = Calendar.getInstance();
Calendar today = Calendar.getInstance();
Calendar earlier = Calendar.getInstance();
earlier.add(Calendar.DATE, -6);
mDbHelper = DBHelper.getInstance(mContext);
mUser = User.getDefaultUser(mContext);
try {
List<PhysicalActivity> physicalActivities = mDbHelper.getPhysicalActivityInRange(mUser, cal, cal);
PhysicalActivityReport physicalActivityReport = new PhysicalActivityReport(earlier.getTime(), today.getTime());
physicalActivityReport.makeReport(mContext, mUser);
int userStepGoal = PhysicalActivity.getDailyStepsGoal(mContext);
return new TaskPhysicalActivity(userStepGoal, physicalActivityReport.getPhysicalActivityList(), physicalActivities,physicalActivityReport);
} catch (ParseException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(TaskPhysicalActivity taskPhysicalActivity) {
int stepsCount = 0;
Calendar cal = Calendar.getInstance();
TaskPhysicalActivity taskPhysicalActivityObject = taskPhysicalActivity;
List<PhysicalActivity> physicalActivities = taskPhysicalActivityObject.getPhysicalActivities();
List<PhysicalActivity> activityList = taskPhysicalActivityObject.getActivityList();
PhysicalActivityReport physicalActivityReport = taskPhysicalActivityObject.getPhysicalActivityReport();
pAItemHolder.tvActivityEmptyText.setVisibility(View.GONE);
if (physicalActivities.size() > 0) {
for (int i = 0; i < physicalActivities.size(); i++) {
stepsCount = stepsCount
+ physicalActivities.get(i).getValue();
}
final int finalStepsCount = stepsCount > 0 ? stepsCount : 0;
pAItemHolder.tvActivityValue.setText(String.valueOf(finalStepsCount));
pAItemHolder.tvActivityValueText.setText(mContext.getResources().getString(R.string.steps_unit));
pAItemHolder.tvActivityEmptyText.setText("");
pAItemHolder.vActivityCardEmptyView.setVisibility(View.GONE);
pAItemHolder.vActivityCardView.setVisibility(View.VISIBLE);
} else {
pAItemHolder.tvActivityValue.setText("--");
pAItemHolder.tvActivityValueText.setText(mContext.getResources().getString(R.string.steps_unit));
pAItemHolder.tvActivityEmptyText.setText("");
pAItemHolder.vActivityCardEmptyView.setVisibility(View.VISIBLE);
pAItemHolder.vActivityCardView.setVisibility(View.GONE);
}
pAItemHolder.tvActivityGoal.setText(String.format(mContext.getResources().getString(R.string.activity_goal_display_string),
taskPhysicalActivityObject.getUserStepsGoal(), mContext.getResources().getString(R.string.steps_unit), mContext.getResources().getString(R.string.per_day)));
pAItemHolder.vActivityGraph.setActivityValues(activityList);
if (physicalActivityReport.getPhysicalActivityAverage() > 0) {
pAItemHolder.tvPercentInRange.setText("Average steps " + physicalActivityReport.getPhysicalActivityAverage());
}
if (activityList.size() == 0) {
pAItemHolder.vActivityCardEmptyView.setVisibility(View.VISIBLE);
pAItemHolder.vActivityCardView.setVisibility(View.GONE);
} else {
pAItemHolder.vActivityCardEmptyView.setVisibility(View.GONE);
pAItemHolder.vActivityCardView.setVisibility(View.VISIBLE);
}
}
}.execute(holder);
在上面的代码中,doInBackground 内的以下四行执行数据库访问:
List<PhysicalActivity> physicalActivities = mDbHelper.getPhysicalActivityInRange(mUser, cal, cal);
PhysicalActivityReport physicalActivityReport = new PhysicalActivityReport(earlier.getTime(), today.getTime());
physicalActivityReport.makeReport(mContext, mUser);
int userStepGoal = PhysicalActivity.getDailyStepsGoal(mContext);
我使用这些操作的结果来更新 onPostExecute 方法中的 UI。
我使用 AsyncTask 的方式有问题吗?我错过了什么吗?
【问题讨论】:
-
onbindToViewHolder 方法旨在快速获取对象,加载其内容并将此内容加载到视图,而不是执行逻辑。 AcyncTask 或 Thread 应该在片段或活动中。只有结果应该传递给适配器,所以当绑定到视图持有者时,你的数据准备好了。
-
@Rafal 你的回答听起来很棒!你有任何可以证明相同的样本 sn-p 吗?即使我在我的 FirebaseRecyclerAdapter 中也面临着粘性和滞后滚动的问题。帮助将不胜感激。谢谢!
标签: android listview android-asynctask android-recyclerview