Android 在片段事务期间在 swipeRefreshLayout 上设置刷新(false)时片段两次
Android fragment twice when setRefreshing(false) on swipeRefreshLayout during fragment transaction
我的 activity 中有两个片段(我使用片段事务在它们之间导航):
- 科目列表
- 学科详情 - 成绩列表
主题片段布局:
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/refresher"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.v4.widget.SwipeRefreshLayout>
swipeRefreshLayout 的侦听器是 activity。它触发一个 AsyncTask 下载新数据,通知片段数据已更改并隐藏 swipeRefreshLayout。
onPostExecute 方法中有问题的部分:
...
try {
formatData();
} catch (JSONException e) {
e.printStackTrace();
}
View refresher = findViewById(R.id.refresher);
((SwipeRefreshLayout) refresher).setRefreshing(false);
marksFragment.notifyUpdate(activity);
subjectsFragment.notifyUpdate(activity);
它通常有效,但在这种情况下无效:
- 我拉动刷新数据
- 我导航到主题详细信息(使用
片段交易)
- 调用setRefreshing方法
片段交易
在这种情况下,主题片段就挂在那里,两个片段都在 activity。
SubjectFragment 代码:
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
((SwipeRefreshLayout) view.findViewById(R.id.refresher)).setOnRefreshListener((SwipeRefreshLayout.OnRefreshListener) activity);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.subjects_fragment, null);
}
如何在 refreshLayout 上 setRefreshing(false)
并避免两次获取主题片段?
更改您的代码,参考 stack overflow
上的答案
public class YourFragment extends Fragment {
SwipeRefreshLayout swipeLayout;
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
String[] values = new String[] { "Android List View",
"Adapter implementation",
"Simple List View In Android",
"Create List View Android",
"Android Example",
"List View Source Code",
"List View Array Adapter",
"Android Example List View",
"Android List View",
"Adapter implementation",
"Simple List View In Android",
"Create List View Android",
"Android Example",
"List View Source Code",
"List View Array Adapter",
"Android Example List View",
"Android List View",
"Adapter implementation",
"Simple List View In Android",
"Create List View Android",
"Android Example",
"List View Source Code",
"List View Array Adapter",
"Android Example List View"
};
final SwipeRefreshLayout swipeView = (SwipeRefreshLayout)view. findViewById(R.id.refresher);
swipeView.setEnabled(false);
ListView lView = (ListView) view.findViewById(R.id.your_list_view);
ArrayAdapter<String> adp = new ArrayAdapter<String>(view.getContext(),
android.R.layout.simple_list_item_1, android.R.id.text1, values);
lView.setAdapter(adp);
swipeView.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
swipeView.setRefreshing(true);
( new Handler()).postDelayed(new Runnable() {
@Override
public void run() {
swipeView.setRefreshing(false);
}
}, 3000);
}
});
lView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView absListView, int i) {
}
@Override
public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (firstVisibleItem == 0)
swipeView.setEnabled(true);
else
swipeView.setEnabled(false);
}
});
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.subjects_fragment, null);
}
}
我在 SO 上发现了一个类似的问题:
When switch fragment with SwipeRefreshLayout during refreshing, fragment freezes but actually still work
我使用 appcompat-v7:23.3.0。这个答案对我有用:
This issue seems to still be occurring in appcompat 22.1.1. Wrapping
the SwipeRefreshLayout inside a FrameLayout solved this for me.
所以我的主题片段布局如下所示:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/refresher"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.v4.widget.SwipeRefreshLayout>
</FrameLayout>
我的 swipelayout.setOnRefresh
电话两次都遇到同样的问题。
基本上原因不在 swipelayout.setOnRefreshLisetener
我正在加载一些数据,当我的 recyclerview 到达终点时 swipelayout.setOnRefreshListener 我也在做同样的事情。
所以我为消除错误所做的是我只是注释掉了 swipelayout.setOnRefreshListener
中的加载方法。
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
if (mLatestAdapter.getItemCount() > 0) {
mLatestAdapter.removeAllItems();
mPresenter.resetPagination();
// mPresenter.loadMoreItems(false);//commentwed this line
}
}
});
这就是我在我的 recyclerview 中所做的
mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
// Here get the child count, item count and visibleitems
// from layout manager
visibleItemCount = mLayoutManager.getChildCount();
totalItemCount = mLayoutManager.getItemCount();
pastVisiblesItems = mLayoutManager
.findFirstVisibleItemPosition();
// Now check if userScrolled is true and also check if
// the item is end then update recycler view and set
// userScrolled to false
if (userScrolled
&& (visibleItemCount + pastVisiblesItems) == totalItemCount) {
userScrolled = false;
if (!getBaseActivity().isNetworkConnected()) {
getBaseActivity().onError("Internet is not Connected");
return;
}
Log.wtf(TAG, "onScrolled: reach end" );
mPresenter.loadMoreItems(true);//here it is after removing all items from recyclerview it calls automatically
}
}
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
// If scroll state is touch scroll then set userScrolled
// true
if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
userScrolled = true;
}
}
});
我的 activity 中有两个片段(我使用片段事务在它们之间导航):
- 科目列表
- 学科详情 - 成绩列表
主题片段布局:
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/refresher"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.v4.widget.SwipeRefreshLayout>
swipeRefreshLayout 的侦听器是 activity。它触发一个 AsyncTask 下载新数据,通知片段数据已更改并隐藏 swipeRefreshLayout。
onPostExecute 方法中有问题的部分:
...
try {
formatData();
} catch (JSONException e) {
e.printStackTrace();
}
View refresher = findViewById(R.id.refresher);
((SwipeRefreshLayout) refresher).setRefreshing(false);
marksFragment.notifyUpdate(activity);
subjectsFragment.notifyUpdate(activity);
它通常有效,但在这种情况下无效:
- 我拉动刷新数据
- 我导航到主题详细信息(使用 片段交易)
- 调用setRefreshing方法 片段交易
在这种情况下,主题片段就挂在那里,两个片段都在 activity。
SubjectFragment 代码:
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
((SwipeRefreshLayout) view.findViewById(R.id.refresher)).setOnRefreshListener((SwipeRefreshLayout.OnRefreshListener) activity);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.subjects_fragment, null);
}
如何在 refreshLayout 上 setRefreshing(false)
并避免两次获取主题片段?
更改您的代码,参考 stack overflow
上的答案 public class YourFragment extends Fragment {
SwipeRefreshLayout swipeLayout;
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
String[] values = new String[] { "Android List View",
"Adapter implementation",
"Simple List View In Android",
"Create List View Android",
"Android Example",
"List View Source Code",
"List View Array Adapter",
"Android Example List View",
"Android List View",
"Adapter implementation",
"Simple List View In Android",
"Create List View Android",
"Android Example",
"List View Source Code",
"List View Array Adapter",
"Android Example List View",
"Android List View",
"Adapter implementation",
"Simple List View In Android",
"Create List View Android",
"Android Example",
"List View Source Code",
"List View Array Adapter",
"Android Example List View"
};
final SwipeRefreshLayout swipeView = (SwipeRefreshLayout)view. findViewById(R.id.refresher);
swipeView.setEnabled(false);
ListView lView = (ListView) view.findViewById(R.id.your_list_view);
ArrayAdapter<String> adp = new ArrayAdapter<String>(view.getContext(),
android.R.layout.simple_list_item_1, android.R.id.text1, values);
lView.setAdapter(adp);
swipeView.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
swipeView.setRefreshing(true);
( new Handler()).postDelayed(new Runnable() {
@Override
public void run() {
swipeView.setRefreshing(false);
}
}, 3000);
}
});
lView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView absListView, int i) {
}
@Override
public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (firstVisibleItem == 0)
swipeView.setEnabled(true);
else
swipeView.setEnabled(false);
}
});
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.subjects_fragment, null);
}
}
我在 SO 上发现了一个类似的问题:
When switch fragment with SwipeRefreshLayout during refreshing, fragment freezes but actually still work
我使用 appcompat-v7:23.3.0。这个答案对我有用:
This issue seems to still be occurring in appcompat 22.1.1. Wrapping the SwipeRefreshLayout inside a FrameLayout solved this for me.
所以我的主题片段布局如下所示:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/refresher"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="@android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</android.support.v4.widget.SwipeRefreshLayout>
</FrameLayout>
我的 swipelayout.setOnRefresh
电话两次都遇到同样的问题。
基本上原因不在 swipelayout.setOnRefreshLisetener
我正在加载一些数据,当我的 recyclerview 到达终点时 swipelayout.setOnRefreshListener 我也在做同样的事情。
所以我为消除错误所做的是我只是注释掉了 swipelayout.setOnRefreshListener
中的加载方法。
swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
if (mLatestAdapter.getItemCount() > 0) {
mLatestAdapter.removeAllItems();
mPresenter.resetPagination();
// mPresenter.loadMoreItems(false);//commentwed this line
}
}
});
这就是我在我的 recyclerview 中所做的
mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
// Here get the child count, item count and visibleitems
// from layout manager
visibleItemCount = mLayoutManager.getChildCount();
totalItemCount = mLayoutManager.getItemCount();
pastVisiblesItems = mLayoutManager
.findFirstVisibleItemPosition();
// Now check if userScrolled is true and also check if
// the item is end then update recycler view and set
// userScrolled to false
if (userScrolled
&& (visibleItemCount + pastVisiblesItems) == totalItemCount) {
userScrolled = false;
if (!getBaseActivity().isNetworkConnected()) {
getBaseActivity().onError("Internet is not Connected");
return;
}
Log.wtf(TAG, "onScrolled: reach end" );
mPresenter.loadMoreItems(true);//here it is after removing all items from recyclerview it calls automatically
}
}
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
// If scroll state is touch scroll then set userScrolled
// true
if (newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
userScrolled = true;
}
}
});