-3

When I tapped on an item to open detail activity I got a nullpointer error and managed to figure out which variable is giving the null, mContactItemDetail. I retrieve data from Firebase datasnapshot within onCreate and try to pass it to a global variable mContactItemDetail which seems to be passed or not. When I try to call the mContactItemDetail I get a null value. Can someone help me understand why, what am I missing?

public class DetailActivityFragment extends Fragment {

    private static final String LOG_TAG = DetailActivityFragment.class.getSimpleName();

    private DatabaseReference databaseRef;
    private String mContactID;
    private ContactItemDetail mContactItemDetail;

    private TextView textViewName;
    private TextView textViewNumber;
    private TextView textViewLocation;
    private TextView textViewDescription;

    public DetailActivityFragment() {
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        databaseRef = FirebaseDatabase.getInstance().getReference();

        Bundle arg = getArguments();
        mContactID = arg.getString(Constants.DETAIL_CONTACT_ID);

        Log.v(LOG_TAG, "ContactID " + mContactID);

        databaseRef.child(Constants.FIREBASE_LOCATION_DETAIL_LIST).child(mContactID). addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                Log.v(LOG_TAG, "Datasnapshot: " + dataSnapshot.getValue());

                ContactItemDetail contactItem = dataSnapshot.getValue(ContactItemDetail.class);


                if (contactItem != null) {
                    mContactItemDetail = contactItem;
                }
                Log.v(LOG_TAG, "contactdetail 1: " + mContactItemDetail);               
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_detail, container, false);

        initializeDetailScreen(rootView);


        Log.v(LOG_TAG, "contactdetail 2: " + mContactItemDetail);

    // textViewName.setText(mContactItemDetail.getContactName());
    // textViewNumber.setText(Long.toString(mContactItemDetail.getTel()));
    // textViewLocation.setText(mContactItemDetail.getLocation());
    // textViewDescription.setText(mContactItemDetail.getDescription());


        return rootView;
    }

    public void initializeDetailScreen(View view) {
        textViewName = (TextView) view.findViewById(R.id.detail_textview_name);
        textViewNumber = (TextView) view.findViewById(R.id.detail_textview_contact_number);
        textViewLocation = (TextView) view.findViewById(R.id.detail_textview_location);
        textViewDescription = (TextView) view.findViewById(R.id.detail_textview_description);
    }
}

Logcat for mContactItemDetail in onCreate returns a value

08-09 22:08:11.929 5234-5234/co.house.myapp V/DetailActivityFragment: contactdetail 1: co.house.myapp.model.ContactItemDetail@41ff1c18

But Logcat for mContactItemDetail in onCreateView returns a null

08-09 22:08:11.859 5234-5234/co.house.myapp V/DetailActivityFragment: contactdetail 2: null

and the mContactItemDetail class is as below

public class ContactItemDetail {

    private String contactName;
    private String description;
    private long fax;
    private String location;
    private String postalAddress;
    private long rating;
    private long tel;

    public ContactItemDetail() {
    }

    public ContactItemDetail(String contactName, String description, long fax, String location,
                             String postalAddress, long rating, long tel) {
        this.contactName = contactName;
        this.description = description;
        this.fax = fax;
        this.location = location;
        this.postalAddress = postalAddress;
        this.rating = rating;
        this.tel = tel;
    }

    public String getContactName() {
        return contactName;
    }

    public String getDescription() {
        return description;
    }

    public long getFax() {
        return fax;
    }

    public String getLocation() {
        return location;
    }

    public String getPostalAddress() {
        return postalAddress;
    }

    public long getRating() {
        return rating;
    }

    public long getTel() {
        return tel;
    }
}

And this is the error log that I get if I comment out the textViewNumber in onCreateView, because the null value I believe

