简体   繁体   English

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

[英]How can I prevent my findViewById method from being called too early?

So I've got a Dialog , which contains some editText fields (these are spread over 3 fragments, shown by a viewpager, in case this info matters). 因此,我有一个Dialog ,其中包含一些editText字段(在此信息很重要的情况下,它们分布在3个片段中,由viewpager显示)。 For an edit action, I want to create that dialog with some values already put in. 对于edit操作,我想创建一个对话框,并添加一些值。

At the moment I'm trying to do it like this: 目前,我正在尝试这样做:

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

This shows the onClickListener for the edit button (which is contained in a recyclerView . This particular bit comes from my Adapter ). 这显示了用于编辑按钮的onClickListener(包含在recyclerView 。这一点来自我的Adapter )。

After that, I tried this in the onCreateDialog method for the GSIID dialogFragment: 之后,我在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();
}

This returned a NPE , saying I was trying to use setText on a null, so view.findViewById() is returning null. 这返回了一个NPE ,表示我试图在null上使用setText ,因此view.findViewById()返回null。 I thought I'd fix that by moving this code to the onStart() method, to make sure everything is there before I try to set stuff on it, but I'm still getting the same error. 我以为可以通过将代码移到onStart()方法来解决此问题,以确保在尝试对其进行设置之前所有内容都存在,但仍然出现相同的错误。

All this time, I'm noticing that the dialog does NOT open before the error occurs, so I'm guessing the findViewById() method is still called too soon, but I don't know how to fix that. 一直以来,我注意到该对话框在错误发生之前不会打开,因此我猜findViewById()方法仍然调用得太早,但是我不知道如何解决。

I have tested to make sure my code is not broken, by having the above code run when a button on the GSIID dialog is pressed (so the dialog is opened then). 我已经测试过,通过按GSIID对话框上的按钮(然后打开对话框)来运行上面的代码,以确保我的代码没有损坏。 This did indeed work. 确实确实有效。

So, basically: How can I prevent this findViewById method from being called too early? 因此,基本上:如何防止该findViewById方法被过早调用?

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

You need to master the life-cycle of an Activity in android this link and this link can help you to understand the sequence of function calls in each step of the life-cycle. 您需要在android中掌握此链接的生命周期,此链接可以帮助您了解生命周期每个步骤中函数调用的顺序。

In most cases you have your views in onCreatView() so it is reasonable to put your findViewById there but in other cases you should make sure the view has been inflated before you call findViewById 在大多数情况下,您的视图位于onCreatView()因此将您的findViewById放在此处是合理的,但在其他情况下,应确保视图已膨胀,然后再调用findViewById

Well, my day is saved, thanks to this post. 好吧,感谢这篇文章,我的日子得以保存。

Basically, you just need a method inside your custom PagerAdapter that returns the view for the index you give it. 基本上,您只需要在自定义PagerAdapter中使用一个方法,该方法PagerAdapter以为您提供的索引返回视图。

CustomAdapter 自定义适配器

New: Constructor (I believe that's what it's called) 新增内容: 构造函数 (我相信这就是它的名字)

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

Changed: instantiateItem() 更改: 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;
}

New: getViewAtPosition() 新增: 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;
}

Other stuff 其他的东西

When initialising PagerAdapter, make sure you pass a LayoutInflater as an argument. 初始化PagerAdapter时,请确保传递LayoutInflater作为参数。 For me it was like this: mPagerAdapter = new TestAdapter(getActivity().getLayoutInflater()); 对我来说就像这样: mPagerAdapter = new TestAdapter(getActivity().getLayoutInflater());

Now, I did this in my onStart() method, but I'm guessing you can do this pretty much everywhere. 现在,我在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"));
}

This properly finds all my EditText 's, and should properly find everything I put in my ViewPager . 这样可以正确找到我所有的EditText ,并且应该可以找到我放在ViewPager Great! 大! Thanks all for trying to help me, and of course a big thank you to cYrixmorten , with his great post . 谢谢大家为我提供的帮助,当然也非常感谢cYrixmorten的出色职务

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM