web-dev-qa-db-fra.com

setUserVisibleHint appelé avant onCreateView dans Fragment

Je travaille sur ViewPager et j'utilise Fragment ici 

setUserVisibleHint () appelé avant onCreateView () dans Fragment

J'utilise Fragment de la bibliothèque de support Android.support.v4.app.Fragment

Est-ce un problème avec Library?

Comment puis-je m'en débarrasser ?

MODIFIER

Je remplace setUserVisibleHint () et n'appelle pas super pour s'en débarrasser.

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    //FIXED: setUserVisibleHint() called before onCreateView() in Fragment causes NullPointerException
    //super.setUserVisibleHint(isVisibleToUser);
}
50
Amit Yadav
// create boolean for fetching data
private boolean isViewShown = false;

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (getView() != null) {
        isViewShown = true;
        // fetchdata() contains logic to show data when page is selected mostly asynctask to fill the data
        fetchData();
    } else {
        isViewShown = false;
    }
} 

Utilisez la variable d'instance isViewShown pour décider s'il faut extraire les données dans onCreateView() ou dans setUserVisibleHint().

Le code ci-dessous contient une logique pour onCreateView():

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.main_layout, container, false);

   // view initialization steps.......

   if (!isViewShown) {
        fetchData();
   } 
   // do other stuff
}

Ce code va résoudre votre problème. Comme cela a résolu mon problème. :)

Cette astuce va extraire des données dans onCreateView() pour un saut direct d'une page à une autre, alors que lorsque vous balayez la vue, les données seront extraites de la méthode setUserVisibleHint(). :) 

86
vikoo

vous pouvez utiliser cette logique, vous pouvez également désactiver viewDidAppear à tout moment en définissant isVisible = false 

public class MyFragment extends Fragment {
    private Boolean isStarted = false;
    private Boolean isVisible = false;

    @Override
    public void onStart() {
        super.onStart();
        isStarted = true;
        if (isVisible && isStarted){
            viewDidAppear();
        }
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        isVisible = isVisibleToUser;
        if (isStarted && isVisible) {
            viewDidAppear();
        }
    }

    public void viewDidAppear() {
       // your logic
    }
}
25
Fareed Alnamrouti

J'ai trouvé la meilleure solution

private boolean isVisible;
private boolean isStarted;

@Override
public void onStart() {
    super.onStart();
    isStarted = true;
    if (isVisible)
        sendRequest(); //your request method
}

@Override
public void onStop() {
    super.onStop();
    isStarted = false;
}

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    isVisible = isVisibleToUser;
    if (isVisible && isStarted)
        sendRequest(); //your request method
}

C'est une version améliorée de la réponse de fareed namrouti. J'ai testé cela sur de nombreuses conditions. C'est sur.

12
Doctor Henry
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment, container, false);

    if (getUserVisibleHint()) {
         sendRequest();
    }

    return view;
}

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    if (isVisibleToUser) {
        if (isResumed()){ 
             sendRequest();
          }
    }
}
4
Gev Kostanyan

Ci-dessous a travaillé pour moi .... 

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState)
{
    //// create class member variable to store view
    viewFrag =inflater.inflate(R.layout.fragment_main_favorite, container, false);

    // Inflate the layout for this fragment
    return viewFrag;
}

et utiliser cette 

 @Override
    public void setUserVisibleHint(boolean visible)
    {
        super.setUserVisibleHint(visible);


            if (visible)
            {

                View v =  viewFrag ;
                if (v == null) {
                    Toast.makeText(getActivity(), "ERROR ", Toast.LENGTH_LONG ).show();
                    return;
                }
            }

    }
3
Vijay

Cette variante simple fonctionne dans mon code:

@Override
public void onStart() {
    super.onStart();

    if (getUserVisibleHint()) {
        updateUI(); // your logic
    }
}

et

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

    if (isResumed() && isVisibleToUser) {
       updateUI(); // your logic
    }
}
1
V.March

Mon SightFragment.Java ici, devrait réinitialiser les indicateurs dans onDestroyView():

package cc.cubone.turbo.core.app;

