Android setUserVisibleHint 在 Fragment 中的 onCreateView 之前调用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24161160/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 07:51:35  来源:igfitidea点击:

setUserVisibleHint called before onCreateView in Fragment

androidandroid-fragmentscallback

提问by Amit Yadav

I am working on ViewPagerand using Fragmentthere I found

我在那里工作ViewPager和使用Fragment我发现

setUserVisibleHint() called before onCreateView() in Fragment

setUserVisibleHint() 在 Fragment 中的 onCreateView() 之前调用

I am using Fragmentfrom support library android.support.v4.app.Fragment

我正在使用Fragment支持库android.support.v4.app.Fragment

Is this is a problem with Library ?

这是图书馆的问题吗?

How can I get rid of it ?

我怎样才能摆脱它?

EDIT

编辑

I Override setUserVisibleHint() and not calling super to get rid of it.

我覆盖 setUserVisibleHint() 而不是调用 super 来摆脱它。

@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    //FIXED: setUserVisibleHint() called before onCreateView() in Fragment causes NullPointerException
    //super.setUserVisibleHint(isVisibleToUser);
}

回答by vikoo

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

Use isViewShowninstance variable to decide whether to fetch data in onCreateView()or in setUserVisibleHint().

使用isViewShown实例变量来决定是onCreateView()setUserVisibleHint().

Below code contains logic for onCreateView():

下面的代码包含逻辑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
}

This code will solve your problem. As It solved my problem. :)

此代码将解决您的问题。因为它解决了我的问题。:)

This trick will fetch data in onCreateView()for direct jumping from one page to another, whereas when you swipe the view it will fetch the data from setUserVisibleHint()method. :)

这个技巧将获取数据onCreateView()以直接从一个页面跳转到另一个页面,而当您滑动视图时,它将从setUserVisibleHint()方法中获取数据。:)

回答by Fareed Alnamrouti

you can use this logic, also you can turn off viewDidAppearany time by setting isVisible = false

您可以使用此逻辑,也可以viewDidAppear通过设置随时关闭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
    }
}

回答by DrMorteza

I found the best 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
}

It's improved version of fareed namrouti's answer. I tested this on many conditions. It's safe.

它是fareed namrouti答案的改进版。我在许多条件下对此进行了测试。它是安全的。

回答by Gev Kostanyan

@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();
          }
    }
}

回答by Vijay

Below Worked for me....

下面为我​​工作......

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

and use this

并使用这个

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

    }

回答by joinAero

My SightFragment.javahere, should reset the flags in onDestroyView():

我的SightFragment.java在这里,应该重置标志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) {
    }

}

回答by Tobias

While most of this solutions work, you don't even need to track the state by yourself.

虽然大多数解决方案都有效,但您甚至不需要自己跟踪状态。

With current versions fo the support library there is a isResumed()method which does probably what most of you try to achieve by using an isStartedflag:

对于支持库的当前版本,有一种isResumed()方法可能可以通过使用isStarted标志来完成大多数人尝试实现的目标:

Return true if the fragment is in the resumed state. This is true for the duration of onResume() and onPause() as well.

如果片段处于恢复状态,则返回 true。对于 onResume() 和 onPause() 的持续时间也是如此。

And then it's as easy as:

然后就这么简单:

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

回答by V.March

That simple variant work in my code:

这个简单的变体在我的代码中工作:

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

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

and

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

    if (isResumed() && isVisibleToUser) {
       updateUI(); // your logic
    }
}

回答by Rahul

BELOW WORKED FOR ME

以下为我工作

Please create a global view like this

请创建这样的全局视图

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

and use this

并使用这个

@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.
            }
    }

回答by reed

Create this code in your setUserVisibleHint():

在您的setUserVisibleHint() 中创建此代码:

if(isVisibleToUser && getView() != null){
        isActive = true;
        init();
    }else if(isVisibleToUser && getView() == null){
        isActive = false;
    }else{
        isActive = true;
    }

In your onCreateView():

在您的onCreateView() 中

public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
if(!isActive){
        init();
    }
}