除非重新启动,否则滑动选项卡中的 ListView 不会更新
ListView in swipe tab not updated unless restart
在我的应用程序中,它有两个选项卡,一个是提醒,另一个是已完成的任务。
当切换按钮被点击时,我希望它将列表移动到已完成的任务。
想法是:
- 从 sqlite 获取选中的行 ID
- 根据 Reminder Table 中的 id 检索数据并插入 Completed Table。
- 在已完成选项卡中调用检索方法。
但是当我点击切换按钮并滑动到完成时,它仍然是空的。退出应用程序并滑动到选项卡后,仅显示数据。
如何在滑动时让数据立即显示在“已完成”选项卡中,而不是退出应用程序并重新打开?谢谢
AllAdapter(提醒)
holder.toggle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (((ToggleButton)v).isChecked()) {
int getPosition = (Integer) v.getTag(); // Here we get the position that we have set for the checkbox using setTag.
search.get(getPosition).setSelected(((ToggleButton) v).isChecked());
int id= search.get(getPosition).getID();
mdb = new MyDatabaseHelper(v.getContext());
database = mdb.getReadableDatabase();
Cursor cursor = database.rawQuery("SELECT * FROM " + MyDatabaseHelper.TABLE__TASK + " WHERE ID = ? ", new String[]{id+""}, null);
if (cursor != null && cursor.getCount() > 0) {
while (cursor.moveToNext()) {
String allTask = cursor.getString(cursor.getColumnIndex("Title"));
String name = cursor.getString(cursor.getColumnIndex("Name"));
String allTime = cursor.getString(cursor.getColumnIndex("Time"));
String allDate = cursor.getString(cursor.getColumnIndex("Date"));
insertDataToCompleteTab(id,name,allTask,allTime,allDate); // insert to another table
}
}
} else {
int getPosition = (Integer) v.getTag(); // Here we get the position that we have set for the checkbox using setTag.
search.get(getPosition).setSelected(((ToggleButton) v).isChecked());
}
}
});
已完成任务
retrieveList(name);
public void retrieveList(String name) {
Toast.makeText(getActivity(),name,Toast.LENGTH_SHORT).show();
search.clear();
database = mdb.getReadableDatabase();
Cursor cursor = database.rawQuery("SELECT * FROM " + MyDatabaseHelper.TABLE_TASKCOMPLETED + " WHERE Name = ? ", new String[]{name}, null);
if (cursor != null && cursor.getCount() > 0) {
while (cursor.moveToNext()) {
int iD = cursor.getInt(cursor.getColumnIndex("ID"));
String allTask = cursor.getString(cursor.getColumnIndex("Title"));
String allTime = cursor.getString(cursor.getColumnIndex("Time"));
String allDate = cursor.getString(cursor.getColumnIndex("Date"));
if (adapter != null) {
adapter.add(iD, allTask, allTime, allDate);
listview.setAdapter(adapter);
adapter.getCount();
// check();
}
}
} else {
}
}
所有适配器
已完成选项卡
完全适配器
默认情况下,ViewPager
内最近的标签页会同时加载。之所以发生这种情况,是因为在您使用切换按钮进行任何切换之前,数据已加载到第二个选项卡。要解决问题,您必须更新已完成选项卡中的数据,以防任何数据更改。
这可以通过多种方式实现:
第一个片段应在每次更改时发送一个事件,第二个片段应订阅该事件并手动更新数据
使用加载程序和内容提供程序(或仅自定义 uri)。 Loader 订阅任何 uri 更改,并且您的 repository/dao 数据库助手通知此类 uri 任何更改(当 insert/update/delete 方法已被调用时)
context.getContentResolver().notifyChange(uri);
您的对象的加载程序。
abstract class CachedLoader<T> extends AsyncTaskLoader<T> {
@Nullable
private T cachedData;
CachedLoader(Context context) {
super(context);
}
void registerUri(Uri... observerUris) {
for (Uri uri:observerUris) {
getContext().getContentResolver().registerContentObserver(uri, true, createContentObserver());
}
}
ContentObserver createContentObserver() {
return new ForceLoadContentObserver();
}
@Override
public void deliverResult(T data) {
super.deliverResult(data);
this.cachedData = data;
}
@Override
public void onContentChanged() {
super.onContentChanged();
cachedData = null;
}
@Override
protected void onStartLoading() {
if (!takeContentChanged() && cachedData != null) {
deliverResult(cachedData);
return;
}
forceLoad();
}
@Override
protected void onReset() {
super.onReset();
cachedData = null;
}
}
调用注册 uri 以订阅该 uri 更改。
或者用一个CursorLoader
,因为你直接用游标操作。正如我在更新的问题中看到的
我更喜欢第二种方法,但第一种更简单
来自Android documentation for fragment lifecycle
系统显示片段onResume()
或onPause()
只有在活动onResume()
或onPause()
被调用时才会被调用。它们与 Activity.
紧密耦合
因此,您无法在选项卡更改时刷新视图。
为了解决这个问题,我在 setUserVisibleHint 中找到了一个解决方案
在我的申请中,因为我们有相同的要求。 Viewpager
调用片段的以下函数并在片段代码中实现它
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
// Make sure that we are currently visible
if (this.isVisible()) {
// If we are becoming invisible, then...
if (!isVisibleToUser) {
Log.d("TAG", "Stop animation and audio you are not visible");
}
}
}
这就是文档所说的
Set a hint to the system about whether this fragment's UI is currently
visible to the user. This hint defaults to true and is persistent
across fragment instance state save and restore.An app may set this to
false to indicate that the fragment's UI is scrolled out of visibility
or is otherwise not directly visible to the user. This may be used by
the system to prioritize operations such as fragment lifecycle updates
or loader ordering behavior.This method may be called outside of the
fragment lifecycle. and thus has no ordering guarantees with regard to
fragment lifecycle method calls.
ViewPager 在它的子片段上调用它。
有关详细信息,ViewPager 还调用 setMenuVisibility
如果您在显示或删除菜单时遇到问题,可以使用它。请参阅 setMenuVisiblity documnet 的 link,其中指出
Set a hint for whether this fragment's menu should be visible. This is
useful if you know that a fragment has been placed in your view
hierarchy so that the user can not currently seen it, so any menu
items it has should also not be shown.
所以我只是将下面的代码放在我的已完成任务片段中
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(isVisibleToUser){
retrieveList(name);//call the method to be refreshed
}
else{
//no
}
}
从@Swapnil 得到提示并从
得到答案
像这样在片段 onResumse 上放置下面的代码
@Override
public void onResume() {
super.onResume();
retrieveList(name);
}
您可以按照
创建一个界面
public interface ReminderCompletedListener
{
void reminderCompleted();
}
在 CompletedTask
中创建该侦听器的实例并将其注册到您的 Activity。
((MyActivity) getActivity()).setReminderCompletedListener(new ReminderCompletedListener()
{
@Override
public void reminderCompleted()
{
retrieveList(name);
}
});
在您的 Activity 中创建一个可以从切换点击侦听器调用的方法
((MyActivity) getActivity()).reminderCompleted();
当您完成“提醒”选项卡中的任务时,将触发“已完成”列表重新加载。从这个解决方案中得到的一个主要考虑是它直接将你的片段与你的 Activity.
结合起来
还有其他解决方案,您可以使用总线 (eventbus/otto) 之类的东西,也可以使用 rxjava,如果您愿意,可以探索这些,但我给出的香草解决方案应该可以工作很好。
在我的应用程序中,它有两个选项卡,一个是提醒,另一个是已完成的任务。
当切换按钮被点击时,我希望它将列表移动到已完成的任务。
想法是:
- 从 sqlite 获取选中的行 ID
- 根据 Reminder Table 中的 id 检索数据并插入 Completed Table。
- 在已完成选项卡中调用检索方法。
但是当我点击切换按钮并滑动到完成时,它仍然是空的。退出应用程序并滑动到选项卡后,仅显示数据。
如何在滑动时让数据立即显示在“已完成”选项卡中,而不是退出应用程序并重新打开?谢谢
AllAdapter(提醒)
holder.toggle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (((ToggleButton)v).isChecked()) {
int getPosition = (Integer) v.getTag(); // Here we get the position that we have set for the checkbox using setTag.
search.get(getPosition).setSelected(((ToggleButton) v).isChecked());
int id= search.get(getPosition).getID();
mdb = new MyDatabaseHelper(v.getContext());
database = mdb.getReadableDatabase();
Cursor cursor = database.rawQuery("SELECT * FROM " + MyDatabaseHelper.TABLE__TASK + " WHERE ID = ? ", new String[]{id+""}, null);
if (cursor != null && cursor.getCount() > 0) {
while (cursor.moveToNext()) {
String allTask = cursor.getString(cursor.getColumnIndex("Title"));
String name = cursor.getString(cursor.getColumnIndex("Name"));
String allTime = cursor.getString(cursor.getColumnIndex("Time"));
String allDate = cursor.getString(cursor.getColumnIndex("Date"));
insertDataToCompleteTab(id,name,allTask,allTime,allDate); // insert to another table
}
}
} else {
int getPosition = (Integer) v.getTag(); // Here we get the position that we have set for the checkbox using setTag.
search.get(getPosition).setSelected(((ToggleButton) v).isChecked());
}
}
});
已完成任务
retrieveList(name);
public void retrieveList(String name) {
Toast.makeText(getActivity(),name,Toast.LENGTH_SHORT).show();
search.clear();
database = mdb.getReadableDatabase();
Cursor cursor = database.rawQuery("SELECT * FROM " + MyDatabaseHelper.TABLE_TASKCOMPLETED + " WHERE Name = ? ", new String[]{name}, null);
if (cursor != null && cursor.getCount() > 0) {
while (cursor.moveToNext()) {
int iD = cursor.getInt(cursor.getColumnIndex("ID"));
String allTask = cursor.getString(cursor.getColumnIndex("Title"));
String allTime = cursor.getString(cursor.getColumnIndex("Time"));
String allDate = cursor.getString(cursor.getColumnIndex("Date"));
if (adapter != null) {
adapter.add(iD, allTask, allTime, allDate);
listview.setAdapter(adapter);
adapter.getCount();
// check();
}
}
} else {
}
}
所有适配器
已完成选项卡
完全适配器
默认情况下,ViewPager
内最近的标签页会同时加载。之所以发生这种情况,是因为在您使用切换按钮进行任何切换之前,数据已加载到第二个选项卡。要解决问题,您必须更新已完成选项卡中的数据,以防任何数据更改。
这可以通过多种方式实现:
第一个片段应在每次更改时发送一个事件,第二个片段应订阅该事件并手动更新数据
使用加载程序和内容提供程序(或仅自定义 uri)。 Loader 订阅任何 uri 更改,并且您的 repository/dao 数据库助手通知此类 uri 任何更改(当 insert/update/delete 方法已被调用时)
context.getContentResolver().notifyChange(uri);
您的对象的加载程序。
abstract class CachedLoader<T> extends AsyncTaskLoader<T> {
@Nullable
private T cachedData;
CachedLoader(Context context) {
super(context);
}
void registerUri(Uri... observerUris) {
for (Uri uri:observerUris) {
getContext().getContentResolver().registerContentObserver(uri, true, createContentObserver());
}
}
ContentObserver createContentObserver() {
return new ForceLoadContentObserver();
}
@Override
public void deliverResult(T data) {
super.deliverResult(data);
this.cachedData = data;
}
@Override
public void onContentChanged() {
super.onContentChanged();
cachedData = null;
}
@Override
protected void onStartLoading() {
if (!takeContentChanged() && cachedData != null) {
deliverResult(cachedData);
return;
}
forceLoad();
}
@Override
protected void onReset() {
super.onReset();
cachedData = null;
}
}
调用注册 uri 以订阅该 uri 更改。
或者用一个CursorLoader
,因为你直接用游标操作。正如我在更新的问题中看到的
我更喜欢第二种方法,但第一种更简单
来自Android documentation for fragment lifecycle
系统显示片段onResume()
或onPause()
只有在活动onResume()
或onPause()
被调用时才会被调用。它们与 Activity.
因此,您无法在选项卡更改时刷新视图。
为了解决这个问题,我在 setUserVisibleHint 中找到了一个解决方案
在我的申请中,因为我们有相同的要求。 Viewpager
调用片段的以下函数并在片段代码中实现它
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
// Make sure that we are currently visible
if (this.isVisible()) {
// If we are becoming invisible, then...
if (!isVisibleToUser) {
Log.d("TAG", "Stop animation and audio you are not visible");
}
}
}
这就是文档所说的
Set a hint to the system about whether this fragment's UI is currently visible to the user. This hint defaults to true and is persistent across fragment instance state save and restore.An app may set this to false to indicate that the fragment's UI is scrolled out of visibility or is otherwise not directly visible to the user. This may be used by the system to prioritize operations such as fragment lifecycle updates or loader ordering behavior.This method may be called outside of the fragment lifecycle. and thus has no ordering guarantees with regard to fragment lifecycle method calls.
ViewPager 在它的子片段上调用它。
有关详细信息,ViewPager 还调用 setMenuVisibility
如果您在显示或删除菜单时遇到问题,可以使用它。请参阅 setMenuVisiblity documnet 的 link,其中指出
Set a hint for whether this fragment's menu should be visible. This is useful if you know that a fragment has been placed in your view hierarchy so that the user can not currently seen it, so any menu items it has should also not be shown.
所以我只是将下面的代码放在我的已完成任务片段中
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(isVisibleToUser){
retrieveList(name);//call the method to be refreshed
}
else{
//no
}
}
从@Swapnil 得到提示并从
得到答案像这样在片段 onResumse 上放置下面的代码
@Override
public void onResume() {
super.onResume();
retrieveList(name);
}
您可以按照
创建一个界面public interface ReminderCompletedListener
{
void reminderCompleted();
}
在 CompletedTask
中创建该侦听器的实例并将其注册到您的 Activity。
((MyActivity) getActivity()).setReminderCompletedListener(new ReminderCompletedListener()
{
@Override
public void reminderCompleted()
{
retrieveList(name);
}
});
在您的 Activity 中创建一个可以从切换点击侦听器调用的方法
((MyActivity) getActivity()).reminderCompleted();
当您完成“提醒”选项卡中的任务时,将触发“已完成”列表重新加载。从这个解决方案中得到的一个主要考虑是它直接将你的片段与你的 Activity.
结合起来还有其他解决方案,您可以使用总线 (eventbus/otto) 之类的东西,也可以使用 rxjava,如果您愿意,可以探索这些,但我给出的香草解决方案应该可以工作很好。