08-09 22:01:13.359 6462-6462/? E/SamsungIME: mOCRHelper is null
08-09 22:01:13.649 6462-6462/? E/SamsungIME: mOCRHelper is null
08-09 22:01:13.869 612-612/? E/asset: Creating SharedZip 0x5a0e8d08 /mnt/asec/com.truecaller-1/pkg.apk
08-09 22:01:13.869 612-612/? E/asset: !@+++ opening zip '/mnt/asec/com.truecaller-1/pkg.apk' by system_server(system_server)
08-09 22:01:14.669 612-620/? E/asset: !@+++ closed '/mnt/asec/com.truecaller-1/pkg.apk' by system_server(FinalizerDaemon)
08-09 22:01:15.879 612-612/? E/asset: Creating SharedZip 0x5f8c4640 /mnt/asec/com.truecaller-1/pkg.apk
08-09 22:01:15.889 612-612/? E/asset: !@+++ opening zip '/mnt/asec/com.truecaller-1/pkg.apk' by system_server(system_server)
08-09 22:01:22.189 4744-4744/? E/NetworkScheduler.SR: Invalid parameter app
08-09 22:01:22.189 4744-4744/? E/NetworkScheduler.SR: Invalid package name : Perhaps you didn't include a PendingIntent in the extras?
08-09 22:01:22.209 28564-8748/? E/Drive.UninstallOperation: Package still installed co.house.myapp
08-09 22:01:22.549 612-796/? E/Watchdog: !@Sync 4195
08-09 22:01:22.929 2863-2875/? E/SPPClientService: ============PushLog. commonIsShipBuild. stop!
08-09 22:01:22.929 2863-2875/? E/SPPClientService: [PushClientApplication] Push log off : This is Ship build version
08-09 22:01:23.679 2843-2843/? E/memtrack: Couldn't load memtrack module (No such file or directory)
08-09 22:01:23.679 2843-2843/? E/android.os.Debug: failed to load memtrack module: -2
08-09 22:01:23.679 2811-2811/? E/memtrack: Couldn't load memtrack module (No such file or directory)
08-09 22:01:23.679 2811-2811/? E/android.os.Debug: failed to load memtrack module: -2
08-09 22:01:25.649 2917-2917/? E/memtrack: Couldn't load memtrack module (No such file or directory)
08-09 22:01:25.649 2917-2917/? E/android.os.Debug: failed to load memtrack module: -2
Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
Ndheti
  • 266
  • 3
  • 18

1 Answers1

2

Simply wait for the Firebase method to finish. Don't try to immediately use the variable result.

private void showContactItemDetail(ContactItemDetail item) {
    if (item == null) return; // Might want to Log here

    textViewName.setText(item.getContactName());
    textViewNumber.setText(Long.toString(item.getTel()));
    textViewLocation.setText(item.getLocation());
    textViewDescription.setText(item.getDescription());
}

Then, you can use that method like so in onCreateView. Otherwise, you'll also get a null error on your views when you go to set the details of them.

That being said - onCreate isn't needed at all other than to set databaseRef.

View rootView = inflater.inflate(R.layout.fragment_detail, container, false);
initializeDetailScreen(rootView);

databaseRef.child(Constants.FIREBASE_LOCATION_DETAIL_LIST).child(mContactID). addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        mContactItemDetail = dataSnapshot.getValue(ContactItemDetail.class);
        showContactItemDetail(mContactItemDetail);             
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {

    }
});

return rootView;
OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
  • your solution worked but I am not sure I understand asynchronous here and what my mistake was. Correct me if i am wrong, would you say in my code onDataChange() method was running at the same time as onCreateView() method (that would be the asynchronous i think). And I was trying to access the mContactItemDetail before onDataChange() could assign value to mContactItemDetail (not FINISHED). And that was my mistake. I am still new to programming so trying to get a firm understanding of priciple – Ndheti Aug 09 '16 at 23:30
  • Yeah, essentially that's exactly what happened. You were waiting on a network request (asynchronous) while other code ran – OneCricketeer Aug 10 '16 at 01:08