EditText中的setText在从侦听器调用时抛出空指针异常

时间:2015-02-23 01:43:05

标签: android android-layout android-edittext settext oncheckedchanged

我正在尝试创建一个计数器的倒数。每个计时器显示(hh:mm:ss)是由edittexts组成的线性布局。我有一个计数器(用于计数),这是一个只有1个editText的线性布局。我有一个片段,显示2个计时器布局和1个计数器布局。

我的动机是让用户输入总时间和两个值中的一个:每圈的圈数/时间。然后我想使用以下基本方程式计算另一个... timePerLap = totalTime / lapCount。 我有两个单选按钮,一次只能控制一个场的可见性。

现在的问题是:我想进行计算并根据用户输入的值更新radiobuttons的onCheckedChanged()值。我在自定义布局类中调用一个方法来使用EditText的setText设置值,但它会抛出一个带有以下stackTrace的NPE。我调试并发现editText是NOT NULL。所以这不是问题的原因。

java.lang.NullPointerException
            at android.widget.TextView.sendBeforeTextChanged(TextView.java:8850)
            at android.widget.TextView.access$1100(TextView.java:282)
            at android.widget.TextView$ChangeWatcher.beforeTextChanged(TextView.java:11243)
            at android.text.SpannableStringBuilder.sendBeforeTextChanged(SpannableStringBuilder.java:956)
            at android.text.SpannableStringBuilder.replace(SpannableStringBuilder.java:466)
            at android.text.SpannableStringBuilder.delete(SpannableStringBuilder.java:212)
            at android.text.SpannableStringBuilder.delete(SpannableStringBuilder.java:30)
            at android.text.method.BaseKeyListener.backspaceOrForwardDelete(BaseKeyListener.java:94)
            at android.text.method.BaseKeyListener.backspace(BaseKeyListener.java:49)
            at android.text.method.BaseKeyListener.onKeyDown(BaseKeyListener.java:155)
            at android.text.method.NumberKeyListener.onKeyDown(NumberKeyListener.java:138)
            at android.widget.TextView.doKeyDown(TextView.java:6907)
            at android.widget.TextView.onKeyDown(TextView.java:6679)
            at android.view.KeyEvent.dispatch(KeyEvent.java:3173)
            at android.view.View.dispatchKeyEvent(View.java:7994)
            at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1470)
            at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1470)
            at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1470)
            at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1470)
            at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1470)
            at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1470)
            at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1470)
            at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1470)
            at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchKeyEvent(PhoneWindow.java:2262)
            at com.android.internal.policy.impl.PhoneWindow.superDispatchKeyEvent(PhoneWindow.java:1612)
            at android.app.Activity.dispatchKeyEvent(Activity.java:2524)
            at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:2181)
            at android.view.ViewRootImpl$ViewPostImeInputStage.processKeyEvent(ViewRootImpl.java:4665)
            at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4632)
            at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4197)
            at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4251)
            at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4220)
            at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:4331)
            at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4228)
            at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:4388)
            at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4197)
            at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:4251)
            at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:4220)
            at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:4228)
            at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:4197)
            at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:6564)
            at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:6481)
            at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:6452)
            at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:6417)
            at android.view.ViewRootImpl$ViewRootHandler.handleMessage(ViewRootImpl.java:3764)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:146)
            at android.app.ActivityThread.main(ActivityThread.java:5487)
            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:1283)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1099)
            at dalvik.system.NativeStart.main(Native Method)

主要片段:

public class WorkoutTimerFragment extends Fragment {
    TimerLayout mTotalWOTime;
    TimerLayout mTimePerRep;
    RadioButton mTimePerRepRadio;
    RadioButton mRepCountRadio;
    Counter mRepCount;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        LinearLayout parentLayout = (LinearLayout) inflater.inflate(R.layout.workout_timer_fragment, container, false);

        //All variables are initialized ...

        mTimePerRep = (TimerLayout) timePerRepLayout.getChildAt(0);
        mTimePerRep.setVisibility(View.INVISIBLE);
        mRepCount = (Counter) timePerRepLayout.getChildAt(1);

        RadioGroup radioGroupLayout = (RadioGroup) repLayout.getChildAt(1);
        mTimePerRepRadio = (RadioButton) radioGroupLayout.getChildAt(0);
        mRepCountRadio = (RadioButton) radioGroupLayout.getChildAt(1);
        mRepCountRadio.setOnCheckedChangeListener(null);
        mRepCountRadio.setChecked(true);

        mTimePerRepRadio.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    mTimePerRep.setVisibility(View.VISIBLE);
                    mRepCount.setVisibility(View.INVISIBLE);
                    calculateStartTimes();
                }
            }
        });

        mRepCountRadio.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                if (isChecked) {
                    mTimePerRep.setVisibility(View.INVISIBLE);
                    mRepCount.setVisibility(View.VISIBLE);
                }
                calculateStartTimes();
            }
        });

        return parentLayout;
    }

    public void calculateStartTimes() {
        long totalWorkoutTime = mTotalWOTime.getTotalMilliseconds();
        long timePerRep;
        if (totalWorkoutTime > 0) {
            if (mRepCount.getCounterValue() > 0) {
                mTimePerRep.setTime(totalWorkoutTime / mRepCount.getCounterValue());
            } else if ((timePerRep = mTimePerRep.getTotalMilliseconds()) > 0) {
                mRepCount.setCounterValue((int) (totalWorkoutTime / timePerRep));
            } else {
                //TODO AlertDialog showing the user needs to enter some information
            }
        }
    }
}

Counter.java - 在行mCounter.setText(String.valueOf(counterValue))上的setCounterValue()方法中导致以下问题的布局;

public class Counter extends LinearLayout implements BaseLayout {
    private final TextView mCounterHeader;
    private final EditText mCounter;
    private TextWatcher mTextWatcher;
    private BaseLayout.OnItemChangeListener mItemChangedListener;
    private View mView;

    public Counter(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Options, 0, 0);
        String titleText = a.getString(R.styleable.Options_titleText);

        setOrientation(LinearLayout.VERTICAL);
        setGravity(Gravity.CENTER_VERTICAL);

        LayoutInflater inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mView = inflater.inflate(R.layout.counter, this, true);

        mCounterHeader = (TextView) getChildAt(0);
        mCounterHeader.setText(titleText);

        mCounter = (EditText) getChildAt(1);
        mCounter.setText("0");
        mCounter.addTextChangedListener(mTextWatcher);

        mTextWatcher = new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence value, int start, int count, int after) {
            }

            @Override
            public void onTextChanged(CharSequence value, int start, int before, int count) {
            //Some Listener call back I want to implement but don't have an implementation for yet. 
                if (mItemChangedListener != null) {
                    mItemChangedListener.onItemChanged(Counter.this);
                }
            }

            @Override
            public void afterTextChanged(Editable editableValue) {
            }
        };
    }

    public int getCounterValue() {
        return Integer.parseInt((mCounter.getText().toString()));
    }

    public void setCounterValue(int counterValue) {
        if (counterValue > 0) {
            mCounter.setText(String.valueOf(counterValue));
        }
    }

    public void setItemChangedListener(BaseLayout.OnItemChangeListener itemChangedListener) {
        mItemChangedListener = itemChangedListener;
    }
}

1 个答案:

答案 0 :(得分:0)

从上面的代码中,您似乎没有通过调用

初始化自定义侦听器

setItem在您的活动中更改了侦听器。请确认这个