8

ho un mainactivity che include un TabLayout con ViewPagerTab + ViewPager non aggiornare invece mostra avvertimento strano previsto stato 3 ha trovato 2

Ho aggiunto 3 schede e ogni scheda ha frammenti separati che contiene un recyclerview, e queste schermate di riciclaggio hanno una casella di controllo che dovrebbe essere aggiornata/aggiornata simultaneamente ogni volta che faccio scorrere il viewpager (salverò le posizioni controllate in preferenze e aggiornamenti condivisi tramite preferenza condivisa).

Il mio problema qui è ogni volta che posso controllare una casella di controllo in TAB1, Tab2 non sta aggiornando/rinfrescante fino a quando ho scorrere la Recyclerview. e tab3 sta funzionando bene. e anche io ricevo uno strano avviso nel 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 

mio 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 codice

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

per ogni frammenti.

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; 
      } 
+1

Quindi il controllo di qualcosa in tab1 dovrebbe aggiornare la scheda 2? –

+0

si. dovrebbe essere aggiornato nella scheda 2 e nella scheda 3, ma la scheda 2 si sta aggiornando solo quando si scorre verso il basso, mentre la scheda 3 funziona correttamente. –

+2

Probabilmente ciò che sta accadendo è che andare alla scheda 2 sta chiamando qualcosa (forse 'adapter.notifyDataSetChanged();') che sta aggiornando la scheda 3. –

risposta

4

I FragmentPagerAdapter chiamate setUserVisibleHint(true|false) sui quartieri del frammento attivo che modifica lo stato di questi frammenti. Questa è almeno la risposta dei "messaggi di avviso strani" ma potrebbe non risolvere il problema.

Per quanto riguarda i suoi commenti su come risolvere il messaggio di avvertimento ho creato la mia FragmentPagerAdapter come segue:

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

} 

L'avvertimento è andato ora e attualmente non sperimentare tutti i difetti - ma sono ancora in nel mezzo della ricerca.

+0

sì. allora come posso superare questo problema? –

+1

Aggiunto esempio di come superare il messaggio di avviso. – mikes

+0

Grazie mike, avrò feedback dopo una prova. –

2

Non è importante. È solo un avvertimento. Si prega di provare a cambiare lo sfondo del layout ViewPager su null (non impostare lo sfondo).

+6

Potresti per favore elaborare più la soluzione che fornisci? – abarisone

+0

ohk dove hai problemi? –

2

Ho dedicato molto tempo a questo problema. Il problema è che si tenta di aggiornare viewpager in OnPageChangeListener ascoltatore, si getterà avvertimento

non aggiornare in linea

Soluzione:

Tutti i cambiamenti dei dati e la vista di aggiornamento dovrebbe chiamare fuori OnPageChangeListener, es: onCreateView of Fragment

Il mio avviso era sparito! E l'aggiornamento viewpager è completo

+1

non l'ho capito completamente, puoi pls farmi un esempio .. ?? –

+0

@Ruben in onTabSelected, basta chiamare 'viewPager1.setCurrentItem (tab.getPosition());' solo, notifydatasetChange è in questo metodo non è corretto, genererà avviso e frammento non aggiornato in linea – cuasodayleo

+0

Non mi interessa l'avviso, ma la scheda centrale non si aggiorna correttamente. mostra ancora il vecchio risultato. –

2

È tardi ma ho trovato una soluzione migliore utilizzando FragmentPagerAdapter, sebbene non elimini gli avvisi, ma risolva lo scopo, se qualcuno può informarmi che cosa significa in realtà quell'avvertimento e che cosa causa effettivamente l'avviso sarebbe del mio miglior interesse

Prima di tutti i frammenti utilizzati nel viewpager creare il metodo come di seguito.

 
public void updateView() { 
    //Update whatever views or data you want to update 
} 

Sovrascriviamo Inoltre metodo setUserVisibleHint che viene utilizzato in FragmentPagerAdapter per notificare se il frammento è visibile all'utente o meno.

infine nel proprio frammento aggiungere il seguente codice per aggiornare la vista/data quando il frammento è visibile.

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

quindi implementare questo nel vostro TabFragment o attività

 
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; 
        } 
        case 1: { 
         ((Fragment) mFragmentList.get(1)).updateView(); 
         break; 
        } 
       } 
      } 

Questo si prenderà cura di aggiornare i dati positiv, né si scorrere o si fa clic sulla scheda, se qualcuno trova eventuali problemi o bug, si prega di commento e fatemi sapere o sentitevi liberi di modificare la soluzione

E ho votato per la soluzione di cui sopra che mi ha dato l'approccio per applicare questa soluzione. Grazie a @mikes

1

L'avviso "W/FragmentManager: moveToState: … expected state 3 found 2" può essere ignorato ed è stato rimosso nella Libreria di supporto v24.0.0.

citazione da parte dello sviluppatore ufficiale answer:

Non c'è bisogno di fare nulla supplementare; questo è solo un messaggio di registro informativo. [...]

Il log stesso come descritto qui non influisce sul comportamento. Si prega di aprire un nuovo bug se si verificano altri problemi; combinando diversi problemi nello stesso bug rende più difficili da rintracciare questi problemi separati.

La chiusura dei commenti come problema del registro è stata risolta per una versione futura .

2

In visualizzazione le schede adiacenti del cercapersone sono caricate simultaneamente. Quindi le tue azioni nella scheda 1 non si rifletteranno nella scheda 2 poiché è già stata caricata. Dovresti utilizzare i ricevitori Broadcast per risolvere questo problema. Trasmetti un evento nella scheda 1 e ricevi l'evento nella scheda 2

Problemi correlati