我正在使用自定义cursoradapter类的Recyclerview。适配器包含onClickListener,因此当用户长按一行时,用户将获得一个contextMenu,要求从recyclerview中删除所单击的行。
一切都按预期工作,但是当方向发生变化或者由于onResume()
中的破坏(由于缺乏或RAM或其他)而重建活动时,再循环视图不会在长时间点击时刷新,但适配器内容已正确更改。
请注意changeCursor()
来电notifyDataSetChanged()
。一切正常,除了方向改变或活动娱乐。光标数据和适配器都会更改,但旧数据仍然可见。 (注意:仅当Android系统重新创建活动时)可能是什么问题?
这是我的适配器类:
public class ScheduleAdapter extends CursorRecyclerViewAdapter<ScheduleAdapter.ViewHolder> {
private static Context context;
private int position;
public ScheduleAdapter(Context context, Cursor cursor) {
super(cursor);
ScheduleAdapter.context = context;
}
@SuppressLint("SimpleDateFormat")
@Override
public void onBindViewHolder(final ViewHolder viewHolder, final Cursor cursor) {
TextView lessonName = viewHolder.lessonName;
final TextView lessonTime = viewHolder.lessonTime;
TextView lessonRoom = viewHolder.lessonRoom;
TextView lessonComponent = viewHolder.lessonComponent;
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmm");
long databaseDateStart = Long.parseLong(cursor.getString(2).replaceAll("-", "") + cursor.getString(3).replaceAll(":", ""));
long databaseDateEnd = Long.parseLong(cursor.getString(2).replaceAll("-", "") + cursor.getString(4).replaceAll(":", ""));
long currentDate = Long.parseLong(simpleDateFormat.format(new Date()));
lessonName.setText(cursor.getString(5));
lessonRoom.setText(cursor.getString(6));
lessonComponent.setText(cursor.getString(7));
if (databaseDateStart <= currentDate && databaseDateEnd >= currentDate) {
lessonTime.setTextColor(ContextCompat.getColor(context, R.color.colorAccent));
lessonTime.setText(ApplicationLoader.applicationContext.getResources().getString(R.string.lesson_started));
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!lessonTime.getText().toString().equals(ApplicationLoader.applicationContext.getResources().getString(R.string.lesson_started))) {
TranslateAnimation animation = new TranslateAnimation(
Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, -1.0f, Animation.RELATIVE_TO_SELF, 0.0f
);
animation.setDuration(100);
lessonTime.setAnimation(animation);
lessonTime.setTextColor(ContextCompat.getColor(context, R.color.colorAccent));
lessonTime.setText(ApplicationLoader.applicationContext.getResources().getString(R.string.lesson_started));
} else {
TranslateAnimation animation = new TranslateAnimation(
Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, 1.0f, Animation.RELATIVE_TO_SELF, 0.0f
);
animation.setDuration(100);
lessonTime.setAnimation(animation);
String lessonTimes = cursor.getString(3) + " - " + cursor.getString(4);
lessonTime.setTextColor(ContextCompat.getColor(context, R.color.colorSecondaryText));
lessonTime.setText(lessonTimes);
}
}
});
} else if (databaseDateEnd < currentDate) {
lessonTime.setTextColor(ContextCompat.getColor(context, R.color.colorAccent));
lessonTime.setText(ApplicationLoader.applicationContext.getResources().getString(R.string.finished));
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!lessonTime.getText().toString().equals(ApplicationLoader.applicationContext.getResources().getString(R.string.finished))) {
TranslateAnimation animation = new TranslateAnimation(
Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, -1.0f, Animation.RELATIVE_TO_SELF, 0.0f
);
animation.setDuration(100);
lessonTime.setAnimation(animation);
lessonTime.setTextColor(ContextCompat.getColor(context, R.color.colorAccent));
lessonTime.setText(ApplicationLoader.applicationContext.getResources().getString(R.string.finished));
} else {
TranslateAnimation animation = new TranslateAnimation(
Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f,
Animation.RELATIVE_TO_SELF, 1.0f, Animation.RELATIVE_TO_SELF, 0.0f
);
animation.setDuration(100);
lessonTime.setAnimation(animation);
String lessonTimes = cursor.getString(3) + " - " + cursor.getString(4);
lessonTime.setTextColor(ContextCompat.getColor(context, R.color.colorSecondaryText));
lessonTime.setText(lessonTimes);
}
}
});
} else {
String lessonTimes = cursor.getString(3) + " - " + cursor.getString(4);
lessonTime.setTextColor(ContextCompat.getColor(context, R.color.colorSecondaryText));
lessonTime.setText(lessonTimes);
viewHolder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
setPosition(viewHolder.getAdapterPosition());
return false;
}
});
}
}
@Override
public void onViewRecycled(ViewHolder holder) {
holder.itemView.setOnLongClickListener(null);
super.onViewRecycled(holder);
}
/**
* Gets the row id in SQLite based on the adapter's position.
*
* @return the id
*/
public long getLessonId() {
return super.getItemId(position);
}
private void setPosition(int position) {
this.position = position;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(context).
inflate(R.layout.schedule_adapter_item, parent, false);
return new ViewHolder(itemView);
}
public static class ViewHolder extends RecyclerView.ViewHolder {
final TextView lessonName;
final TextView lessonTime;
final TextView lessonRoom;
final TextView lessonComponent;
public ViewHolder(View view) {
super(view);
lessonName = (TextView) view.findViewById(R.id.schedule_list_row_name);
lessonTime = (TextView) view.findViewById(R.id.schedule_list_row_time);
lessonRoom = (TextView) view.findViewById(R.id.schedule_list_row_room);
lessonComponent = (TextView) view.findViewById(R.id.schedule_list_row_component);
}
}
}
这里是我的片段:
public class ScheduleFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {
private static String componentId;
private static int type;
private Date date;
private ScheduleAdapter adapter;
private DateFormat simpleDateFormat;
private SwipeRefreshLayout swipeRefreshLayout;
private long onLongClickId;
private TextView emptyTextView;
private ProgressBar spinner;
private RecyclerView recyclerView;
@SuppressLint("SimpleDateFormat")
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
componentId = getArguments().getString("componentId");
type = getArguments().getInt("type");
date = (Date) getArguments().getSerializable("date");
simpleDateFormat = new SimpleDateFormat("yyyyMMdd");
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
menu.add(0, 0, 0, getResources().getString(R.string.hide_lesson));
menu.add(0, 1, 1, getResources().getString(R.string.save_lesson));
}
@Override
public boolean onContextItemSelected(MenuItem item) {
if (getUserVisibleHint() && adapter != null) {
onLongClickId = adapter.getLessonId();
if (item.getItemId() == 0) {
showPromptDialog();
return true;
}
if (item.getItemId() == 1) {
Cursor cursor = ApplicationLoader.scheduleDatabase.getSingleLesson(onLongClickId);
if (cursor.moveToFirst()) {
String[] startTimeStrings = cursor.getString(0).split(":");
String[] endTimeStrings = cursor.getString(1).split(":");
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
calendar.set(Calendar.HOUR_OF_DAY, Integer.parseInt(startTimeStrings[0]));
calendar.set(Calendar.MINUTE, Integer.parseInt(startTimeStrings[1]));
Intent intent = new Intent(Intent.ACTION_EDIT);
intent.setType("vnd.android.cursor.item/event");
intent.putExtra("beginTime", calendar.getTimeInMillis());
intent.putExtra("allDay", false);
calendar.set(Calendar.HOUR_OF_DAY, Integer.parseInt(endTimeStrings[0]));
calendar.set(Calendar.MINUTE, Integer.parseInt(endTimeStrings[1]));
intent.putExtra("endTime", calendar.getTimeInMillis());
intent.putExtra("title", cursor.getString(2));
intent.putExtra("eventLocation", cursor.getString(3));
try {
startActivity(intent);
} catch (ActivityNotFoundException e) {
ScheduleActivity.showSnackbar(getResources().getString(R.string.no_calendar_found));
}
}
cursor.close();
return true;
}
}
return false;
}
@Override
public void onResume() {
super.onResume();
if (getUserVisibleHint()) {
if (recyclerView != null && recyclerView.getAdapter() == null) {
new ScheduleFetcher(false, true, false).execute();
} else {
new ScheduleFetcher(false, false, false).execute();
}
}
}
@SuppressLint("SimpleDateFormat")
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd");
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
int month = calendar.get(Calendar.MONTH);
String monthString = null;
switch (month) {
case 0:
monthString = getResources().getString(R.string.january);
break;
case 1:
monthString = getResources().getString(R.string.february);
break;
case 2:
monthString = getResources().getString(R.string.march);
break;
case 3:
monthString = getResources().getString(R.string.april);
break;
case 4:
monthString = getResources().getString(R.string.may);
break;
case 5:
monthString = getResources().getString(R.string.june);
break;
case 6:
monthString = getResources().getString(R.string.july);
break;
case 7:
monthString = getResources().getString(R.string.august);
break;
case 8:
monthString = getResources().getString(R.string.september);
break;
case 9:
monthString = getResources().getString(R.string.october);
break;
case 10:
monthString = getResources().getString(R.string.november);
break;
case 11:
monthString = getResources().getString(R.string.december);
}
ActionBar toolbar = ((ScheduleActivity) getActivity()).getSupportActionBar();
if (toolbar != null) {
toolbar.setTitle(simpleDateFormat.format(date) + " " + monthString);
// ugly workaround to fix toolbar title truncation
toolbar.setDisplayHomeAsUpEnabled(false);
toolbar.setDisplayHomeAsUpEnabled(true);
}
if (!ApplicationLoader.scheduleDatabase.containsWeek(date) &&
!ApplicationLoader.scheduleDatabase.isFetched(date)) {
new ScheduleFetcher(true, true, false).execute();
} else {
new ScheduleFetcher(false, false, false).execute();
}
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle
savedInstanceState) {
ViewGroup viewGroup = (ViewGroup) inflater.inflate(R.layout.fragment_schedule, container, false);
swipeRefreshLayout = (SwipeRefreshLayout) viewGroup.findViewById(R.id.swipe_refresh_layout);
swipeRefreshLayout.setOnRefreshListener(this);
swipeRefreshLayout.setColorSchemeResources(R.color.colorAccent, R.color.colorPrimaryText, R.color.colorPrimary);
emptyTextView = (TextView) viewGroup.findViewById(R.id.schedule_not_found);
spinner = (ProgressBar) viewGroup.findViewById(R.id.progress_bar);
recyclerView = (RecyclerView) viewGroup.findViewById(R.id.schedule_recyclerview);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
Cursor scheduleDay = ApplicationLoader.scheduleDatabase.getLessons(
simpleDateFormat.format(date), componentId);
if (scheduleDay != null && scheduleDay.getCount() > 0) {
adapter = new ScheduleAdapter(getActivity(), scheduleDay);
recyclerView.setAdapter(adapter);
}
registerForContextMenu(recyclerView);
if (recyclerView != null && recyclerView.getAdapter() != null) {
emptyTextView.setVisibility(View.GONE);
}
return viewGroup;
}
private void alertConnectionProblem() {
if (!getUserVisibleHint()) {
return;
}
ApplicationLoader.runOnUIThread(new Runnable() {
@Override
public void run() {
new AlertDialog.Builder(getActivity())
.setTitle(getResources().getString(R.string.alert_connection_title))
.setMessage(getResources().getString(R.string.alert_connection_description))
.setPositiveButton(getResources().getString(R.string.connect),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
new ScheduleFetcher(true, false, true).execute();
dialog.cancel();
}
})
.setNegativeButton(getResources().getString(R.string.cancel),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
}).show();
}
});
}
private void showPromptDialog() {
if (!getUserVisibleHint()) {
return;
}
ApplicationLoader.runOnUIThread(new Runnable() {
@Override
public void run() {
new AlertDialog.Builder(getActivity())
.setTitle(getResources().getString(R.string.confirmation))
.setMessage(getResources().getString(R.string.deletion_description))
.setPositiveButton(getResources().getString(R.string.hide),
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
ApplicationLoader.scheduleDatabase.hideLesson(onLongClickId);
new ScheduleFetcher(false, false, false).execute();
Snackbar snackbar = Snackbar.make(getActivity().findViewById(R.id.coordinator_layout), getResources().getString(R.string.lesson_hidden), Snackbar.LENGTH_SHORT);
snackbar.setAction(getResources().getString(R.string.undo), new View.OnClickListener() {
@Override
public void onClick(View view) {
ApplicationLoader.scheduleDatabase.restoreLessons(onLongClickId);
new ScheduleFetcher(false, false, false).execute();
Snackbar snackbar1 = Snackbar.make(getActivity().findViewById(R.id.coordinator_layout), getResources().getString(R.string.lesson_restored), Snackbar.LENGTH_SHORT);
snackbar1.show();
ApplicationLoader.restartNotificationThread();
}
});
snackbar.show();
ApplicationLoader.restartNotificationThread();
dialog.cancel();
}
})
.setNegativeButton(getResources().getString(R.string.cancel), new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
}).show();
}
});
}
@Override
public void onRefresh() {
new ScheduleFetcher(true, false, true).execute();
}
public class ScheduleFetcher extends AsyncTask<Void, Void, Void> {
private final boolean fetchData;
private final boolean showSpinner;
private final boolean showSwipeRefresh;
private Cursor scheduleDay;
public ScheduleFetcher(boolean fetchData, boolean showSpinner, boolean showSwipeRefresh) {
this.fetchData = fetchData;
this.showSpinner = showSpinner;
this.showSwipeRefresh = showSwipeRefresh;
}
@Override
protected void onPreExecute() {
super.onPreExecute();
if (adapter == null || adapter.getItemCount() == 0) {
if (showSpinner && spinner != null && emptyTextView != null) {
emptyTextView.setVisibility(View.GONE);
spinner.setVisibility(View.VISIBLE);
}
}
if (showSwipeRefresh && swipeRefreshLayout != null) {
swipeRefreshLayout.setRefreshing(true);
}
}
@Override
protected Void doInBackground(Void... param) {
if (fetchData) {
try {
ScheduleHandler.saveSchedule(ScheduleHandler.getScheduleFromServer(componentId, date, type), date, componentId);
} catch (Exception e) {
alertConnectionProblem();
}
}
scheduleDay = ApplicationLoader.scheduleDatabase.getLessons(simpleDateFormat.format(date), componentId);
return null;
}
@Override
protected void onPostExecute(Void param) {
super.onPostExecute(param);
if (adapter == null) {
adapter = new ScheduleAdapter(getActivity(), scheduleDay);
if (recyclerView != null) {
recyclerView.setAdapter(adapter);
}
} else {
adapter.changeCursor(scheduleDay);
}
if (adapter.getItemCount() == 0) {
if (emptyTextView != null) {
emptyTextView.setVisibility(View.VISIBLE);
}
} else {
if (emptyTextView != null) {
emptyTextView.setVisibility(View.GONE);
}
}
if (showSpinner && spinner != null) {
spinner.setVisibility(View.GONE);
}
if (showSwipeRefresh && swipeRefreshLayout != null
&& swipeRefreshLayout.isRefreshing()) {
swipeRefreshLayout.setRefreshing(false);
}
}
}
}