import Android.os.Bundle;
import Android.support.v4.app.Fragment;
import Android.view.View;

/**
 * Fragment for handling view after it has been created and visible to user for the first time.
 *
 * <p>Specially in {@link Android.support.v4.view.ViewPager}, the page will be created beforehand
 * but not be visible to user.
 *
 * <p>Call {@link Android.support.v4.view.ViewPager#setOffscreenPageLimit(int)} to set the number of
 * pages that should be retained.
 *
 * Reference:
 * <ul>
 * <li><a href="http://stackoverflow.com/questions/10024739/how-to-determine-when-fragment-becomes-visible-in-viewpager">
 * How to determine when Fragment becomes visible in ViewPager</a>
 * </ul>
 */
public class SightFragment extends Fragment {

    private boolean mUserSeen = false;
    private boolean mViewCreated = false;

    public SightFragment() {
    }

    /*public boolean isUserSeen() {
        return mUserSeen;
    }

    public boolean isViewCreated() {
        return mViewCreated;
    }*/

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (!mUserSeen && isVisibleToUser) {
            mUserSeen = true;
            onUserFirstSight();
            tryViewCreatedFirstSight();
        }
        onUserVisibleChanged(isVisibleToUser);
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        // Override this if you want to get savedInstanceState.
        mViewCreated = true;
        tryViewCreatedFirstSight();
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        mViewCreated = false;
        mUserSeen = false;
    }

    private void tryViewCreatedFirstSight() {
        if (mUserSeen && mViewCreated) {
            onViewCreatedFirstSight(getView());
        }
    }

    /**
     * Called when the new created view is visible to user for the first time.
     */
    protected void onViewCreatedFirstSight(View view) {
        // handling here
    }

    /**
     * Called when the fragment's UI is visible to user for the first time.
     *
     * <p>However, the view may not be created currently if in {@link Android.support.v4.view.ViewPager}.
     */
    protected void onUserFirstSight() {
    }

    /**
     * Called when the visible state to user has been changed.
     */
    protected void onUserVisibleChanged(boolean visible) {
    }

}
1
joinAero
public class MyFragment extends Fragment {

private boolean manageVisibility;


public MyFragment() {
    // Required empty public constructor
}

public static CommunityFragment newInstance() {

    Bundle args = new Bundle();

    CommunityFragment fragment = new CommunityFragment();
    fragment.setArguments(args);
    return fragment;
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    manageVisibility = true;
    return inflater.inflate(R.layout.fragment_community, container, false);
}


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

    if (manageVisibility && isVisibleToUser) {
       // fragment is visible
        }
    } else if (manageVisibility) {
       // fragment is invisible
        }
    }
  } 
}
0
Levon Petrosyan

Bien que la plupart de ces solutions fonctionnent, vous n'avez même pas besoin de suivre l'état par vous-même.

Avec les versions actuelles de la bibliothèque de support, il existe une méthodeisResumed()qui correspond probablement à ce que la plupart d’entre vous essayez d’atteindre en utilisant un indicateur isStarted:

Renvoie true si le fragment est à l'état de reprise. Cela vaut également pour la durée de onResume () et onPause ().

Et puis c'est aussi simple que:

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (isResumed()) {
            updateUi(isVisibleToUser);
        }
    }
0
Tobias

CI-DESSOUS A TRAVAILLÉ POUR MOI

S'il vous plaît créer une vue globale comme celle-ci

private View view; 

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        //Inflate view layout
        view =inflater.inflate(R.layout.your_fragment, container, false);

        // return view
        return view;
    }

et utiliser cette

@Override
    public void setUserVisibleHint(boolean isUserVisible)
    {
        super.setUserVisibleHint(isUserVisible);
       //When fragment is visible to user and view is not null then enter here.
            if (isUserVisible && view != null)
            {
               // do your stuff here.
            }
    }
0
Rahul

C'est la meilleure solution que j'ai trouvée.

    @Override
    public void onCreateView() {
        super.onStart();
        if (getUserVisibilityHint()){
            //do stuff
        }
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (isResumed() && isVisibleToUser) {
            //do stuff
        }
    }
0
free_style