web-dev-qa-db-ja.com

Tab + ViewPagerが更新されない代わりに、奇妙な警告が表示されます。

ViewPagerを含むTabLayoutを含むメインアクティビティがあります

3つのタブを追加し、各タブにはrecyclerviewを含む個別のフラグメントがあり、これらのrecyclerviewには、ビューページャーをスワイプするたびに同時に更新/更新する必要があるチェックボックスがあります(チェックした位置を共有に保存します)プリファレンスと共有プリファレンスを介した更新)

ここでの私の問題は、tab1のチェックボックスをオンにするたびに、Recyclerviewを下にスクロールするまで、tab2が更新/更新されないことです。tab3は正常に機能しています。およびで奇妙な警告が表示されますlogcatも。

 03-05 09:35:53.345 4317-4327/com.example.rubin W/art: Suspending all threads took: 6.805ms
    03-05 09:35:58.310 4317-4317/com.example.rubin W/FragmentManager: moveToState: Fragment state for Tab3{10a5f1f0 #2 id=0x7f0d00b6} not updated inline; expected state 3 found 2
    03-05 09:36:01.363 4317-4317/com.example.rubin W/FragmentManager: moveToState: Fragment state for Tab1{2d9aa887 #1 id=0x7f0d00b6} not updated inline; expected state 3 found 2 

私のPagerAdapter

public class PagerAdapter1 extends FragmentStatePagerAdapter {
    int mNumOfTabs;
    public PagerAdapter1(FragmentManager fm, int NumOfTabs) {
        super(fm);
        this.mNumOfTabs = NumOfTabs;
    }
    @Override
    public Fragment getItem(int position) {
        switch (position) {
            case 0:
               return new Tab1();
            case 1:
               return new Tab2();
            case 2:
               return new Tab3();

            default:
                return null;

        }
    }

    @Override
    public int getCount() {
        return mNumOfTabs;
    }
}

Tablayout OnPageChangelistener

final PagerAdapter1 adapter = new PagerAdapter1
                (getSupportFragmentManager(), tabLayout1.getTabCount(), getApplicationContext());
        viewPager1.setAdapter(adapter);
        viewPager1.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout1));
        tabLayout1.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                viewPager1.setCurrentItem(tab.getPosition());
                adapter.notifyDataSetChanged();
            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {

            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {
            }
        });
    }

各フラグメントのコード。

 public class Tab1 extends Fragment {

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View v = inflater.inflate(R.layout.home_tab1_recycler, container, false);
            RecyclerView rv = (RecyclerView) v.findViewById(R.id.home_recyclerview);   
            LinearLayoutManager llm = new LinearLayoutManager(getContext());
            rv.setLayoutManager(llm);
            rv.setHasFixedSize(true); // to improve performance
            rv.setAdapter(new HomeManager()); // the projectdatabase manager is assigner to the RV
            return v;
        }

        public class HomeManager extends RecyclerView.Adapter<HomeManager.RecyclerViewHolder> {
    int Length,h;
 View v1;
        ArrayList<String> PROJECT_ID = new ArrayList<String>();
Set<String> set;
        List<String> selected;
     public class RecyclerViewHolder extends RecyclerView.ViewHolder {
     CheckBox mCheck;
      RecyclerViewHolder(final View itemView) {
                    super(itemView);
      mCheck = (CheckBox) itemView.findViewById(R.id.PROJECT_fav);
     SharedPreferences pref = getContext().getSharedPreferences("MirSP", Context.MODE_PRIVATE);
                    set = pref.getStringSet("FAV", null);
      if (set != null) {
                        selected = new ArrayList<String>(set);
                    } else {
                        selected = new ArrayList<String>();
                    }
    mCheck.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
     h = getAdapterPosition();
    check = PROJECT_ID.get(h); // for saving the project id from json.
     if (selected.contains(check)) {
                                    selected.remove(check);
                                    mCheck.setBackgroundResource(R.drawable.ic_favorite_white1_24dp);
                                    Snackbar snackbar = Snackbar.make(v, "Property Unfavorited", Snackbar.LENGTH_SHORT);
                                    snackbar.show();
                                } else {
                                    selected.add(check);
                                    mCheck.setBackgroundResource(R.drawable.ic_favorite_white_24dp);
                                    Snackbar snackbar = Snackbar.make(v, "Property Favorited", Snackbar.LENGTH_SHORT);
                                    snackbar.show();

                                }
                                Log.e("HF update checked", String.valueOf(selected));
                                Set<String> set = new HashSet<String>();
                                set.addAll(selected);
                                SharedPreferences pref = getContext().getSharedPreferences("MirSP", Context.MODE_PRIVATE);
                                SharedPreferences.Editor editor = pref.edit();
                                editor.putStringSet("FAV", set);
                                editor.commit();
                            }
         }
                    });
     @Override
            public RecyclerViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
                v1 = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.recyclerview_item, viewGroup, false);
                return new RecyclerViewHolder(v1);
            }

            @Override
            public void onBindViewHolder(final RecyclerViewHolder viewHolder, int i) {
    SharedPreferences pref = getContext().getSharedPreferences("MirSP", Context.MODE_PRIVATE);
                set = pref.getStringSet("FAV", null);
                if (set != null) {
                    selected = new ArrayList<String>(set);
                } else {
                    selected = new ArrayList<String>();
                }
                Log.e("HF update UI", String.valueOf(selected));
    if (String.valueOf(selected).contains(String.valueOf(PROJECT_ID.get(i)))) {
                        viewHolder.mCheck.setBackgroundResource(R.drawable.ic_favorite_white_24dp);
                    } else {
                        viewHolder.mCheck.setBackgroundResource(R.drawable.ic_favorite_white1_24dp);
                    }
                }
     @Override
            public int getItemCount() {
                //Code for Total length of json
                return Length;
            }
