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
setUserVisibleHint called before onCreateView in Fragment
提问by Amit Yadav
I am working on ViewPager
and using Fragment
there I found
我在那里工作ViewPager
和使用Fragment
我发现
setUserVisibleHint() called before onCreateView() in Fragment
setUserVisibleHint() 在 Fragment 中的 onCreateView() 之前调用
I am using Fragment
from 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 isViewShown
instance 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 viewDidAppear
any 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 isStarted
flag:
对于支持库的当前版本,有一种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();
}
}