Android 查看寻呼机和片段生命周期
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24697951/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
View pager and fragment lifecycle
提问by shreyas
I have a ViewPager that loads three pages at a time. If I swipe from page 1 to page 2 then to 3, the first page(fragment) goes to onPause()
. Then, if I swipe to the second page, 1st page comes to onResume()
even though the page 1 is still not visible to the user. So, my question is: how to distinguish between the first and second page in code? For example, if I have to run a piece of code when the fragment is visible, how is that done?
我有一个一次加载三个页面的 ViewPager。如果我从第 1 页滑动到第 2 页,然后再滑动到第 3 页,则第一页(片段)将转到 onPause()
. 然后,如果我滑动到第二页,onResume()
即使用户仍然看不到第 1页,也会出现第 1 页。所以,我的问题是:如何区分代码中的第一页和第二页?例如,如果我必须在片段可见时运行一段代码,这是如何完成的?
回答by Shreyas Shetty
The FragmentPagerAdapter keeps additional fragments, besides the one shown, in resumed state. The solution is to implement a custom OnPageChangeListener and create a new method for when the fragment is shown.
FragmentPagerAdapter 将其他片段(除了显示的片段)保持在恢复状态。解决方案是实现自定义 OnPageChangeListener 并在显示片段时创建一个新方法。
1) Create LifecycleManager Interface The interface will have two methods and each ViewPager's Fragment will implement it. These methods Are as follows:
1) 创建 LifecycleManager 接口 该接口有两个方法,每个 ViewPager 的 Fragment 都会实现它。这些方法如下:
public interface FragmentLifecycle {
public void onPauseFragment();
public void onResumeFragment();
}
2) Let each Fragment implement the interface Add iplements statement for each class declaration:
2)让每个Fragment实现接口为每个类声明添加iplements语句:
public class FragmentBlue extends Fragment implements FragmentLifecycle
public class FragmentGreen extends Fragment implements FragmentLifecycle
public class FragmentPink extends Fragment implements FragmentLifecycle
3) Implement interface methods in each fragment In order to check that it really works as expected, I will just log the method call and show Toast:
3) 在每个片段中实现接口方法为了检查它是否真的按预期工作,我将记录方法调用并显示 Toast:
@Override
public void onPauseFragment() {
Log.i(TAG, "onPauseFragment()");
Toast.makeText(getActivity(), "onPauseFragment():" + TAG, Toast.LENGTH_SHORT).show();
}
@Override
public void onResumeFragment() {
Log.i(TAG, "onResumeFragment()");
Toast.makeText(getActivity(), "onResumeFragment():" + TAG, Toast.LENGTH_SHORT).show();
}
4) Call interface methods on ViewPager page change You can set OnPageChangeListener on ViewPager and get callback each time when ViewPager shows another page:
4)ViewPager页面变化时调用接口方法可以在ViewPager上设置OnPageChangeListener,每次ViewPager显示另一个页面时获取回调:
pager.setOnPageChangeListener(pageChangeListener);
5) Implement OnPageChangeListener to call your custom Lifecycle methods
5) 实现 OnPageChangeListener 来调用你自定义的 Lifecycle 方法
Listener knows the new position and can call the interface method on new Fragment with the help of PagerAdapter. I can here call onResumeFragment() for new fragment and onPauseFragment() on the current one.
Listener 知道新的位置,可以在 PagerAdapter 的帮助下调用新 Fragment 上的接口方法。我可以在这里为新片段调用 onResumeFragment() 并在当前片段上调用 onPauseFragment() 。
I need to store also the current fragment's position (initially the current position is equal to 0), since I don't know whether the user scrolled from left to right or from right to left. See what I mean in code:
我还需要存储当前片段的位置(最初当前位置等于 0),因为我不知道用户是从左向右滚动还是从右向左滚动。看看我在代码中的意思:
private OnPageChangeListener pageChangeListener = new OnPageChangeListener() {
int currentPosition = 0;
@Override
public void onPageSelected(int newPosition) {
FragmentLifecycle fragmentToShow = (FragmentLifecycle)pageAdapter.getItem(newPosition);
fragmentToShow.onResumeFragment();
FragmentLifecycle fragmentToHide = (FragmentLifecycle)pageAdapter.getItem(currentPosition);
fragmentToHide.onPauseFragment();
currentPosition = newPosition;
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) { }
public void onPageScrollStateChanged(int arg0) { }
};
I didn't write the code. Full tutorial here: http://looksok.wordpress.com/2013/11/02/viewpager-with-detailed-fragment-lifecycle-onresumefragment-including-source-code/
我没有写代码。完整教程在这里:http: //looksok.wordpress.com/2013/11/02/viewpager-with-detailed-fragment-lifecycle-onresumefragment-include-source-code/
回答by Hao Qi
if your Fragment extend android.support.v4.app.Fragment
如果您的 Fragment 扩展 android.support.v4.app.Fragment
you can use this, it works for me.
你可以用这个,它对我有用。
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (!isVisibleToUser) {
//do sth..
}
}
回答by Hyman
user method pager.setOffscreenPageLimit(numbr) to set how many fragments you want in stack to be hold.
用户方法 pager.setOffscreenPageLimit(numbr) 设置要在堆栈中保留多少个片段。
回答by Parin Parikh
Override setUserVisibleHint()
. This method will call once the fragment is visible to the user.
覆盖setUserVisibleHint()
。一旦片段对用户可见,此方法将调用。
回答by venu46
Override setUserVisibleHint()this will call when fragment is visible to the user
覆盖setUserVisibleHint()这将在片段对用户可见时调用
回答by biezhihua
Solve your problem:
解决您的问题:
public class FragmentVisibleHelper implements LifecycleObserver {
private static final String TAG = "VipVisibleHelper";
public interface IVisibleListener {
void onVisible();
void onInVisible();
}
boolean mIsVisibleToUser;
boolean mStarted = false;
volatile boolean mIsCalledVisible = false;
volatile boolean mIsCalledInvisible = false;
IVisibleListener mListener;
public void setListener(IVisibleListener mListener) {
this.mListener = mListener;
}
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
void onResume() {
Log.d(TAG, String.format("%-60s %s", this.toString(), "onResume() called:"));
if (mIsVisibleToUser) {
dispatchVisible();
}
}
private void dispatchVisible() {
Log.d(TAG, String.format("%-60s %s", this.toString(), "dispatchVisible() called mIsCalledVisible = [" + mIsCalledVisible + "] mIsCalledInvisible = [" + mIsCalledInvisible + "] "));
if (!mIsCalledVisible) {
mIsCalledVisible = true;
mIsCalledInvisible = false;
if (Profile.LOG) {
Log.d(TAG, String.format("%-60s %s", this.toString(), "dispatchVisible() called onVisible"));
}
if (mListener != null) {
mListener.onVisible();
}
}
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
void onPause() {
Log.d(TAG, String.format("%-60s %s", this.toString(), "onPause() called:"));
if (mIsVisibleToUser) {
dispatchInvisible();
}
}
private void dispatchInvisible() {
Log.d(TAG, String.format("%-60s %s", this.toString(), "dispatchInvisible() called mIsCalledVisible = [" + mIsCalledVisible + "] mIsCalledInvisible = [" + mIsCalledInvisible + "] "));
if (!mIsCalledInvisible) {
mIsCalledInvisible = true;
mIsCalledVisible = false;
if (Profile.LOG) {
Log.d(TAG, String.format("%-60s %s", this.toString(), "dispatchInvisible() called onInVisible"));
}
if (mListener != null) {
mListener.onInVisible();
}
}
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
void onStart() {
Log.d(TAG, String.format("%-60s %s", this.toString(), "onStart() called"));
mStarted = true;
if (mIsVisibleToUser) {
dispatchVisible();
}
}
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
void onStop() {
Log.d(TAG, String.format("%-60s %s", this.toString(), "onStop() called"));
if (mIsVisibleToUser) {
dispatchInvisible();
}
mStarted = false;
}
public void setUserVisibleHint(boolean isVisibleToUser) {
Log.d(TAG, String.format("%-60s %s", this.toString(), "setUserVisibleHint() called with: isVisibleToUser = [" + isVisibleToUser + "]:"));
mIsVisibleToUser = isVisibleToUser;
if (mStarted) { // fragment have created
if (mIsVisibleToUser) {
dispatchVisible();
} else {
dispatchInvisible();
}
}
}
public boolean isVisibleToUser() {
return mIsVisibleToUser;
}
}
回答by Ray Lee
The fragment's lifecycle methods are not called when swiping between fragments. You can use ViewPager.SimpleOnPageChangeListener
to solve this problem. The sample code is as bellow (in Kotlin).
在片段之间滑动时不会调用片段的生命周期方法。你可以用它ViewPager.SimpleOnPageChangeListener
来解决这个问题。示例代码如下(在 Kotlin 中)。
// other code
mViewPager.addOnPageChangeListener(object: ViewPager.SimpleOnPageChangeListener() {
override fun onPageSelected(position: Int) {
val oldPosition = mViewPager.currentItem
val oldFragment = mViewPager.adapter?.instantiateItem(mViewPager, oldPosition)
oldFragment.onPauseStuff() // Hint: do as here call onPause
val newFragment = mViewPager.adapter?.instantiateItem(mViewPager, position)
newFragment.onResumeStuff() // Hint: do as here call onResume
}
// other code