如何防止过早调用findViewById方法



所以我有一个Dialog,它包含一些editText字段(这些字段分布在3个片段上,由视图寻呼机显示,以防这些信息很重要)。对于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对话的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,说我试图在null上使用setText,所以view.findViewById()返回null。我想我应该通过将此代码移动到onStart()方法来解决这个问题,以确保在尝试对其进行设置之前一切都在那里,但我仍然会遇到同样的错误。

一直以来,我都注意到对话框在错误发生之前不会打开,所以我猜findViewById()方法仍然调用得太早,但我不知道如何修复它。

我已经进行了测试,以确保我的代码没有被破坏,当按下GSIID对话框上的按钮时运行上面的代码(这样对话框就会打开)。这确实奏效了。

那么,基本上:如何防止这个findViewById方法被过早调用?

很可能是通过在onCreateView()中查找视图,方法是调用从该方法返回的视图的查找。

你需要掌握android中活动的生命周期这个链接可以帮助你理解生命周期中每个步骤的函数调用顺序。

在大多数情况下,您的视图都在onCreatView()中,因此将findViewById放在那里是合理的,但在其他情况下,在调用findViewById 之前,您应该确保视图已经膨胀

好吧,多亏了这篇文章,我的日子得救了。

基本上,您只需要在自定义PagerAdapter中有一个方法,该方法返回您给它的索引的视图

自定义适配器

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

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

更改:instantiateItem()

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

新建:getViewAtPosition()

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

其他东西

初始化PagerAdapter时,请确保传递LayoutInflater作为参数。对我来说是这样的: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中的所有内容。太棒了感谢所有帮助我的人,当然也非常感谢cYrixmorten,感谢他出色的工作。

相关内容

最新更新