简体   繁体   中英

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). For an edit action, I want to create that dialog with some values already put in.

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 ).

After that, I tried this in the onCreateDialog method for the GSIID dialogFragment:

@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. 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.

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.

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). This did indeed work.

So, basically: How can I prevent this findViewById method from being called too early?

最有可能是通过在您从此方法返回的视图上调用查找来在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.

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

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.

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()

@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()

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. For me it was like this: mPagerAdapter = new TestAdapter(getActivity().getLayoutInflater());

Now, I did this in my onStart() method, but I'm guessing you can do this pretty much everywhere.

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 . Great! Thanks all for trying to help me, and of course a big thank you to cYrixmorten , with his great post .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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