8
Mr Robot

FragmentPagerAdapterはアクティブなフラグメントの近傍でsetUserVisibleHint(true|false)を呼び出し、このフラグメントの状態を変更します。これは少なくとも「奇妙な警告メッセージ」の答えですが、問題が解決しない場合があります。

その警告メッセージを解決する方法についてのあなたのコメントに関して、私は次のように私自身のFragmentPagerAdapterを作成しました:

public abstract class AbstractTabPagerAdapter extends PagerAdapter {

    private static final String TAG = AbstractTabPagerAdapter.class.getCanonicalName();

    private final FragmentManager mFragmentManager;

    private FragmentTransaction mCurTransaction;

    private Fragment mCurrentPrimaryItem = null;

    public AbstractTabPagerAdapter(FragmentManager fragmentManager) {
        mFragmentManager = fragmentManager;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        if (mCurTransaction == null) {
            throw new IllegalArgumentException("current transaction must not be null");
        }
        String fragmentTag = makeFragmentName(container.getId(), position);
        Fragment fragment = (Fragment) mFragmentManager.findFragmentByTag(fragmentTag);
        if (fragment != null) {
            mCurTransaction.attach(fragment);
            Log.d(TAG, "Attaching existing fragment " + fragment + " at position " + position);
            //mCurTransaction.add(container.getId(), fragment, makeFragmentName(container.getId(), position));
        } else {
            fragment = getItem(position);
            mCurTransaction.add(container.getId(), fragment, fragmentTag);
            Log.d(TAG, "Attaching new fragment " + fragment + " at position " + position);
        }

        if (fragment != mCurrentPrimaryItem) {
            fragment.setMenuVisibility(false);
            //fragment.setUserVisibleHint(false);
        }

        return fragment;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        if (mCurTransaction == null) {
            throw new IllegalArgumentException("current transaction must not be null");
        }
        mCurTransaction.detach((Fragment) object);
        //mCurTransaction.remove((Fragment)object);
    }

    @Override
    public void setPrimaryItem(ViewGroup container, int position, Object object) {
        //super.setPrimaryItem(container, position, object);
        Fragment fragment = (Fragment) object;
        if (fragment != mCurrentPrimaryItem) {
            Log.d(TAG, "set Primary item " + position + " to " + fragment);
            if (mCurrentPrimaryItem != null) {
                mCurrentPrimaryItem.setMenuVisibility(false);
                // this command unexpectedly changes the state of the fragment which leads to a warning message and possible some strange behaviour
                //mCurrentPrimaryItem.setUserVisibleHint(false);
            }
            if (fragment != null) {
                fragment.setMenuVisibility(true);
                //fragment.setUserVisibleHint(true);
            }
            mCurrentPrimaryItem = fragment;
        }
    }

    @Override
    public boolean isViewFromObject(View view, Object fragment) {
        return ((Fragment) fragment).getView() == view;
    }

