这是我的场景:
我的 Activity 中有 ViewPager,它承载 6 个 fragment 。我通过用手指滑动来禁用分页,所以每当我想滑动时,我都会使用相关按钮和:
viewPager.setCurrentItem(viewPager.getCurrentItem() + 1, true);
在滑动的每个 fragment 中(滑动完成后)我想向我的服务器发送一个GET 请求并获取一些数据并将其显示在该 fragment 中。为此:
第一种方法:我在我的 fragment 中使用了这段代码,它在 fragment 可见时立即运行:
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if(isVisibleToUser)
{
sendGetRequest();
}
}
但是,这里有一个问题:setUserVisibleHint 恰好在 fragment 可见时执行,因此滑动动画有一些滞后(不够平滑)。
所以我使用了第二种方法:
我在这样的托管 Activity 中向 ViewPager 添加了一个 OnPageChangeListener() :
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
int CurrentPossition = 0;
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { }
@Override
public void onPageSelected(int position) {
CurrentPossition = position;
}
@Override
public void onPageScrollStateChanged(int state) {
if(state == ViewPager.SCROLL_STATE_IDLE && CurrentPossition != 0){
Toast.makeText(getBaseContext(),"finished" , Toast.LENGTH_SHORT).show();
try{
new fragment_two().sendGetRequest();;
}catch(Exception ex){
ex.printStackTrace();
}
}
}
});
效果很好,滑动完成后 toast 立即显示,但与完全可见的 fragment 不同,当 sendGetRequest() 运行时我得到 NullPointerException。
这里是堆栈跟踪:
04-08 20:15:37.840 12848-12848/com.example.mohamad.travelagency W/System.err: java.lang.NullPointerException
04-08 20:15:37.850 12848-12848/com.example.mohamad.travelagency W/System.err: at android.content.ContextWrapper.getApplicationInfo(ContextWrapper.java:152)
04-08 20:15:37.850 12848-12848/com.example.mohamad.travelagency W/System.err: at android.view.ContextThemeWrapper.getTheme(ContextThemeWrapper.java:103)
04-08 20:15:37.850 12848-12848/com.example.mohamad.travelagency W/System.err: at android.app.AlertDialog.resolveDialogTheme(AlertDialog.java:143)
04-08 20:15:37.850 12848-12848/com.example.mohamad.travelagency W/System.err: at android.app.AlertDialog.<init>(AlertDialog.java:98)
04-08 20:15:37.850 12848-12848/com.example.mohamad.travelagency W/System.err: at android.app.ProgressDialog.<init>(ProgressDialog.java:77)
04-08 20:15:37.850 12848-12848/com.example.mohamad.travelagency W/System.err: at com.example.mohamad.travelagency.fragment_two.GetServetData_L1(fragment_two.java:458)
04-08 20:15:37.850 12848-12848/com.example.mohamad.travelagency W/System.err: at com.example.mohamad.travelagency.MainActivity$1.onPageScrollStateChanged(MainActivity.java:124)
04-08 20:15:37.860 12848-12848/com.example.mohamad.travelagency W/System.err: at android.support.v4.view.ViewPager.dispatchOnScrollStateChanged(ViewPager.java:1811)
04-08 20:15:37.860 12848-12848/com.example.mohamad.travelagency W/System.err: at android.support.v4.view.ViewPager.setScrollState(ViewPager.java:404)
04-08 20:15:37.860 12848-12848/com.example.mohamad.travelagency W/System.err: at android.support.v4.view.ViewPager.access$000(ViewPager.java:91)
04-08 20:15:37.860 12848-12848/com.example.mohamad.travelagency W/System.err: at android.support.v4.view.ViewPager$3.run(ViewPager.java:250)
04-08 20:15:37.860 12848-12848/com.example.mohamad.travelagency W/System.err: at android.view.Choreographer$CallbackRecord.run(Choreographer.java:761)
04-08 20:15:37.860 12848-12848/com.example.mohamad.travelagency W/System.err: at android.view.Choreographer.doCallbacks(Choreographer.java:574)
04-08 20:15:37.860 12848-12848/com.example.mohamad.travelagency W/System.err: at android.view.Choreographer.doFrame(Choreographer.java:543)
04-08 20:15:37.860 12848-12848/com.example.mohamad.travelagency W/System.err: at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:747)
04-08 20:15:37.860 12848-12848/com.example.mohamad.travelagency W/System.err: at android.os.Handler.handleCallback(Handler.java:733)
04-08 20:15:37.860 12848-12848/com.example.mohamad.travelagency W/System.err: at android.os.Handler.dispatchMessage(Handler.java:95)
04-08 20:15:37.860 12848-12848/com.example.mohamad.travelagency W/System.err: at android.os.Looper.loop(Looper.java:136)
04-08 20:15:37.870 12848-12848/com.example.mohamad.travelagency W/System.err: at android.app.ActivityThread.main(ActivityThread.java:5271)
04-08 20:15:37.870 12848-12848/com.example.mohamad.travelagency W/System.err: at java.lang.reflect.Method.invokeNative(Native Method)
04-08 20:15:37.870 12848-12848/com.example.mohamad.travelagency W/System.err: at java.lang.reflect.Method.invoke(Method.java:515)
04-08 20:15:37.870 12848-12848/com.example.mohamad.travelagency W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:851)
04-08 20:15:37.870 12848-12848/com.example.mohamad.travelagency W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:667)
04-08 20:15:37.870 12848-12848/com.example.mohamad.travelagency W/System.err: at dalvik.system.NativeStart.main(Native Method)
任何想法都会很棒。 最好的问候
回答:
Daniel Nugent 的代码运行良好,除了在发送 GET 请求期间显示 ProgressDialog 之外,我使用了:
final ProgressDialog dialog = new ProgressDialog(new MainActivity());
这段代码也返回了 NullPointerException,我删除了它,现在运行良好。
最佳答案
使用 ViewPager.OnPageChangeListener
是正确的方法,但您需要稍微重构您的适配器,以便保留对 FragmentPagerAdapter 中包含的每个 fragment 的引用。
您可以使用适配器中的 instantiateItem()
方法覆盖,这是一个简化的示例:
class PagerAdapter extends FragmentPagerAdapter {
String tabTitles[] = new String[] { "One", "Two", "Three", "Four"};
Context context;
//This will contain your Fragment references:
public Fragment[] fragments = new Fragment[tabTitles.length];
public PagerAdapter(FragmentManager fm, Context context) {
super(fm);
this.context = context;
}
@Override
public int getCount() {
return tabTitles.length;
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new FragmentOne();
case 1:
return new FragmentTwo();
case 2:
return new FragmentThree();
case 3:
return new FragmentFour();
}
return null;
}
//This populates your Fragment reference array:
@Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment createdFragment = (Fragment) super.instantiateItem(container, position);
fragments[position] = createdFragment;
return createdFragment;
}
@Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
return tabTitles[position];
}
}
然后,不要创建新的 fragment ,而是使用适配器中包含的 fragment :
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { }
@Override
public void onPageSelected(int position) {
// do this instead, assuming your adapter reference
// is named mAdapter:
Fragment frag = mAdapter.fragments[position];
if (frag != null && frag instanceof FragmentTwo) {
((FragmentTwo)frag).sendGetRequest();
}
}
@Override
public void onPageScrollStateChanged(int state) { }
});
请注意,如果您在适配器中使用不同的 Fragment 类,您可以实现定义 sendGetRequest()
的接口(interface),并在每个 Fragment 类中实现 sendGetRequest() 方法。
如果您不采用接口(interface)方法,则需要将 Fragment 转换为您自己的 Fragment 类型,如上例所示,即:
if (frag instanceof FragmentTwo) {
((FragmentTwo)frag).sendGetRequest();
}
更新
对于使用 ViewPager2 和 Kotlin,它的外观如下:
viewPager.registerOnPageChangeCallback(
object: ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
val frag: Fragment = mAdapter.fragments[position]
if (frag != null && frag is FragmentTwo) {
(frag as FragmentTwo).sendGetRequest()
}
}
}
)
关于java - 从 Activity 访问 ViewPager Fragment 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36503779/