Android片段onCreateView延迟

问题描述 投票:0回答:2

背景和问题:

我有一个自定义的Fragment类。我将此片段类重用于多个状态显示。在父级Activity中,我加载该片段并在该片段上调用方法以设置一些文本等。执行此操作时,我命中了NullPointerException。原因是尚未调用onCreateView(),即视图不存在,因此访问TextView来调用.setText(String)当然会遇到NullPointerException

片段类

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

}

在我的主要活动中的某处,作为来自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();
}

其中copyStartFragmentcopyFinishFragment是上述片段的实例。

注意:

根据Service状态更新间隔,对replace()片段的调用几乎是瞬时的-我认为这是实际问题。

我的解决方法:

具有所有视图及其属性的initial setter。例如initialTitleTextinitialMessageTextinitialActionButtonTextinitialActionButtonVisibility等。我觉得这有点怪异,与片段使用的预期设计理念不符。

我的问题

这是我遇到此类错误的设计问题,还是有一种变通方法可以更快地调用onCreateView()

java android android-fragments android-lifecycle
2个回答
1
投票

您正在使用.commit()作为替换片段的一部分。这是异步完成的。没有办法解决,这只是该功能的工作原理。

您可以使用.commitNow(),它将完成同步。这样,您应该可以在函数返回后立即访问视图。

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


0
投票

使用推荐的方式将初始字符串传递给片段,以初始化片段:

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

    fragment.setArguments(args);
    return fragment;
}

然后输入onCreate

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

然后,当您在TextView中设置OnViewCreated文本时,字符串和任何其他参数都可用。

使用以下方法初始化活动中的片段:

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

旁注:onCreateView仅应用于膨胀布局资源,在膨胀布局之后,请使用OnViewCreated初始化视图。

© www.soinside.com 2019 - 2024. All rights reserved.