    public abstract Fragment getItem(int position);

    @Override
    public void startUpdate(ViewGroup container) {
        super.startUpdate(container);
        if (mCurTransaction != null) {
            throw new IllegalArgumentException("current transaction must not be null");
        }
        mCurTransaction = mFragmentManager.beginTransaction();
        Log.d(TAG, "FragmentTransaction started");
    }

    @Override
    public void finishUpdate(ViewGroup container) {
        if (mCurTransaction != null) {
            mCurTransaction.commit();
            mCurTransaction = null;
            //mFragmentManager.executePendingTransactions();
            Log.d(TAG, "FragmentTransaction committed");
        } else {
            throw new IllegalArgumentException("current transaction must not be null");
        }
    }

    private String makeFragmentName(int viewId, int position) {
        if (viewId <= 0)
            throw new IllegalArgumentException("viewId " + viewId);
        return "tabpageradptr:" + getPageTitle(position) + ":" + viewId + ":" + position;
    }

}

警告メッセージは消え、現在は欠陥はありませんが、まだ調査中です。

4
mikes

遅いですが、FragmentPagerAdapterを使用する最善の方法を考え出しましたが、警告を削除するわけではありませんが、目的を解決します。誰かがその警告が実際に何を意味し、実際に警告を引き起こしているのかを教えてくれるなら、それは私の最大の関心事です。

まず、viewpagercreateメソッドで使用されるすべてのフラグメントで次のようになります。

 public void updateView(){
 //更新するビューまたはデータを更新します
} 

また、FragmentPagerAdapterで使用されるメソッドsetUserVisibleHintをオーバーライドして、フラグメントがユーザーに表示されるかどうかを通知します。

 @ Override 
 public void setUserVisibleHint(boolean isVisibleToUser){
 this.isVisibleToUser = isVisibleToUser; 
 super.setUserVisibleHint(isVisibleToUser); 
 .____。]

最後に、フラグメントに次のコードを追加して、フラグメントが表示されたときにビュー/日付を更新します。

 @ Override 
 public void onStart(){
 if(isVisibleToUser)
 updateView(); 
} 

次に、これをTabFragmentまたはActivityに実装します

 viewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener(){
 @Override 
 public void onPageScrolled(int position、float positionOffset、int positionOffsetPixels){
 
} 
 
 @ Override 
 public void onPageSelected(int position){
 
 switch(position){
 case 0 :{
((Fragment)mFragmentList.get(0))。updateView(); 
 break; 
} 
ケース1:{
 ((Fragment)mFragmentList.get(1))。updateView(); 
 break; 
} 
} 
} 

これにより、スワイプするかタブをクリックするかして、データが一貫して更新されます。問題やバグが見つかった場合は、コメントしてお知らせください。または、ソリューションを編集してください。

そして、私はこのソリューションを適用するためのアプローチを私に与えた上記のソリューションに投票しました。ありがとう@mikes

2
PravinDodia

それは重要ではありません。これは単なる警告です。 ViewPagerレイアウトの背景をnullに変更してみてください(背景を設定しないでください)。

2
Bipin Bharti

私はこの問題に多くの時間を費やしました。問題は、OnPageChangeListenerリスナーでviewpagerを更新しようとすると、警告がスローされることです。

インラインで更新されません

解決:

すべてのデータ変更および更新ビューは、OnPageChangeListenerから呼び出す必要があります。例:onCreateView of Fragment

警告が消えました!そして、viewpagerは完全に更新されます

2
cuasodayleo

ビューページャーでは、隣接するタブが同時に読み込まれます。したがって、タブ1でのアクションは、すでにロードされているため、タブ2には反映されません。この問題を解決するには、ブロードキャストレシーバーを使用する必要があります。タブ1でイベントをブロードキャストし、タブ2でイベントを受信します

2
Sachin Thampan

"W/FragmentManager: moveToState: … expected state 3 found 2"警告は無視でき、サポートライブラリv24.0.0で削除されました。

公式開発者からの引用 回答

追加のことをする必要はありません。これは情報ログメッセージのみです。 […]

ここで説明するログ自体は、動作に影響を与えません。他に問題がある場合は、新しいバグを開いてください。同じバグで異なる問題を混同すると、それらの個別の問題を追跡するのがより困難になります。

ログの問題としてコメントを閉じることは、将来のリリースで解決されました。

1
lejonl