简体   繁体   English

Android 片段 onCreateView 延迟

[英]Android fragment onCreateView delayed

Background & Problem:背景与问题:

I have a custom Fragment class.我有一个自定义Fragment类。 I reuse this fragment class for multiple status displays.我将这个片段类重用于多个状态显示。 In the parent Activity , I load the fragment and call a method on the fragment to set some text, etc. When I do this, I hit a NullPointerException .在父Activity ,我加载片段并调用片段上的方法来设置一些文本等。当我这样做时,我遇到了NullPointerException The reason is onCreateView() has not yet been called, ie the view doesn't exist, thus accessing a TextView to call .setText(String) will ofcourse run into a NullPointerException .原因是onCreateView()还没有被调用,即视图不存在,因此访问TextView来调用.setText(String)会遇到NullPointerException

Fragment Class片段类

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;

import com.example.app.R;

public class CopyStaticFragment extends Fragment {

    private String initialActionText, initialSecondaryText, initialTitleText;
    private TextView textViewTitle, textViewSecondary;
    private Button btnAction;
    private View.OnClickListener actionCallback;

    public void setActionButtonListener(View.OnClickListener actionCallback) {
        this.actionCallback = actionCallback;
    }

    public CopyStaticFragment() {
    }

    public CopyStaticFragment(View.OnClickListener actionCallback) {
        this.actionCallback = actionCallback;
    }

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

        textViewTitle = layout.findViewById(R.id.textViewTitle);
        textViewTitle.setText(initialTitleText);
        textViewSecondary = layout.findViewById(R.id.textViewSecondary);
        textViewSecondary.setText(initialSecondaryText);
        btnAction = layout.findViewById(R.id.btnAction);
        btnAction.setText(initialActionText);
        btnAction.setOnClickListener(v -> {
            if(actionCallback != null) {
                actionCallback.onClick(v);
            }
        });

        return layout;
    }

    public void setPrimaryText(String text) {
        textViewTitle.setText(text);
    }

    public void setSecondaryText(String text) {
        textViewSecondary.setText(text);
    }

    public void setActionText(String text) {
        btnAction.setText(text);
    }

    public void setInitialActionText(String text) {
        this.initialActionText = text;
    }

    public void setInitialSecondaryText(String text) {
        this.initialSecondaryText = text;
    }

    public void setInitialTitleText(String text) {
        this.initialTitleText = text;
    }

}

Somewhere in my main activity, as a callback response from a Service status, I will do something like:在我的主要活动的某个地方,作为来自Service状态的回调响应,我将执行以下操作:

if (instance.getUnbackedUpCount() > 0) {
    // Load first fragment - i.e. we can backup content
    getSupportFragmentManager().beginTransaction()
            .replace(R.id.frameCurrentStatus, copyStartFragment)
            .commit();
    capacityControlFragment.setInfoIconVisible(true);
} else {
    getSupportFragmentManager().beginTransaction()
            .replace(R.id.frameCurrentStatus, copyFinishFragment)
            .commit();
}

where copyStartFragment & copyFinishFragment are instances of the above mentioned fragment.其中copyStartFragmentcopyFinishFragment是上述片段的实例。

Note:笔记:

Depending on the Service status update interval, the call to replace() fragments can be almost instantaneous - which I figure is the actual problem.根据Service状态更新间隔,对replace()片段的调用几乎是瞬时的——我认为这是实际问题。

My workaround:我的解决方法:

Is to have initial setters for all views and their properties.是为所有视图及其属性设置初始设置器。 eg initialTitleText , initialMessageText , initialActionButtonText , initialActionButtonVisibility , etc. I feel this is hack'ish and not inline with the intended design philisophy of Fragment use.例如initialTitleTextinitialMessageTextinitialActionButtonTextinitialActionButtonVisibility等。我觉得这是hack'ish,不符合Fragment 使用的预期设计理念。

My Question我的问题

Is this a design problem on my part for encountering such an error or is there a workaround to call the onCreateView() sooner?这是我遇到此类错误的设计问题还是有解决方法可以更快地调用onCreateView()

You are using .commit() as part of replacing fragments.您正在使用.commit()作为替换片段的一部分。
This is done async.这是异步完成的。 No way around it, it's just how that function works.没有办法解决它,这就是该功能的工作方式。

You can use .commitNow() , and it will be done sync.您可以使用.commitNow() ,它将完成同步。
By doing it like this, you should be able to access the views instantly after the function returns.通过这样做,您应该能够在函数返回后立即访问视图。

https://developer.android.com/reference/androidx/fragment/app/FragmentTransaction#commitNow() https://developer.android.com/reference/androidx/fragment/app/FragmentTransaction#commitNow()

Pass the initial strings to the fragment using the recommended way to initialise a fragment:使用推荐的方法将初始字符串传递给片段以初始化片段:

public static CopyStaticFragment newInstance(String initialString....) {
    CopyStaticFragment fragment = new CopyStaticFragment();
    Bundle args = new Bundle();
    args.putString(INITIAL_STRING, initialString);

    fragment.setArguments(args);
    return fragment;
}

Then in onCreate :然后在onCreate

 @Override
public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
    if (getArguments() != null) {
        mInitialString = getArguments().getString(INITIAL_STRING);
    }
}

Then when you set your TextView text in OnViewCreated the string and any other parameters are available.然后,当您在OnViewCreated设置TextView文本时,字符串和任何其他参数都可用。

Initialise your fragment in the activity using:使用以下方法在活动中初始化您的片段:

CopyStaticFragment.newInstance("initial string",....);

Side note: onCreateView should only be used to inflate your layout resource, use OnViewCreated to initialise your views after the layout has been inflated.旁注: onCreateView应该只用于膨胀你的布局资源,在布局膨胀后使用OnViewCreated来初始化你的视图。

Stay as far away as you can from commitNow() and popBackStackImmediate() unless you love IllegalStateException尽可能远离commitNow()popBackStackImmediate()除非你喜欢IllegalStateException

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 带有错误片段的ViewPagers oncreateView的Android片段 - Android Fragment with ViewPagers oncreateView Called in Wrong Fragment Android片段oncreateview被调用,但视图未膨胀且没有错误 - Android fragment oncreateview is called but view is not inflated and there are no errors 使用onCreateView的Android片段但无法添加Firebase - android fragment using onCreateView but cant add firebase onCreateView中的Android片段getActivity()。getApplicationContext()为null - Android Fragment getActivity().getApplicationContext() in onCreateView is null Android-片段视图在onCreateView之外获取NULL - Android - Fragment Views get NULL outside onCreateView android setText在片段内部被延迟 - android setText is delayed inside fragment 在OnCreateView中显示Admob插页式广告时未加载Android片段布局 - Android fragment layout not loading when showing an Admob interstitial ad in OnCreateView 尽管初始化,Android Fragment onCreateView的ArrayList也为空 - Android Fragment onCreateView has null ArrayList despite initialization Android:访问内部AsyncTask类的变量,但在片段的onCreateView中将其获取为null - Android: Accessing a variable of an inner AsyncTask class but getting it as null in onCreateView of a fragment onCreateView Fragment未调用 - onCreateView Fragment not called
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM