티스토리 뷰

반응형

Stack Overflow에 자주 검색, 등록되는 문제들과 제가 개발 중 찾아 본 문제들 중에서 나중에도 찾아 볼 것 같은 문제들을 정리하고 있습니다.

Stack Overflow에서 가장 먼저 확인하게 되는 가장 높은 점수를 받은 Solution과 현 시점에 도움이 될 수 있는 가장 최근에 업데이트(최소 점수 확보)된 Solution을 각각 정리하였습니다.

 

아래 word cloud를 통해 이번 포스팅의 주요 키워드를 미리 확인하세요.

Getting the current Fragment instance in the viewpager

뷰페이저(viewpager) 내 현재 프래그먼트 인스턴스(instance) 가져오기

 문제 내용 

Below is my code which has 3 Fragment classes each embedded with each of the 3 tabs on ViewPager. I have a menu option. As shown in the onOptionsItemSelected(), by selecting an option, I need to update the fragment that is currently visible. To update that I have to call a method which is in the fragment class. Can someone please suggest how to call that method?

아래는 뷰페이저의 3개 탭(tab) 중 하나에 포함된 3개의 프래그먼트 클래스가 있는 코드입니다. 메뉴 옵션이 있습니다. onOptionsItemSelected()에서 보여지듯이 옵션을 선택하면 현재 보이는 프래그먼트를 업데이트해야 합니다. 업데이트를 위해 프래그먼트 클래스에 있는 메소드를 호출해야 합니다. 해당 메소드를 호출하는 방법을 알려주세요.
public class MainActivity  extends ActionBarActivity {

     ViewPager ViewPager;
     TabsAdapter TabsAdapter;

     @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            ViewPager = new ViewPager(this);
            ViewPager.setId(R.id.pager);
            setContentView(ViewPager);

            final ActionBar bar = getSupportActionBar();

            bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

            //Attaching the Tabs to the fragment classes and setting the tab title.
            TabsAdapter = new TabsAdapter(this, ViewPager);
            TabsAdapter.addTab(bar.newTab().setText("FragmentClass1"),
                    FragmentClass1.class, null);
            TabsAdapter.addTab(bar.newTab().setText("FragmentClass2"),
              FragmentClass2.class, null);
            TabsAdapter.addTab(bar.newTab().setText("FragmentClass3"),
              FragmentClass3.class, null);


            if (savedInstanceState != null) {
                bar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
            }

        }

        @Override
        public boolean onOptionsItemSelected(MenuItem item) {

            switch (item.getItemId()) {

            case R.id.addText:

           **// Here I need to call the method which exists in the currently visible Fragment class**

                    return true;

            }

            return super.onOptionsItemSelected(item);
        }


     @Override
     protected void onSaveInstanceState(Bundle outState) {
      super.onSaveInstanceState(outState);
            outState.putInt("tab", getSupportActionBar().getSelectedNavigationIndex());

     }

     public static class TabsAdapter extends FragmentPagerAdapter
      implements ActionBar.TabListener, ViewPager.OnPageChangeListener {

      private final Context mContext;
            private final ActionBar mActionBar;
            private final ViewPager mViewPager;
            private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();

            static final class TabInfo {
                private final Class<?> clss;
                private final Bundle args;

                TabInfo(Class<?> _class, Bundle _args) {
                    clss = _class;
                    args = _args;
                }
            }

      public TabsAdapter(ActionBarActivity activity, ViewPager pager) {
       super(activity.getSupportFragmentManager());
                mContext = activity;
                mActionBar = activity.getSupportActionBar();
                mViewPager = pager;
                mViewPager.setAdapter(this);
                mViewPager.setOnPageChangeListener(this);
            }

      public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
                TabInfo info = new TabInfo(clss, args);
                tab.setTag(info);
                tab.setTabListener(this);
                mTabs.add(info);
                mActionBar.addTab(tab);
                notifyDataSetChanged();

            }

      @Override
      public void onPageScrollStateChanged(int state) {
       // TODO Auto-generated method stub

      }

      @Override
      public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
       // TODO Auto-generated method stub

      }

      @Override
      public void onPageSelected(int position) {
       // TODO Auto-generated method stub
       mActionBar.setSelectedNavigationItem(position);
      }

      @Override
      public void onTabReselected(Tab tab, FragmentTransaction ft) {
       // TODO Auto-generated method stub

      }

      @Override
      public void onTabSelected(Tab tab, FragmentTransaction ft) {
       Object tag = tab.getTag();
                for (int i=0; i<mTabs.size(); i++) {
                    if (mTabs.get(i) == tag) {
                        mViewPager.setCurrentItem(i);

                    }
                }

                tabPosition = tab.getPosition();
      }

      @Override
      public void onTabUnselected(Tab tab, FragmentTransaction ft) {
       // TODO Auto-generated method stub

      }

      @Override
      public Fragment getItem(int position) {
       TabInfo info = mTabs.get(position);
                return Fragment.instantiate(mContext, info.clss.getName(), info.args);
      }

      @Override
      public int getCount() {
       return mTabs.size();
      }

     }

    }

 

