简体   繁体   中英

Using a fragment in ViewPager

I'm new to Android, this is my first project, I've spent a while trying to solve this now and have hit a bit of a dead end. I'm wanting to open a fragment using ViewPager, and then access the fragment from the Activity it was opened from. I have tried creating the fragment in the Activity rather than the ViewPager but that throws up a different error.

public class TorchActivity extends SherlockFragmentActivity {

private static TorchFragment torchFrag;

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    ViewPager pager = (ViewPager) findViewById(R.id.pager);
    pager.setAdapter(new ViewPagerAdapter(getSupportFragmentManager()));
}   

public static class ViewPagerAdapter extends FragmentPagerAdapter {

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

    @Override
    public int getCount() {
        return (2);
    }

    @Override
    public Fragment getItem(int position) {
        if(position == 0){
            torchFrag = new TorchFragment();
            return torchFrag;
        }else{
            ColourPickerFragment colourPickerFrag = new ColourPickerFragment();
            return colourPickerFrag;
        }
    }
}
}

main.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/pager"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</android.support.v4.view.ViewPager>

When I come to access the fragment later on in the same Activity I get a NullPointerException.

@Override
public void lightSensorCheck(boolean isThereALightSensor) {
    torchFrag.setIsThereALightSensor(isThereALightSensor);
}

In the fragment:

public void setIsThereALightSensor(boolean isThereALightSensor) {
    this.isThereALightSensor = isThereALightSensor;
}

It works fine if I take the ViewPager code out and run it, any help is appreciated.

    02-17 16:01:30.132: E/AndroidRuntime(32006): FATAL EXCEPTION: main
02-17 16:01:30.132: E/AndroidRuntime(32006): java.lang.RuntimeException: Unable to start activity ComponentInfo{uk.co.bimrose.android.survivaltorch/uk.co.bimrose.android.survivaltorch.TorchActivity}: java.lang.NullPointerException
02-17 16:01:30.132: E/AndroidRuntime(32006):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2517)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2574)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at android.app.ActivityThread.access$600(ActivityThread.java:162)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1413)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at android.os.Handler.dispatchMessage(Handler.java:99)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at android.os.Looper.loop(Looper.java:158)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at android.app.ActivityThread.main(ActivityThread.java:5789)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at java.lang.reflect.Method.invokeNative(Native Method)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at java.lang.reflect.Method.invoke(Method.java:525)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1027)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:843)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at dalvik.system.NativeStart.main(Native Method)
02-17 16:01:30.132: E/AndroidRuntime(32006): Caused by: java.lang.NullPointerException
02-17 16:01:30.132: E/AndroidRuntime(32006):    at uk.co.bimrose.android.survivaltorch.TorchActivity.lightSensorCheck(TorchActivity.java:199)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at uk.co.bimrose.android.survivaltorch.LightFragment.updateLightSensorStatus(LightFragment.java:180)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at uk.co.bimrose.android.survivaltorch.LightFragment.sensorCheck(LightFragment.java:134)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at uk.co.bimrose.android.survivaltorch.LightFragment.onAttach(LightFragment.java:65)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:883)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1104)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:682)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1460)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:556)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at uk.co.bimrose.android.survivaltorch.TorchActivity.onStart(TorchActivity.java:109)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1239)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at android.app.Activity.performStart(Activity.java:5205)
02-17 16:01:30.132: E/AndroidRuntime(32006):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2490)
02-17 16:01:30.132: E/AndroidRuntime(32006):    ... 11 more

Here is the code for the fragment:

public class TorchFragment extends SherlockFragment implements OnClickListener {

private Button buttonOn;
private Button buttonSos;
private Button buttonOff;

private TextView luxStatic;
private TextView luxMessage;
private TextView timerStatic;
private TextView timerMessage;
private TextView batteryStatic;
private TextView batteryMessage;
private TextView shutdownMessage;
private TextView shutdownMessageStatic;
private TextView timesUsed;

private ImageView img;
private TextView heading;

private SharedPreferences prefs;
private int lightSensitivity;
private boolean timerOn;
private int batteryPct;

private boolean isThereALightSensor;

public static int serviceCount;

private AlertResetListener alertResetListener;
private ServiceListener sListener;
private SetDataListener sDListener;
private ClearShutdownMessageListener cSMListener;
private ColourSchemeListener cSListener;

private int[] colourScheme = new int[4];
private LinearLayout dataCompassLayout;

int x = 0;

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);

    // Makes sure that the container activity has implemented the callback interface
    try {
        alertResetListener = (AlertResetListener) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString() + " must implement AlertReset");
    }

    // start / stop service
    try {
        sListener = (ServiceListener) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString() + " must implement ServiceListener");
    }

    // Clear the dataFragment
    try {
        sDListener = (SetDataListener) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString() + " must implement SetDataListener");
    }

    // Clear the dataFragment shutdown message
    try {
        cSMListener = (ClearShutdownMessageListener) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString() + " must implement ClearShutdownMessageListener");
    }

    // Get the colourscheme
    try {
        cSListener = (ColourSchemeListener) activity;
    } catch (ClassCastException e) {
        throw new ClassCastException(activity.toString() + " must implement ColourSchemeListener");
    }

}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
    View result = inflater.inflate(R.layout.torchfrag, parent, false);

    buttonOn = (Button) result.findViewById(R.id.button_on);
    buttonSos = (Button) result.findViewById(R.id.button_sos);
    buttonOff = (Button) result.findViewById(R.id.button_off);

    buttonOn.setText("ON");
    buttonOff.setText("OFF");
    buttonSos.setText("SOS");

    luxStatic = (TextView) result.findViewById(R.id.luxstatic);
    luxMessage = (TextView) result.findViewById(R.id.luxmessage);
    timerStatic = (TextView) result.findViewById(R.id.timerstatic);
    timerMessage = (TextView) result.findViewById(R.id.timermessage);
    batteryStatic = (TextView) result.findViewById(R.id.batterystatic);
    batteryMessage = (TextView) result.findViewById(R.id.batterymessage);
    shutdownMessage = (TextView) result.findViewById(R.id.shutdownmessage);
    shutdownMessageStatic = (TextView) result.findViewById(R.id.shutdownmessagestatic);
    timesUsed = (TextView) result.findViewById(R.id.timesused);

    timesUsed.setText(Integer.toString(TorchActivity.timesUsed));

    //Compass
    img = (ImageView) result.findViewById(R.id.compass);
    heading = (TextView) result.findViewById(R.id.heading);
    dataCompassLayout = (LinearLayout) result.findViewById(R.id.datacompasslayout);

    setColourScheme();

    buttonOn.setOnClickListener(this);
    buttonSos.setOnClickListener(this);
    buttonOff.setOnClickListener(this);

    return (result);
}

public void onResume() {
    setColourScheme();
    clearShutdownMessage();
    getPreferences();
    clearText();
    setStaticMessage();
    super.onResume();
}

@Override
public void onClick(View view) {
    alertResetListener.alertReset();
    TorchActivity.keepRunning = false;
    cSMListener.clearShutdownMessage();
    switch (view.getId()) {
    case R.id.button_on:
        serviceCount++;
        sListener.startService("on");
        break;
    case R.id.button_sos:
        serviceCount++;
        sListener.startService("sosPreset");
        break;
    case R.id.button_off:
        sListener.reset();
        sDListener.setData();
        break;
    default:
        throw new RuntimeException("Unknown button ID");
    }
}

private void setColourScheme(){
    //Calls the method from the activity which gets the colour scheme from the ColourSchemeFragment
    colourScheme = cSListener.getColourScheme();
    buttonOn.setBackgroundColor(getResources().getColor(colourScheme[0]));
    buttonOff.setBackgroundColor(getResources().getColor(colourScheme[1]));
    buttonSos.setBackgroundColor(getResources().getColor(colourScheme[2]));
    dataCompassLayout.setBackgroundColor(getResources().getColor(colourScheme[3]));
}

