example - how to implement fragments in android studio
setUserVisibleHint llamado before onCreateView en Fragment (10)
Crea este código en tu setUserVisibleHint () :
if(isVisibleToUser && getView() != null){
isActive = true;
init();
}else if(isVisibleToUser && getView() == null){
isActive = false;
}else{
isActive = true;
}
En su onCreateView () :
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
if(!isActive){
init();
}
}
Estoy trabajando en ViewPager
y usando Fragment
allí encontré
setUserVisibleHint () llamado before onCreateView () en Fragment
Estoy usando Fragment
de la biblioteca de soporte android.support.v4.app.Fragment
¿Esto es un problema con la Biblioteca?
¿Cómo puedo deshacerme de eso?
EDITAR
Sobreescribo setUserVisibleHint () y no llamo a super para deshacerme de él.
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
//FIXED: setUserVisibleHint() called before onCreateView() in Fragment causes NullPointerException
//super.setUserVisibleHint(isVisibleToUser);
}
Esta es la mejor solución que encontré.
@Override
public void onCreateView() {
super.onStart();
isStarted = true;
if (getUserVisibilityHint()){
//do stuff
}
}
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isResumed() && isVisibleToUser) {
//do stuff
}
}
Mi SightFragment.java aquí, debe reiniciar las banderas en 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://.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) {
}
}
puede usar esta lógica, también puede desactivar viewDidAppear
cualquier momento estableciendo 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
}
}
ABAJO TRABAJADO PARA MÍ
Por favor crea una vista global como esta
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;
}
y usa esto
@Override
public void setUserVisibleHint(boolean isUserVisible)
{
super.setUserVisibleHint(isUserVisible);
// when fragment visible to user and view is not null then enter here.
if (isUserVisible && view != null)
{
// do your stuff here.
}
}
Debajo trabajó para mí ...
@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;
}
y usa esto
@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;
}
}
}
Encontré la mejor solución
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
}
Es una versión mejorada de la respuesta de fareed namrouti . Probé esto en muchas condiciones. Es seguro.
// 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;
}
}
Utilice la variable de instancia isViewShown
para decidir si va a buscar datos en onCreateView()
o en setUserVisibleHint()
.
El siguiente código contiene lógica para 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
}
Este código resolverá tu problema. Como resolvió mi problema. :)
Este truco obtendrá datos en onCreateView()
para saltar directamente de una página a otra, mientras que cuando desliza la vista obtendrá los datos del método setUserVisibleHint()
. :)
@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();
}
}
}
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
}
}
}
}