简体   繁体   中英

Fragment views null when called from onResume activity

I want to read NFC tags and I am able to do so when the activity is in the foreground. However, when the activity is not in the foreground and an NFC tag is detected, the activity is not able to resume and throws an exception like the following:

java.lang.NullPointerException: Attempt to invoke virtual method 'void  android.widget.TextView.setText(java.lang.CharSequence)' on a null object reference

I am using Viewpager with FragmentPagerAdapter to setup the tabs. All of this setup is done in the onCreate() method as below:

public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_main);

    toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    /*assert getSupportActionBar() != null;
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);*/


    viewPager = (ViewPager) findViewById(R.id.viewpager);
    setupViewPager(viewPager);

    tabLayout = (TabLayout) findViewById(R.id.tabs);
    tabLayout.setupWithViewPager(viewPager);

    mWriteFragmentIndex = 1;
    mReadFragmentIndex = 0;

    mNfcAdapter = NfcAdapter.getDefaultAdapter(MainActivity.this);
    mPendingIntent = PendingIntent.getActivity(MainActivity.this, 0,
            new Intent(MainActivity.this, MainActivity.class).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
}

And the Fragment Pager Adapter looks like the following:

private void setupViewPager(ViewPager viewPager) {

    adapter = new ViewPagerAdapter(getSupportFragmentManager());

    mReadFragment = new ReadFragment();
    adapter.addFragment(mReadFragment, "Read");


    mWriteFragment = new WriteFragment();
    adapter.addFragment(mWriteFragment, "Write");

    viewPager.setAdapter(adapter);

}

class ViewPagerAdapter extends FragmentPagerAdapter {
    private final List<Fragment> mFragmentList = new ArrayList<>();
    private final List<String> mFragmentTitleList = new ArrayList<>();

    public ViewPagerAdapter(FragmentManager manager) {
        super(manager);
    }

    @Override
    public Fragment getItem(int position) {
        return mFragmentList.get(position);
    }

    @Override
    public int getCount() {
        return mFragmentList.size();
    }

    public void addFragment(Fragment fragment, String title) {
        mFragmentList.add(fragment);
        mFragmentTitleList.add(title);
    }

    @Override
    public CharSequence getPageTitle(int position) {
        return mFragmentTitleList.get(position);
    }


    @Override
    public Object instantiateItem(ViewGroup container, int position) {

        Fragment fragment = (Fragment) super.instantiateItem(container, position);

        if(fragment instanceof ReadFragment){
            mReadFragment = (ReadFragment) fragment;
        }
        if(fragment instanceof WriteFragment){
            mWriteFragment = (WriteFragment) fragment;
        }
        return fragment;
    }


}

When an NFC tag is detected while the activity is not in the foreground, I receive the NFC intent in the onResume method. Then, I call a method in the fragment to read the tag.

    private void readIfTag(Intent intent){

    if(NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction()) || NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction())){

        if(mReadFragment != null) {

           mReadFragment.readTag(intent);

            if(viewPager.getCurrentItem() != mReadFragmentIndex) {
                viewPager.setCurrentItem(mReadFragmentIndex);
            }

        }

    }

}

Tag is read properly(I can see the text retrieved from the tag in the log) but the exception is thrown when the fragment tries to update its view.

I can see from the logs that the instantiateItem() of the PagerAdapter and in turn the onCreateView() of the fragment is executed AFTER the readIfTag() method, which is why the fragment view is empty. I do not understand why this is/where I have made a mistake.

Any help with any part of the code is appreciated. Thanks.

Update The method in the fragment that gets called is given below. Notice that the mInstructionTextView.setText("") is the line that throws the exception. So in other words, the fragment somehow exists but its view does not.

 public void readTag(Intent intent) {

    String action = intent.getAction();
    if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {

        String type = intent.getType();
        if (MIME_TEXT_PLAIN.equals(type)) {

            Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            Ndef ndef = Ndef.get(tag);
            if (ndef == null) {
                // NDEF is not supported by this Tag.
                return;
            }
            NdefMessage ndefMessage = ndef.getCachedNdefMessage();

            NdefRecord[] records = ndefMessage.getRecords();
            for (NdefRecord ndefRecord : records) {
                if (ndefRecord.getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_TEXT)) {
                    try {
                        String result =  readText(ndefRecord);


                                mInstructionTextView.setText("");

I managed to solve the problem by using an interface between the Activity and the Fragment.

The problem was that the method accessing the Fragment view was executing before the FragmentPagerAdapter had instantiated the Fragments fully(their views, to be precise).

Therefore, what I did was to create an interface in the Fragment that the Activity had to implement. At the end of the onCreateView() of the Fragment, I called the method in the interface. In the implementation of this method(which is in the Activity), I called the method for reading tag.

maybe try invoking code you invoke inside onResume in

void onResumeFragments()

and quote from docu

This is the fragment-orientated version of onResume() that you can override to perform operations in the Activity at the same point where its fragments are resumed.

Don't put Code in onCreate ! onCreate() is called before onCreateView().So you can't get view in onCreate() .

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