androidandroid-fragmentsmapfragment

android - getFragmentById returns null


I'm trying to get the mapFragment that's in another fragment, but when i call findFragmentById, it only returns null, i'm trying to get it so i can remove it from the fragmentmanager (in the onDestroyView method) but it throws a nullpointerexception, i have no idea how to fix this. The fragment that contains the map is part of a viewpager.

Here's my class for the fragment with the map:

import android.app.Activity;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.Context;
import android.database.DataSetObserver;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.SpinnerAdapter;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapFragment;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;

import java.util.ArrayList;
import java.util.List;

import desomer_michael_2app.desomer_michael_eindopdracht_app.Interfaces.ODKortrijkSportLocaties;
import desomer_michael_2app.desomer_michael_eindopdracht_app.Klassen.Sportlocatie;
import desomer_michael_2app.desomer_michael_eindopdracht_app.Util.Connectivity;
import desomer_michael_2app.desomer_michael_eindopdracht_app.Util.WSKortrijkSportlocaties;


/**
 * A simple {@link Fragment} subclass.
 * Activities that contain this fragment must implement the
 * {@link SportStartFragment.OnSportStartFragmentInteractionListener} interface
 * to handle interaction events.
 */
public class SportStartFragment extends Fragment implements ODKortrijkSportLocaties, OnMapReadyCallback {
    private View view;
    private OnSportStartFragmentInteractionListener mListener;

    public SportStartFragment() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        view = inflater.inflate(R.layout.fragment_sportstart, container, false);

        String huidigegebruiker = getActivity().getIntent().getExtras().getString("huidigeGebruiker");
        TextView welkomstTekst = (TextView) view.findViewById(R.id.tV_welkomtekst);
        welkomstTekst.setText("Welkom, " + huidigegebruiker + "!");

        MapFragment map = (MapFragment) getActivity().getFragmentManager().findFragmentById(R.id.map);
        //getActivity().getSupportFragmentManager().putFragment(null, "mapFragm", map);
        map.getMapAsync(this);

        Spinner spinSporten = (Spinner) view.findViewById(R.id.spinSporten);
        spinSporten.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });

        Connectivity connectie = new Connectivity();
        if(connectie.isConnected(this.getActivity())){
            WSKortrijkSportlocaties webservice = new WSKortrijkSportlocaties();
            webservice.execute(this);
        } else{
            CharSequence toastTekst = "Zorg ervoor dat u verbonden bent met het internet.";
            int duration = Toast.LENGTH_SHORT;
            Toast toast = Toast.makeText(this.getActivity(),toastTekst, duration);
            toast.show();
        }

        return view;
    }

    @Override
    public void onDestroyView(){


            super.onDestroyView();
            Fragment fragm = getActivity().getSupportFragmentManager().findFragmentById(R.id.map);
            android.support.v4.app.FragmentTransaction fragmentTransaction = getActivity().getSupportFragmentManager().beginTransaction();
            fragmentTransaction.remove(fragm);
            fragmentTransaction.commit();


    }


    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mListener = (OnSportStartFragmentInteractionListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
        //map.onDestroy();
    }

    @Override
    public void updateKaart(ArrayList<Sportlocatie> sportlocaties) {

    }

    @Override
    public void getSporten(ArrayList<Sportlocatie> sportlocaties) {
        Log.i("SportActivity", "Aantal sportlocaties: " + Integer.toString(sportlocaties.size()));

        ArrayList<String> sporten = new ArrayList<>();

        for(Sportlocatie sl : sportlocaties){
            char hoofdletter = Character.toUpperCase(sl.getSport().charAt(0));
            String hoofdletterString = hoofdletter + sl.getSport().substring(1);

            if(!sporten.contains(hoofdletterString)){
                char first = Character.toUpperCase(sl.getSport().charAt(0));
                String sportHoofdLetter = first + sl.getSport().substring(1);
                sporten.add(sportHoofdLetter);
            }
        }

        ArrayList<String> juisteSporten = new ArrayList();

        for(String sport : sporten){
            if(!juisteSporten.contains("Petanque") && sport.startsWith("Pet")){
                juisteSporten.add("Petanque");
            } else{
                if(!juisteSporten.contains("Duiveltjesveld") && sport.startsWith("Duiv")){
                    juisteSporten.add("Duiveltjesveld");
                } else{
                    if(!sport.startsWith("Pet") && !sport.startsWith("Duiv")) juisteSporten.add(sport);
                }
            }
        }
        Spinner spinnerSporten = (Spinner) view.findViewById(R.id.spinSporten);
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this.getActivity(), R.layout.support_simple_spinner_dropdown_item, juisteSporten);
        spinnerSporten.setAdapter(adapter);
    }

    @Override
    public void onMapReady(final GoogleMap googleMap) {

        LocationManager locationManager = (LocationManager) getActivity().getSystemService(Context.LOCATION_SERVICE);
        LocationListener locationListener = new LocationListener() {
            @Override
            public void onLocationChanged(Location location) {
                LatLng lokaal;
                lokaal = new LatLng(location.getLatitude(), location.getLongitude());
                googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(lokaal, 16));
                googleMap.addMarker(new MarkerOptions().position(lokaal));
            }

            @Override
            public void onStatusChanged(String provider, int status, Bundle extras) {

            }

            @Override
            public void onProviderEnabled(String provider) {

            }

            @Override
            public void onProviderDisabled(String provider) {

            }
        };

        locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0,0, locationListener);

    }

    /**
     * This interface must be implemented by activities that contain this
     * fragment to allow an interaction in this fragment to be communicated
     * to the activity and potentially other fragments contained in that
     * activity.
     * <p/>
     * See the Android Training lesson <a href=
     * "http://developer.android.com/training/basics/fragments/communicating.html"
     * >Communicating with Other Fragments</a> for more information.
     */
    public interface OnSportStartFragmentInteractionListener {
        // TODO: Update argument type and name

    }
}

The xml of my fragment that contains the mapfragment:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context="desomer_michael_2app.desomer_michael_eindopdracht_app.SportActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/tV_welkomtekst"
        android:textSize="25dp"
        android:layout_gravity="center"/>

    <TextView
        android:text="@string/sportdropdown_tekst"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="25dp"/>

    <Spinner
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:id="@+id/spinSporten"></Spinner>

    <fragment
        android:layout_width="match_parent"
        android:layout_height="300sp"
        android:id="@+id/map"
        android:name="com.google.android.gms.maps.MapFragment"
        />

    <Button
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="@string/tekst_startWorkout"/>


</LinearLayout>

Solution

  • To get a nested fragment you need to call getChildFragmentManager() instead of getSupportFragmentManager(), this will return the fragment.

    But you won't be able to remove the fragment.

    It's impossible to remove fragment added from XML, and in your case unnecessary as it will be destroyed when destroying the parent fragment anyway.