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);
}
// 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()
. :)
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
}
}
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.
@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();
}
}
}
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;
}
}
}
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
}
}
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) {
}
}
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
}
}
}
}
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);
}
}
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.
}
}
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
}
}