从活动访问ViewPager Fragment方法 [英] Access ViewPager Fragment method from Activity

查看:62
本文介绍了从活动访问ViewPager Fragment方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的情况:

我的活动"中有 ViewPager ,其中包含6个片段.我通过用手指轻扫来禁用分页,所以每当我想滑动时,我都会使用相关的按钮和:

viewPager.setCurrentItem(viewPager.getCurrentItem() + 1, true);

在每个被刷过的片段中(刷完后),我想向服务器发送一个 GET 请求,并获取一些数据并将其显示在该片段中.为此:

第一种方法:我在片段中使用了此代码,该代码在片段可见后立即运行:

@Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if(isVisibleToUser)
        {
          sendGetRequest();
        }
}

但是,这是一个问题: setUserVisibleHint 仅在可见片段时执行,并且由于滑动动画带有一些滞后(不够流畅).

所以我使用了第二种方法: 我在托管活动中向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();
                    }
                }
            }
        });

它运行良好,并且吐司一扫就显示,但与完全可见的片段不同,当 sendGetRequest()运行时,我得到NullPointerException.

这是StackTrace:

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是正确的方法,但是您需要对适配器进行一些重构,以保留对包含在其中的每个Fragment的引用. FragmentPagerAdapter.

您可以使用适配器中的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,而是使用适配器中包含的片段:

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()的接口,并且在每个Fragment类中都实现sendGetRequest()方法.

如果不使用接口方法,则需要将Fragment转换为自己的Fragment类型,如上面的示例所示,即:

if (frag instanceof FragmentTwo) {
    ((FragmentTwo)frag).sendGetRequest();
}

This is my scenario:

I have ViewPager in my Activity which hosts 6 Fragment. I disabled paging by swiping with finger, so whenever I want to swipe I use related button and :

viewPager.setCurrentItem(viewPager.getCurrentItem() + 1, true);

In each fragment that is swiped (after swipe is finished) I want to send a GET request to my server and fetch some data and show it in that fragment. for doing that:

First Approach : I used this code in my fragments which runs as soon as fragment become visible:

@Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if(isVisibleToUser)
        {
          sendGetRequest();
        }
}

But , here was a problem : that setUserVisibleHint executes exactly whene the fragment visible , and because of that the animation of swiping came with some lag(it wasn't smooth enough).

So I used Second Approach : I added an OnPageChangeListener() to ViewPager in hosted activity like this :

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();
                    }
                }
            }
        });

It works great, and toast shows as soon as swipe finished, but unlike fragment which visible completely , when sendGetRequest() runs i get NullPointerException.

here is StackTrace :

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)

any idea would be great. best regards

Answer : Daniel Nugent's code worked well , beside for showing ProgressDialog during sending GET request i used :

final ProgressDialog dialog = new ProgressDialog(new MainActivity());

this code returned NullPointerException too , i removed it and now working well.

解决方案

Using the ViewPager.OnPageChangeListener is the correct way to go, but you will need to refactor your adapter a bit in order to keep a reference to each Fragment contained in the FragmentPagerAdapter.

You do that using the instantiateItem() method override in the adapter, here is a simplified example:

 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];
        }         
 }

Then, instead of creating a new Fragment, use the one contained in the adapter:

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) {  }
});

Note that if you're using different Fragment classes in your adapter, you can implement an interface that defines sendGetRequest(), and in each of your Fragment classes implement the sendGetRequest() method.

If you don't go with the interface approach, you will need to cast the Fragment to your own Fragment type as shown in the example above, i.e.:

if (frag instanceof FragmentTwo) {
    ((FragmentTwo)frag).sendGetRequest();
}

这篇关于从活动访问ViewPager Fragment方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