Suppose below is the fragment class with the method updateList() I want to call:

아래는 호출하려는 updateList() 메소드가 있는 프래그먼트 클래스입니다.
 public class FragmentClass1{

    ArrayList<String> originalData;


    @Override
         public View onCreateView(LayoutInflater inflater, ViewGroup container,
           Bundle savedInstanceState) {

          View fragmentView = inflater.inflate(R.layout.frag1, container, false);

          originalData = getOriginalDataFromDB();

          return fragmentView;

         }


    public void updateList(String text)
    {
       originalData.add(text);
       //Here I could do other UI part that need to added
    }
}

 

 

 높은 점수를 받은 Solution 

by selecting an option, I need to update the fragment that is currently visible.

단순한 방법은 FragmentPagerAdapter 구현과 관련된 트릭을 사용하는 것입니다.

 

A simple way of doing this is using a trick related to the FragmentPagerAdapter implementation:

이를 위한 간단한 방법은 FragmentPagerAdapter 구현과 관련된 트릭을 사용하는 것입니다.

 

case R.id.addText:
     Fragment page = getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":" + ViewPager.getCurrentItem());
     // based on the current position you can then cast the page to the correct 
     // class and call the method:
     if (ViewPager.getCurrentItem() == 0 && page != null) {
          ((FragmentClass1)page).updateList("new item");     
     } 
return true;

Please rethink your variable naming convention, using as the variable name the name of the class is very confusing(so no ViewPager ViewPager, use ViewPager mPager for example).

변수명 지정 규칙에 대해 다시 생각해보세요. 변수 이름으로 클래스 이름을 사용하면 매우 혼란스러울 수 있습니다. (예: ViewPager ViewPager 사용하지 말고, ViewPager mPager와 같이 사용하세요.)

 

 

 

 가장 최근 달린 Solution 

In my previous implementation I stored a list of child Fragments to be able to access them later, but this turned out to be a wrong implementation causing huge memory leaks.

이전 구현에서는 나중에 액세스할 수 있도록 하위 프래그먼트 목록을 저장했지만, 이것은 매우 잘못된 구현으로 메모리 누수를 유발했습니다.

 

I end up using instantiateItem(...) method to get current Fragment:

현재 프래그먼트를 가져오기 위해 instantiateItem(...) 메소드를 사용하게 되었습니다:
val currentFragment = adapter?.instantiateItem(viewPager, viewPager.currentItem)

 

Or to get any other Fragment on position:

또는 다른 위치(position)에 있는 프래그먼트를 가져오려면:
val position = 0
val myFirstFragment: MyFragment? = (adapter?.instantiateItem(viewPager, position) as? MyFragment)

 

From documentation:

문서에서:

 

Create the page for the given position. The adapter is responsible for adding the view to the container given here, although it only must ensure this is done by the time it returns from finishUpdate(ViewGroup).

주어진 위치에 대한 페이지를 만듭니다. 어댑터는 여기에 뷰를 추가하는 것이 책임이지만, finishUpdate(ViewGroup)에서 반환하기 전에 이 작업이 완료된 것만 보장하면 됩니다.

 

 

 

출처 : https://stackoverflow.com/questions/18609261/getting-the-current-fragment-instance-in-the-viewpager

반응형
댓글
공지사항
최근에 올라온 글