programing tip

조각 내에서 조각 뷰 페이지 표시

itbloger 2021. 1. 10. 16:57
반응형

조각 내에서 조각 뷰 페이지 표시


ViewPager가 포함 된 조각이 있습니다. ViewPager는 조각 집합을 포함하는 어댑터와 연결됩니다.

부모 조각을로드 할 때라 IllegalStateException는 메시지가 나타납니다 java.lang.IllegalStateException: Recursive entry to executePendingTransactions.

일부 연구 결과 시스템이 다른 조각 내에서 조각을 표시 할 수 없다는 결론에 도달했습니다. 그러나 ViewPager ( 다른 조각과 함께 사용하는 ViewPager의 버그)를 사용하여 정확히이를 수행 할 수 있다는 표시가있는 것 같습니다. ).

사실, mPager.setAdapter(mAdapter)눌 렸을 때 ViewPager 를 호출 하는 부모 조각에 버튼을 추가 하면 ViewPager가 성공적으로로드됩니다. 이것은 이상적이지 않습니다.

그런 다음 문제는 조각 수명주기와 관련되어야합니다. 따라서 내 질문은 이것이다 : 다른 사람이이 문제를 해결하는 방법을 찾았습니까? 그렇다면 어떻게합니까?

조각 트랜잭션이 끝날 때까지 ViewPager에서 어댑터 설정을 지연하는 방법이 있습니까?

다음은 부모 조각 코드입니다.

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

    mView = inflater.inflate(R.layout.team_card_master, container, false);
    mViewPager = (ViewPager)mView.findViewById(R.id.team_card_master_view_pager);

    final Button button = (Button)mView.findViewById(R.id.load_viewpager_button);
    button.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            mViewPager.setAdapter(mAdapter);
            button.setVisibility(View.GONE);
        }
    });

    mAdapter = new ViewPagerAdapter(getFragmentManager());
 //     mViewPager.setAdapter(mAdapter);

    return mView;
}

그리고 어댑터 :

public class ViewPagerAdapter extends FragmentPagerAdapter {
    public ViewPagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public int getCount() {
        if (mCursor == null) return 0;
        else return mCursor.getCount();
    }

    @Override
    public Fragment getItem(int position) {
        Bundle b = createBundle(position, mCursor);
        return TeamCardFragment.newInstance(b);
    }
}

AsyncTask를 사용하여 viewPager에 대한 어댑터를 설정하십시오. 그것은 나를 위해 작동합니다. asyncTask는 원본 조각이 전환을 완료하도록 만드는 것입니다. 그런 다음 기본적으로 재귀를 피하기 위해 viewPager 조각을 진행합니다.

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

    mView = inflater.inflate(R.layout.team_card_master, container, false);
    mViewPager = (ViewPager)mView.findViewById(R.id.team_card_master_view_pager);

    final Button button = (Button)mView.findViewById(R.id.load_viewpager_button);
    button.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            mViewPager.setAdapter(mAdapter);
            button.setVisibility(View.GONE);
        }
    });

    mAdapter = new ViewPagerAdapter(getFragmentManager());
    new setAdapterTask().execute();

    return mView;
}

private class setAdapterTask extends AsyncTask<Void,Void,Void>{
      protected Void doInBackground(Void... params) {
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
                   mViewPager.setAdapter(mAdapter);
        }
}

FragmentStatePagerAdapter대신 사용할 수 있습니다 FragmentPageAdapter. 조각이 제거됩니다.


I just ran into this same problem. I had a Fragment that needed to host a ViewPager of Fragments. When I stacked another Fragment on top of my ViewPagerFragment, and then hit back, I would get an IllegalStateException. After checking the logs (when stacking a new Fragment), I found that my ViewPagerFragment would go through its lifecycle methods to stop and destroy, however its children Fragments in the the ViewPager would stay in onResume. I realized that the children Fragments should be managed by the FragmentManager for the ViewPagerFragment, not the FragmentManager of the Activity.

나는 그 당시에 위의 대답 Fragments은 아이를 가질 수 없다는 한계를 극복하기위한 것이었다는 것을 알고 있습니다 Fragments. 그러나 이제 최신 지원 라이브러리가 Fragment중첩 을 지원하므로 더 이상 .NET 용 어댑터 설정을 해킹 할 필요가 없으며 ViewPager전달 만하면 getChildFragmentManager()됩니다. 이것은 지금까지 완벽하게 작동했습니다.

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

    mView = inflater.inflate(R.layout.team_card_master, container, false);
    mViewPager = (ViewPager) mView.findViewById(R.id.team_card_master_view_pager);

    mAdapter = new ViewPagerAdapter(getChildFragmentManager());
    mViewPager.setAdapter(mAdapter);

    return mView;
}

Handler.post()원래 조각 트랜잭션 외부에서 어댑터를 설정 하는 데 사용 했습니다.

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    mHandler.post(new Runnable() {
        @Override
        public void run() {
            mViewPager.setAdapter(mAdapter);     
        }
    });        
}

ViewCreated의 TabIndicator에서 viewPager 어댑터를 초기화하려고 할 때이 문제에 직면했습니다. 온라인에서 그것에 대해 읽은 후 나는 이것이 조각이 아직 활동에 추가되지 않았기 때문일 수 있음을 깨달았습니다. 그래서 초기화 코드를 조각의 onStart ()로 옮겼으므로 문제가 해결 될 것입니다. 그러나 나에게는 여전히 같은 문제가 다시 발생했습니다.

