如何防止我的findViewById方法被过早调用?

时间:2016-04-13 20:23:25

标签: java android

所以我有Dialog,其中包含一些editText字段(这些字段分布在3个片段上,由viewpager显示,以防此信息很重要)。对于edit操作,我想创建一个已经放入一些值的对话框。

目前我试图这样做:

editButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                GeneralSettingsInitialInputDialog GSIID = new GeneralSettingsInitialInputDialog();
                Bundle args = new Bundle();
                args.putString("name", TitleTV.getText().toString());
                args.putString("ip", IPaddressET.getText().toString());
                args.putString("port", PortET.getText().toString());
                args.putString("username", UsernameET.getText().toString());
                args.putString("pass", PasswordET.getText().toString());
                Log.d(tag, args.toString());

                GSIID.setArguments(args);
                GSIID.show(((Activity) context).getFragmentManager(), "GSIID");

这显示了编辑按钮的onClickListener(包含在recyclerView中。这个特定位来自我的Adapter)。

之后,我在GSIID dialogFragment的onCreateDialog方法中尝试了这个:

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    LayoutInflater inflater = getActivity().getLayoutInflater();
    ma = (MainActivity) getActivity();
    dbHandler = DBHandler.getInstance(getActivity());

    view = inflater.inflate(R.layout.fragment_generalsettingsviewpager, null);

    mPager = (ViewPager) view.findViewById(R.id.pager);
    mPager.setOffscreenPageLimit(3);
    mPagerAdapter = new TestAdapter();
    mPager.setAdapter(mPagerAdapter);


    if (getArguments() != null) {
        ((EditText) view.findViewById(R.id.IDName)).setText(getArguments().getString("name"));
        ((EditText) view.findViewById(R.id.IDIPaddress)).setText(getArguments().getString("ip"));
        ((EditText) view.findViewById(R.id.IDPort)).setText(getArguments().getString("port"));
        ((EditText) view.findViewById(R.id.IDUsername)).setText(getArguments().getString("username"));
        ((EditText) view.findViewById(R.id.IDPassword)).setText(getArguments().getString("pass"));
    }


    // Build Dialog
    final AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
    builder.setView(view)
            .setTitle("Setup Device")
            .setMessage("Please add all required details for your Raspberry Pi here.")
            .setPositiveButton("Next", null)
            .setNegativeButton("Cancel", null);
    return builder.show();
}

这返回了一个NPE,说我试图在空值上使用setText,因此view.findViewById()返回null。我想我已经通过将此代码移动到onStart()方法来解决这个问题,以确保在我尝试设置内容之前一切都在那里,但我仍然得到相同的错误。< / p>

这一次,我注意到在错误发生之前对话框没有打开,所以我猜测findViewById()方法仍然过早被调用,但我没有&#39;我知道如何解决这个问题。

我已通过测试以确保我的代码没有被破坏,通过在按下GSIID对话框上的按钮时运行上述代码(因此打开对话框)。这确实有效。

所以,基本上:如何防止过早调用此findViewById方法?

3 个答案:

答案 0 :(得分:0)

最有可能是通过调用您从此方法返回的视图上的查找来查找onCreateView()中的视图。

答案 1 :(得分:0)

你需要在android link中掌握一个Activity的生命周期,这个link可以帮助你理解生命周期每一步中函数调用的顺序。

在大多数情况下,您可以在class Parent: Object, Mappable { dynamic var id: Int = 0 var children = List<Child>() required convenience init?(_ map: Map) { self.init() } func mapping(map: Map) { id <- map["id"] child <- (map["children"], ListTransform<Child>()) } } 中查看自己的观点,因此将onCreatView()放在那里是合理的,但在其他情况下,您应该确保在调用findViewById之前视图已被夸大

答案 2 :(得分:0)

好吧,感谢this张贴,我的一天得救了。

基本上,您只需要在自定义private View view0 = null; private View view1 = null; private View view2 = null; private View viewError = null; public TestAdapter(LayoutInflater inflater) { view0 = inflater.inflate(R.layout.fragment_generalsettingsinputdialog1, null); view1 = inflater.inflate(R.layout.fragment_generalsettingsinputdialog2, null); view2 = inflater.inflate(R.layout.fragment_generalsettingsinputdialog3, null); viewError = inflater.inflate(R.layout.fragment_viewpagererror, null); } 中使用一个方法来返回您为其提供的索引的视图。

CustomAdapter

新: 构造函数(我相信它的名字是什么)

@Override
public Object instantiateItem(ViewGroup container, int position) {
    LayoutInflater inflater = getActivity().getLayoutInflater();
    View instView = getViewAtPosition(position);
    instView.setTag("layoutThingy"+position);
    container.addView(instView);
    instView.requestFocus();
    return instView;
}

已更改: instantiateItem()

public View getViewAtPosition(int position) {
    View view = null;
    switch(position) {
        case 0:
            view = view0;
            break;
        case 1:
            view = view1;
            break;
        case 2:
            view = view2;
            break;
        default:
            view = viewError;
    }
    return view;
}

新: getViewAtPosition()

LayoutInflater

其他东西

初始化PagerAdapter时,请确保传递mPagerAdapter = new TestAdapter(getActivity().getLayoutInflater());作为参数。对我来说就是这样:onStart()

现在,我在View page1 = mPagerAdapter.getViewAtPosition(0); View page2 = mPagerAdapter.getViewAtPosition(1); View page3 = mPagerAdapter.getViewAtPosition(2); if (getArguments() != null) { ((EditText) page1.findViewById(R.id.IDName)).setText(getArguments().getString("name")); ((EditText) page2.findViewById(R.id.IDIPaddress)).setText(getArguments().getString("ip")); ((EditText) page2.findViewById(R.id.IDPort)).setText(getArguments().getString("port")); ((EditText) page3.findViewById(R.id.IDUsername)).setText(getArguments().getString("username")); ((EditText) page3.findViewById(R.id.IDPassword)).setText(getArguments().getString("pass")); } 方法中做到了这一点,但我猜你几乎可以在任何地方做到这一点。

EditText

这可以正确找到我的所有ViewPager,并且应该正确找到我放在{{1}}中的所有内容。大!感谢所有人试图帮助我,当然非常感谢cYrixmorten和他的伟大post