简体   繁体   中英

Getting views in Activity from fragment

In my project i have a simple class to retrieve location..it has a static Fragment as innerclass.

MainActivity.java

public class MainActivity extends Activity {

    GPSTracker gps;
    double mylatitude, mylongitude;
    TextView txt_location;



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        txt_location = (TextView) findViewById(R.id.current_location);


        if (savedInstanceState == null) {
            getFragmentManager().beginTransaction()
                    .add(R.id.container, new PlaceholderFragment()).commit();

            }


            gps = new GPSTracker(MainActivity.this);


            if (gps.canGetLocation()) {

                mylatitude = gps.getLatitude();
                mylongitude = gps.getLongitude();

                String latis = Double.toString(mylatitude);
                String longis = Double.toString(mylongitude);
                Log.d("my",latis+ "location to string is done   " + longis);
                txt_location.setText(latis+longis);
            }

    }



       public static class PlaceholderFragment extends Fragment {


        public PlaceholderFragment() {

        }

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


            return inflater.inflate(R.layout.fragment_main, container,
                    false);

        }
    }

}

The code is showing NullPointerException at txt_location.setText(latis+longis); .

Logcat log is as follows:

java.lang.RuntimeException: Unable to start activity ComponentInfo{.MainActivity}: java.lang.NullPointerException
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1956)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
            at android.app.ActivityThread.access$600(ActivityThread.java:123)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:4424)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:825)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:592)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.NullPointerException
            at MainActivity.onCreate(MainActivity.java:47)
            at android.app.Activity.performCreate(Activity.java:4465)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1051)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
            at android.app.ActivityThread.access$600(ActivityThread.java:123)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:4424)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:825)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:592)
            at dalvik.system.NativeStart.main(Native Method)

I found That error is because it can not find txt_places from (TextView) findViewById(R.id.current_location); (There isn't any mistake in XML file), because it is the view in fragment's xml not in Activity's. How do I access it in Activity?

Since you are having the TextView inside the fragment and the Location related methods in the activity is completely wrong. Move all of them to one place. Either move the Location related methods inside the fragment, or move the layout from the fragment to the activity.

something like this

public class MainActivity extends Activity {




@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);


    if (savedInstanceState == null) {
        getFragmentManager().beginTransaction()
                .add(R.id.container, new PlaceholderFragment()).commit();

        }
 }

   public static class PlaceholderFragment extends Fragment {

   GPSTracker gps;
   double mylatitude, mylongitude;
   TextView txt_location;

    public PlaceholderFragment() {

    }

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

         View view = inflater.inflate(R.layout.fragment_main, container,
                false);
         txt_location = (TextView) view.findViewById(R.id.current_location);


        gps = new GPSTracker(getActivity());


        if (gps.canGetLocation()) {

            mylatitude = gps.getLatitude();
            mylongitude = gps.getLongitude();

            String latis = Double.toString(mylatitude);
            String longis = Double.toString(mylongitude);
            Log.d("my",latis+ "location to string is done   " + longis);
            txt_location.setText(latis+longis);
        }



        return view;

    }
}

}

Modify onCreateView method like that:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
         Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_main, container,
                false);
    txt_location = (TextView) view.findViewById(R.id.current_location);

    return view;

}

My sidenote as an answer, as the OP requested.

IMHO it is a bad design to change a Fragment 's View from the Activity it is attached to.

A method should be called on the Fragment from the Activity so that the Fragment always handles its own UI, not its parent Activity . That would mean that your Activity (let's say MainActivity ) keeps a variable to its Fragment s (lets say MyFragmentA and MyFragmentB ).

To update the UI of any of MainActivity 's Fragment s you should call a method that will do the work: myFragmentA.updateUI() . So that the Fragment will only be the one to truly touch its UI. It's not MVC design pattern, but cleaner anyway.

In your case TextView txt_location seems to be a View inside a Fragment , so the variable txt_location itself should not be declared in the Activity but in the Fragment it is displayed in.

  1. This makes the code a lot cleaner.
  2. You can truly respect the lifecycle of your objects, being an Activity ( onCreate() , onResume() etc) or a Fragment ( onCreate() , onCreateView() , onViewCreated() etc) which differs.

Answer

Again, in your case (TextView) findViewById(R.id.current_location) makes no sense from the Activity point of view, since current_location is not in its view, but in one of its children: a Fragment .

Place txt_location = (TextView) view.findViewById(R.id.current_location); in onCreateView() of your Fragment and use txt_location.setText() in onViewCreate() or later (again in the Fragment ).

this is very easy . just add getActivity() before findviewbyid for example :

EditText et = (EditText) getActivity().findViewById(R.id.toolbarsrch);

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