하지만 내 코드에서 모든 것이 잘 작동한다는 것을 차단 한 후 executePendingTransactions ()를 명시 적으로 호출하여 보류중인 작업의 정상적인 비동기 실행을 우회하려고 시도했기 때문입니다.


부모 조각을로드 할 때 java.lang.IllegalStateException : recursive entry to executePendingTransactions 메시지와 함께 IllegalStateException이 발생합니다.

일부 연구 결과 시스템이 다른 조각 내에서 조각을 표시 할 수 없다는 결론에 도달했습니다. 그러나 ViewPager (다른 조각과 함께 사용하는 ViewPager의 버그)를 사용하여 정확히이를 수행 할 수 있다는 표시가있는 것 같습니다. ).

ViewPager의 ID를 명시 적으로 설정합니다.

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
      mView = inflater.inflate(R.layout.team_card_master, container, false);
      mViewPager = (ViewPager)mView.findViewById(R.id.team_card_master_view_pager);
      mViewPager.setId(100);

      final Button button = (Button)mView.findViewById(R.id.load_viewpager_button);
      button.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
          mViewPager.setAdapter(mAdapter);
          button.setVisibility(View.GONE);
        }
      });
      mAdapter = new ViewPagerAdapter(getFragmentManager());
      mViewPager.setAdapter(mAdapter);

      return mView;
    }

매직 넘버 100 대신 xml 리소스에서 id를 사용할 수 있습니다.

<resources>
  <item name="Id_For_ViewPager" type="id"/>
</resources>

및 setId (R.Id_For_ViewPager).

자세한 내용은 FragmentManager.java 소스를 참조하십시오.

https://github.com/android/platform_frameworks_support/blob/master/v4/java/android/support/v4/app/FragmentManager.java#L900

또는이 페이지 (일본어)를 참조하십시오. 원래 아이디어는 사실 내가 아니라 그녀에게서 나온 것입니다. http://y-anz-m.blogspot.jp/2012/04/androidfragment-viewpager-id.html


Thomas Amssler의 멋진 게시물 사용 : http://tamsler.blogspot.nl/2011/11/android-viewpager-and-fragments-part-ii.html

Iv'e는 모든 유형의 조각을 만드는 데 사용할 수있는 어댑터를 만들었습니다. 어댑터 자체는 다음과 같습니다.

public abstract class EmbeddedAdapter extends FragmentStatePagerAdapter {

private SparseArray<WeakReference<Fragment>>    mPageReferenceMap   = new SparseArray<WeakReference<Fragment>>();
private ArrayList<String> mTabTitles;

public abstract Fragment initFragment(int position);

public EmbeddedAdapter(FragmentManager fm, ArrayList<String> tabTitles) {
    super(fm);
    mTabTitles = tabTitles;
}

@Override
public Object instantiateItem(ViewGroup viewGroup, int position) {
    mPageReferenceMap.put(Integer.valueOf(position), new WeakReference<Fragment>(initFragment(position)));
    return super.instantiateItem(viewGroup, position);
}

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

@Override
public CharSequence getPageTitle(int position) {
    return mTabTitles.get(position);
}

@Override
public Fragment getItem(int pos) {
    return getFragment(pos);
}

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
    super.destroyItem(container, position, object);
    mPageReferenceMap.remove(Integer.valueOf(position));
}

public Fragment getFragment(int key) {

    WeakReference<Fragment> weakReference = mPageReferenceMap.get(key);

    if (null != weakReference) {

        return (Fragment) weakReference.get();

    } else {
        return null;
    }
}

@Override
public int getItemPosition(Object object) {
    return POSITION_NONE;
}

}

어댑터를 사용하려면 다음을 수행해야합니다.

private void setAdapter() {

    if(mAdapter == null) mAdapter = new EmbeddedAdapter(getActivity().getSupportFragmentManager(), mTabTitles) {

        @Override
        public Fragment initFragment(int position) {

            Fragment fragment;

            if(position == 0){

                // A start fragment perhaps?
                fragment = StartFragment.newInstance(mBlocks);

            }else{

                // Some other fragment
                fragment = PageFragment.newInstance(mCategories.get((position)));
            }
            return fragment;
        }
    };

    // Have to set the adapter in a handler
    Handler handler = new Handler();
    handler.post(new Runnable() {

        @Override
        public void run() {

            mViewPager.setVisibility(View.VISIBLE);
            mPagerTabStrip.setVisibility(View.VISIBLE);
            mAdapter.notifyDataSetChanged();
        }
    });
}

모든 조각은 다음을 사용합니다.

setRetainInstance(true);

문서에 따르면 : https://developer.android.com/reference/android/app/Fragment.html#getChildFragmentManager ()

중첩 조각을 관리하려면 getChildFragmentManager대신을 사용해야 합니다 getFragmentManager.


Instead of setting the adapter in AsyncTask or any Handler just write that part of code in onResume() section

Doing Such you will:

  • Let the transition of the main fragment to complete.
  • Display the child fragment without use of any background task.

The code of onResume() is as follows in your case:

@Override
public void onResume() {
    super.onResume();
    if(mViewPager.getAdapter()==null||mViewPager.getAdapter().getCount()==0)
    mViewPager.setAdapter(mAdapter);
}

Also in onCreateView Instead of

mAdapter = new ViewPagerAdapter(getFragmentManager());

Replace with

mAdapter = new ViewPagerAdapter(getChildFragmentManager());

ReferenceURL : https://stackoverflow.com/questions/7700226/display-fragment-viewpager-within-a-fragment

반응형