【发布时间】:2019-12-22 19:51:42
【问题描述】:
背景和问题:
我有一个自定义的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();
}
其中copyStartFragment & copyFinishFragment 是上述片段的实例。
注意:
根据Service 状态更新间隔,对replace() 片段的调用几乎是瞬时的——我认为这是实际问题。
我的解决方法:
为所有视图及其属性设置 initial 设置器。例如initialTitleText、initialMessageText、initialActionButtonText、initialActionButtonVisibility 等。我觉得这是 hack'ish,不符合 Fragment 使用的预期设计理念。
我的问题
这是我遇到此类错误的设计问题,还是有解决方法可以尽快致电onCreateView()?
【问题讨论】:
-
public CopyStaticFragment(View.OnClickListener actionCallback) {除非您还使用了FragmentFactory,但您可能没有使用,否则您应该会收到一个 lint 错误,如果您这样做,您的应用程序将以可怕的方式崩溃。你所有的set*方法都应该通过Bundle arguments使用fragment.setArguments(Bundle)传递。 -
@EpicPandaForce 感谢您的建议。 set* 方法只是作为一种临时措施——如果没有给出主要问题的解决方案,将实施捆绑。另外,请您解释一下构造函数中的回调问题吗?
-
@EpicPandaForce 非常有帮助,谢谢。此外,您在上面的评论中提到的解决方案似乎也包括我正在使用的这种“解决方法”。即事先设置这些值 - 所以
onCreateView()延迟似乎是一个实际问题。 -
可以在onViewCreated中设置Text。
标签: java android android-fragments android-lifecycle