public void setSosTextColour(String s){
    int sosColour = 0;
    if(s.equals("white")){
        sosColour = R.color.button_text_sos;
    }else{
        sosColour = R.color.button_text_onoff;
    }
    try {
        XmlResourceParser parser = getResources().getXml(sosColour);
        ColorStateList colors = ColorStateList.createFromXml(getResources(), parser);
        buttonSos.setTextColor(colors);
    } catch (Exception e) {
        // handle exceptions
    }
}

// Called from TorchActivity whenever some new data is sent from one of the sensors
public void setMessage(int msg, String from) {
    if (from.equals("light")) {
        luxMessage.setText("Current LUX: " + Integer.toString(msg) + "\n");
    } else if (from.equals("timer")) {
        timerMessage.setText("Turns off in " + Integer.toString(msg) + " minutes\n");
    } else if (from.equals("battery")) {
        // Stops it updating battery % when the torch isn't on
        if (TorchActivity.keepRunning) {
            batteryMessage.setText("Current battery level: " + Integer.toString(msg) + "\n");
            //toast("********");
        }
    }
}

public void setStaticMessage() {
    if (lightSensitivity < 1000) {
        luxStatic.setText("Turns off at " + Integer.toString(lightSensitivity) + " LUX");
    }
    if (timerOn) {
        timerStatic.setText("Timer: ON");
    } else {
        timerStatic.setText("Timer: OFF");
    }
    if (batteryPct > 0) {
        batteryStatic.setText("Turns off at " + Integer.toString(batteryPct) + "% battery");
    }
    shutdownMessageStatic.setText("Torch stopped by: ");
}

public void clearText() {
    luxMessage.setText("\n");
    luxStatic.setText("Light Monitor: OFF");
    // only lets it clear the timer if the torch is off, && it's not the first time through. On the first time
    // through it was getting cleared when it shouldn't have been.
    if (!TorchActivity.keepRunning && !TorchActivity.autoOn) {
        timerMessage.setText("\n");
    }
    timerStatic.setText("\nTimer: OFF");
    batteryMessage.setText("\n");
    batteryStatic.setText("Battery monitor: OFF");
}

public void updateCompass(String s, RotateAnimation rA){
    img.startAnimation(rA);
    heading.setText(s);
}

public void setImageWhite(){
    img.setImageResource(R.drawable.compass_white);
}

public void setImageBlack(){
    img.setImageResource(R.drawable.compass);
}

private void getPreferences() {
    prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
    lightSensitivity = Integer.valueOf(prefs.getString("lightsensitivity", "1000000"));
    timerOn = prefs.getBoolean("timeron", false);
    batteryPct = Integer.valueOf(prefs.getString("batterypct", "50"));
}

// From TorchActivity
public void setShutdownMessage(String s) {
    shutdownMessage.setText("The " + s);
}

public void clearShutdownMessage() {
    shutdownMessage.setText("");
}

public void setIsThereALightSensor(boolean isThereALightSensor) {
    this.isThereALightSensor = isThereALightSensor;
}

public boolean getIsThereALightSensor() {
    return isThereALightSensor;
}

// Container Activity must implement this interface
public interface AlertResetListener {
    public void alertReset();
}

// Container Activity must implement this interface
public interface ServiceListener {
    public void startService(String s);

    // Resets the service and the timer
    public void reset();
}

// Container Activity must implement this interface
public interface SetDataListener {
    public void setData();
}

public interface ClearShutdownMessageListener {
    public void clearShutdownMessage();
}

public interface ColourSchemeListener {
    public int[] getColourScheme();
}

}

Looks like you are calling setIsThereALightSensor before the fragment is attached.

This is confirmed from your comment

Quoting

I solved the issue by starting the fragments in the onAttach in the TorchFragment (via the hosting activity) so it was up and running when it's methods were called

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