Android Fragment生命周期使应用崩溃

时间:2015-05-11 21:08:45

标签: android android-fragments

当创建自定义Fragment对象的Session显示信息时,我需要使用所选Session的属性加载UI。

第一次创建Fragment时,此方法正常 我在onStart中为设置编写了代码,因为布局不会在onCreateView之前调用onStart。 (http://developer.android.com/guide/components/fragments.html

问题是:每当手机旋转时,应用程序崩溃,显然是因为onStart被调用,

我尝试使用onActivityCreatedonResume代替但没有奏效,这是onCreateView

之后自动调用的唯一三个函数

如果不禁用旋转,我该怎么办?

这里有一个很好的片段生命周期图: http://developer.android.com/guide/components/fragments.html

05-12 01:03:12.968  21599-21599/com.example.kn.ib W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0x418f3da0)
    05-12 01:03:12.968  21599-21599/com.example.kn.ib E/AndroidRuntime﹕ FATAL EXCEPTION: main
        Process: com.example.kn.ib, PID: 21599
        java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.kn.ib/com.example.kn.ib.IBCentralActivity}: java.lang.NullPointerException
                at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2305)
                at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2363)
                at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3924)
                at android.app.ActivityThread.access$1000(ActivityThread.java:161)
                at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1271)
                at android.os.Handler.dispatchMessage(Handler.java:102)
                at android.os.Looper.loop(Looper.java:157)
                at android.app.ActivityThread.main(ActivityThread.java:5356)
                at java.lang.reflect.Method.invokeNative(Native Method)
                at java.lang.reflect.Method.invoke(Method.java:515)
                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
                at dalvik.system.NativeStart.main(Native Method)
         Caused by: java.lang.NullPointerException
                at com.example.karimnseir.instabeat.IBSessionInfoFragment.onActivityCreated(IBSessionInfoFragment.java:117)
                at android.app.Fragment.performActivityCreated(Fragment.java:1708)
                at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:908)
                at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1062)
                at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1044)
                at android.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1853)
                at android.app.Activity.performCreate(Activity.java:5429)
                at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1105)
                at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2269)
                at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2363)
                at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3924)
                at android.app.ActivityThread.access$1000(ActivityThread.java:161)
                at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1271)
                at android.os.Handler.dispatchMessage(Handler.java:102)
                at android.os.Looper.loop(Looper.java:157)
                at android.app.ActivityThread.main(ActivityThread.java:5356)
                at java.lang.reflect.Method.invokeNative(Native Method)
                at java.lang.reflect.Method.invoke(Method.java:515)
                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
                at dalvik.system.NativeStart.main(Native Method)

片段onStart(第117行是"ID: "+ session._id + "\n" +

   @Override
    public void onStart() {
        super.onStart();


        sessionID = activityCallback.getSelectedSessionID();
        db = activityCallback.getSessionDatabase();
        instabeatTimeService = new InstabeatDateAndTime();

        session = db.getSession(sessionID);

        TextView textViewForTesting = (TextView) getView().findViewById(R.id.test);
        String testText = "\n" +
                "ID: "+ session._id + "\n" +
                "LAP COUNT: "+ session._lapCount + "\n" +
                "DATE: "+ session._date + "\n" +
                "CALORIES: "+ session._calories + "\n" +
                "ISOPEN: "+ session._isOpen + "\n" +
                "LASTMOD: "+ session._lastMod;

        textViewForTesting.setText(testText);

        Button saveButton = (Button) getView().findViewById(R.id.SessionInfo_SaveButton);
        saveButton.setOnClickListener(this);

        isOpenTextField = (EditText) getView().findViewById(R.id.ISOPEN);
        poolSizeTextField = (EditText) getView().findViewById(R.id.POOLSIZE);
        commentTextField = (EditText) getView().findViewById(R.id.COMMENT);
        metricTextField = (EditText) getView().findViewById(R.id.METRIC);


        Date sessionDate = instabeatTimeService.getDateFromLong(session._date);
        int sessionDay = instabeatTimeService.getDayFromDate(sessionDate);
        int sessionMonth = instabeatTimeService.getMonthFromDate(sessionDate);
        int sessionYear = instabeatTimeService.getYearFromDate(sessionDate);
        int sessionHour = instabeatTimeService.getHourFromDate(sessionDate);
        int sessionMinute = instabeatTimeService.getMinuteFromDate(sessionDate);

        dateField  = (EditText) getView().findViewById(R.id.sessionDateField);
        dateFormatter = new SimpleDateFormat("MM/dd/yyyy", Locale.US);

        dateField.setInputType(InputType.TYPE_NULL);
        dateField.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                datePickerDialog.show();
            }
        });
        dateField.setText(sessionMonth + "/" + sessionDay + "/" + sessionYear);

        datePickerDialog = new DatePickerDialog(getActivity(), new DatePickerDialog.OnDateSetListener() {

            public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
                Calendar newDate = Calendar.getInstance();
                newDate.set(year, monthOfYear, dayOfMonth);
                dateField.setText(dateFormatter.format(newDate.getTime()));
            }

        },sessionYear, sessionMonth, sessionDay);

        timeField = (EditText) getView().findViewById(R.id.sessionTimeField);
        //TODO: set user preferences for time format HH or KK
        timeFormatter = new SimpleDateFormat("HH:mm", Locale.US);

        timeField.setInputType(InputType.TYPE_NULL);
        timeField.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                timePickerDialog.show();
            }
        });
        timeField.setText(sessionHour + ":" + sessionMinute);

        timePickerDialog = new TimePickerDialog(getActivity(), new TimePickerDialog.OnTimeSetListener() {

            public void onTimeSet(TimePicker view,  int hourOfDay, int minute) {
                Calendar newTime = Calendar.getInstance();
                int hr = newTime.get(Calendar.HOUR_OF_DAY);
                int mn = newTime.get(Calendar.MINUTE);
                /*TODO: set user preferences for time format HH or KK */
                dateField.setText(hr+":"+mn);
            }

        },sessionHour, sessionMinute, true/*TODO: set user preferences for time format HH or KK */);
        isOpenTextField.setText(session._isOpen+"");
        metricTextField.setText(session._metric);
        commentTextField.setText(session._comment);
        poolSizeTextField.setText("" + session._poolSize);
    }

1 个答案:

答案 0 :(得分:1)

活动和片段生命周期在android上并不是微不足道的。 请记住活动和片段将被销毁并在设备轮换时重新创建,因此,如果您需要一个不再调用的方法,您可以使用片段的onCreate方法并将setRetainInstanceState(true)放在同一个方法中。通过这种方式,片段将保留并且不会在设备方向更改时被破坏。  此外,您必须在xml布局中定义片段,并且必须分配id,如果您的布局是以编程方式添加的,或者没有UI,您可以使用FragmentManager和标签来添加和检索片段。

您可以查看android handling runtime changes指南