代码之家  ›  专栏  ›  技术社区  ›  Samnan

如何解决自定义计时器中的膨胀异常?

  •  0
  • Samnan  · 技术社区  · 7 年前

    我已经在我的android应用程序中创建了一个自定义的时间选择器对话框,android studio在 “inflater.inflate可能产生空异常” 是的。

    以下是自定义计时器的XML文件:

    属性.xml

    <?xml version="1.0" encoding="utf-8"?>
    
    <resources>
        <attr name="timePickerStyle" format="reference" />
        <declare-styleable name="CustomTimePicker">
           <attr name="internalLayout" format="reference"  />
        </declare-styleable>
     </resources>
    

    时间选择器对话.xml

    <?xml version="1.0" encoding="utf-8"?>
    <app.customview.CustomTimePicker xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/timePicker"
    android:layout_gravity="center_horizontal"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    />
    

    时间选择器.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="horizontal"
        android:layout_gravity="center_horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layoutDirection="ltr">
            <!-- hour -->
            <NumberPicker
                android:id="@+id/hour"
                android:layout_width="70dip"
                android:layout_height="wrap_content"
                android:focusable="true"
                android:focusableInTouchMode="true"
                />
    
            <!-- minute -->
            <NumberPicker
                android:id="@+id/minute"
                android:layout_width="70dip"
                android:layout_height="wrap_content"
                android:layout_marginStart="5dip"
                android:focusable="true"
                android:focusableInTouchMode="true"
                />
    
            <!-- minute -->
            <NumberPicker
                android:id="@+id/amPm"
                android:layout_width="70dip"
                android:layout_height="wrap_content"
                android:layout_marginStart="5dip"
                android:focusable="true"
                android:focusableInTouchMode="true"
                />
    
    </LinearLayout>
    

    customTimePickerDialog.java

    package app.customview;
    
    
    import android.app.AlertDialog;
    import android.content.Context;
    import android.content.DialogInterface;
    import android.content.DialogInterface.OnClickListener;
    import android.os.Bundle;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.widget.TimePicker;
    
    import app.customview.CustomTimePicker.OnTimeChangedListener;
    
    /**
     * A dialog that prompts the user for the time of day using a {@link TimePicker}.
     * <p/>
     * <p>See the <a href="{@docRoot}guide/topics/ui/controls/pickers.html">Pickers</a>
     * guide.</p>
     */
    public class CustomTimePickerDialog extends AlertDialog
            implements OnClickListener, OnTimeChangedListener {
    
        private static final String HOUR = "hour";
        private static final String MINUTE = "minute";
        private static final String IS_24_HOUR = "is24hour";
        private final CustomTimePicker mTimePicker;
        private final OnTimeSetListener mCallback;
        int mInitialHourOfDay;
        int mInitialMinute;
        boolean mIs24HourView;
        private View view;
        /**
         * @param context      Parent.
         * @param callBack     How parent is notified.
         * @param hourOfDay    The initial hour.
         * @param minute       The initial minute.
         * @param is24HourView Whether this is a 24 hour view, or AM/PM.
         */
        public CustomTimePickerDialog(Context context,
                                      OnTimeSetListener callBack,
                                      int hourOfDay, int minute, boolean is24HourView) {
            this(context, 0, callBack, hourOfDay, minute, is24HourView);
        }
    
        /**
         * @param context      Parent.
         * @param theme        the theme to apply to this dialog
         * @param callBack     How parent is notified.
         * @param hourOfDay    The initial hour.
         * @param minute       The initial minute.
         * @param is24HourView Whether this is a 24 hour view, or AM/PM.
         */
        public CustomTimePickerDialog(Context context,
                                      int theme,
                                      OnTimeSetListener callBack,
                                      int hourOfDay, int minute, boolean is24HourView) {
            super(context, theme);
            mCallback = callBack;
            mInitialHourOfDay = hourOfDay;
            mInitialMinute = minute;
            mIs24HourView = is24HourView;
    
            setIcon(0);
            // buggy
            setTitle("Set Time");
    
            //Context themeContext = getContext();
            setButton(BUTTON_POSITIVE, "Done", this);
    
            LayoutInflater inflater = getLayoutInflater();
    
            try {
                view = inflater.inflate(R.layout.time_picker_dialog, null);
            } catch(android.view.InflateException e) {
                view = inflater.inflate(R.layout.time_picker_dialog, null);
                // do nothing
            }
            setView(view);
            mTimePicker = (CustomTimePicker) view.findViewById(R.id.timePicker);
    
            // initialize state
            mTimePicker.setIs24HourView(mIs24HourView);
            mTimePicker.setCurrentHour(mInitialHourOfDay);
            mTimePicker.setCurrentMinute(mInitialMinute);
            mTimePicker.setOnTimeChangedListener(this);
    
        }
    
        public void onClick(DialogInterface dialog, int which) {
            tryNotifyTimeSet();
        }
    
        public void updateTime(int hourOfDay, int minutOfHour) {
            mTimePicker.setCurrentHour(hourOfDay);
            mTimePicker.setCurrentMinute(minutOfHour);
        }
    
        private void tryNotifyTimeSet() {
            if (mCallback != null) {
                mTimePicker.clearFocus();
                mCallback.onTimeSet(mTimePicker, mTimePicker.getCurrentHour(),
                        mTimePicker.getCurrentMinute());
            }
        }
    
        @Override
        protected void onStop() {
            tryNotifyTimeSet();
            super.onStop();
        }
    
        @Override
        public Bundle onSaveInstanceState() {
            Bundle state = super.onSaveInstanceState();
            state.putInt(HOUR, mTimePicker.getCurrentHour());
            state.putInt(MINUTE, mTimePicker.getCurrentMinute());
            state.putBoolean(IS_24_HOUR, mTimePicker.is24HourView());
            return state;
        }
    
        @Override
        public void onRestoreInstanceState(Bundle savedInstanceState) {
            super.onRestoreInstanceState(savedInstanceState);
            int hour = savedInstanceState.getInt(HOUR);
            int minute = savedInstanceState.getInt(MINUTE);
            mTimePicker.setIs24HourView(savedInstanceState.getBoolean(IS_24_HOUR));
            mTimePicker.setCurrentHour(hour);
            mTimePicker.setCurrentMinute(minute);
        }
    
        @Override
        public void onTimeChanged(CustomTimePicker view, int hourOfDay, int minute) {
            // TODO Auto-generated method stub
    
        }
    
    
        /**
         * The callback interface used to indicate the user is done filling in
         * the time (they clicked on the 'Set' button).
         */
        public interface OnTimeSetListener {
    
            /**
             * @param view      The view associated with this listener.
             * @param hourOfDay The hour that was set.
             * @param minute    The minute that was set.
             */
            void onTimeSet(CustomTimePicker view, int hourOfDay, int minute);
        }
    
    }
    

    customTimePicker.java

    public CustomTimePicker(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
    
            // initialization based on locale
            setCurrentLocale(Locale.getDefault());
    
            // process style attributes
             TypedArray attributesArray = context.obtainStyledAttributes(
                    attrs, R.styleable.CustomTimePicker, defStyle, 0);
            int layoutResourceId = attributesArray.getResourceId(
               R.styleable.CustomTimePicker_internalLayout, R.layout.time_picker);
             attributesArray.recycle();
    
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(
                    Context.LAYOUT_INFLATER_SERVICE);
            inflater.inflate(layoutResourceId, this, true);
    
            // hour
            mHourSpinner = (NumberPicker) findViewById(R.id.hour);
            mHourSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
                public void onValueChange(NumberPicker spinner, int oldVal, int newVal) {
                    if (!is24HourView()) {
                        if ((oldVal == HOURS_IN_HALF_DAY - 1 && newVal == HOURS_IN_HALF_DAY)
                                || (oldVal == HOURS_IN_HALF_DAY && newVal == HOURS_IN_HALF_DAY - 1)) {
                            mIsAm = !mIsAm;
                            updateAmPmControl();
                        }
                    }
                    onTimeChanged();
                }
            });
    
    
            // minute
            mMinuteSpinner = (NumberPicker) findViewById(R.id.minute);
            mMinuteSpinner.setMinValue(0);
            mMinuteSpinner.setMaxValue(3);
            mMinuteSpinner.setDisplayedValues(new String[]{"0", "15", "30", "45"});
            mMinuteSpinner.setFormatter(new TwoDigitFormatter());
            mMinuteSpinner.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
                public void onValueChange(NumberPicker spinner, int oldVal, int newVal) {
                    onTimeChanged();
                }
            });
    
            /* Get the localized am/pm strings and use them in the spinner */
            mAmPmStrings = new DateFormatSymbols().getAmPmStrings();
    
            // am/pm
            View amPmView = findViewById(R.id.amPm);
            if (amPmView instanceof Button) {
                mAmPmSpinner = null;
                mAmPmButton = (Button) amPmView;
                mAmPmButton.setOnClickListener(new OnClickListener() {
                    public void onClick(View button) {
                        button.requestFocus();
                        mIsAm = !mIsAm;
                        updateAmPmControl();
                        onTimeChanged();
                    }
                });
            } else {
                mAmPmButton = null;
                mAmPmSpinner = (NumberPicker) amPmView;
                mAmPmSpinner.setMinValue(0);
                mAmPmSpinner.setMaxValue(1);
                mAmPmSpinner.setDisplayedValues(mAmPmStrings);
                mAmPmSpinner.setOnValueChangedListener(new OnValueChangeListener() {
                    public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
                        picker.requestFocus();
                        mIsAm = !mIsAm;
                        updateAmPmControl();
                        onTimeChanged();
                    }
                });
            }
    
            // update controls to initial state
            updateHourControl();
            updateAmPmControl();
    
            setOnTimeChangedListener(NO_OP_CHANGE_LISTENER);
    
            // set to current time
            setCurrentHour(mTempCalendar.get(Calendar.HOUR_OF_DAY));
            setCurrentMinute(mTempCalendar.get(Calendar.MINUTE));
    
            if (!isEnabled()) {
                setEnabled(false);
            }
    
        }
    

    =============================

    在customtimepickerdialog.java中,这一行android studio一直在说“may producc java.lang.null exception…”,如果我试图访问视图对象,应用程序也会崩溃,因为它返回的是null。奇怪的是,偶尔这段代码运行良好,我可以看到计时器和应用程序工作良好,但90%的时间,视图膨胀代码返回空值和应用程序崩溃。

    有人能指出我能做些什么来解决这个问题吗(修正警告,最终确保通胀观点有效)。

    谢谢

    版主注意:请不要将此标记为重复,这不是一般的“空异常”错误问题。在问这个问题之前,我已经找了好几天了,因为我找不到任何可能解决我问题的答案。

    1 回复  |  直到 7 年前
        1
  •  0
  •   RoyalGriffin Abhay Koradiya    7 年前

    你可能是因为 LayoutInflator 使用oncreate()之前的活动无法使用的系统服务。尝试用以下方法获取布局充气机:

    LayoutInflater inflater = getLayoutInflater();