为什么我的Android应用程序显示为空白然后崩溃?

时间:2014-07-04 18:10:28

标签: android android-fragments crash

  代码审核中的

已移动https://codereview.stackexchange.com/questions/56123/why-is-my-android-app-showing-up-blank-and-then-crashing

每当我尝试运行我的Android应用时,它会显示标题栏,其下方没有任何内容。大约两分钟后,它崩溃了。这是logcat:

  

http://pastebin.com/UFKeywgC

我知道问题源于我第一次尝试使用片段结构。这是我的代码:

TipCalculator.java

/* My verion of the Deitel Tip Calculator */
package org.bh.tipcalculator2;

import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.NotificationManager;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.SeekBar;
import android.widget.TableLayout;
import android.widget.TextView;
import android.widget.Toast;

import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class TipCalculator extends Activity {
    // constants used when saving/restoring state
    private static final String BILL_TOTAL     = "BILL_TOTAL";
    private static final String CUSTOM_PERCENT = "CUSTOM_PERCENT";

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




    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.tip_calculator, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    /**
     * A placeholder fragment containing a simple view.
     */
    public static class PlaceholderFragment extends Fragment {

        private double currentBillTotal;      // Bill as entered by the user
        private int currentCustomPercent;     // Custom tip % as set by user
        private EditText billEditText;        // Bill input widget
        private EditText tip10EditText;       // 10% tip output
        private EditText tip15EditText;       // 15% tip output
        private EditText tip20EditText;       // 20% tip output
        private EditText tipCustomEditText;   // ##% tip output
        private EditText total10EditText;     // 10% total output
        private EditText total15EditText;     // 15% total output
        private EditText total20EditText;     // 20% total output
        private EditText totalCustomEditText; // ##% total output
        private TextView customTipTextView;   // Custom tip % output

        public PlaceholderFragment() {

        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            if (savedInstanceState == null)
            {
                getFragmentManager().beginTransaction()
                        .add(R.id.container, new PlaceholderFragment())
                        .commit();
                currentBillTotal = 0;
                currentCustomPercent = 18;
            }
            else
            {
                currentBillTotal = savedInstanceState.getDouble(BILL_TOTAL);
                currentCustomPercent = savedInstanceState.getInt(CUSTOM_PERCENT);
            }
            View rootView = inflater.inflate(R.layout.fragment_tip_calculator, container, false);

            tip10EditText =       (EditText) rootView.findViewById(R.id.tip10EditText);
            tip15EditText =       (EditText) rootView.findViewById(R.id.tip15EditText);
            tip20EditText =       (EditText) rootView.findViewById(R.id.tip20EditText);
            tipCustomEditText =   (EditText) rootView.findViewById(R.id.tipCustomEditText);
            total10EditText =     (EditText) rootView.findViewById(R.id.total10EditText);
            total15EditText =     (EditText) rootView.findViewById(R.id.total15EditText);
            total20EditText =     (EditText) rootView.findViewById(R.id.total20EditText);
            totalCustomEditText = (EditText) rootView.findViewById(R.id.totalCustomEditText);
            customTipTextView =   (TextView) rootView.findViewById(R.id.customTipTextView);

            billEditText = (EditText) rootView.findViewById(R.id.billEditText);
            //System.out.print(billEditText);
            billEditText.addTextChangedListener(billEditTextWatcher);

            SeekBar customSeekBar = (SeekBar) rootView.findViewById(R.id.customSeekBar);
            customSeekBar.setOnSeekBarChangeListener(customSeekBarListener);
            return rootView;
        }

        /**
         * Calls {@link #updateStandard()} and then {@link #updateCustom()}.
         *
         * @see #updateStandard()
         * @see #updateCustom()
         */
        public void updateAll()
        {
            updateStandard();
            updateCustom();
        }

        public void updateStandard()
        {
            calculateTipAndTotal(tip10EditText, total10EditText, .1);
            calculateTipAndTotal(tip15EditText, total15EditText, .15);
            calculateTipAndTotal(tip20EditText, total20EditText, .2);
        }

        public void updateCustom()
        {
            customTipTextView.setText(currentCustomPercent + "%");
            calculateTipAndTotal(tipCustomEditText, totalCustomEditText, currentCustomPercent);
        }

        public void calculateTipAndTotal(EditText tipEditText, EditText totalEditText, double tip)
        {
            tipEditText  .setText(String.format("%.02f", currentBillTotal * tip));
            totalEditText.setText(String.format("%.02f", currentBillTotal * (tip + 1)));
        }

        @Override
        public void onSaveInstanceState(Bundle outState)
        {
            super.onSaveInstanceState(outState);

            outState.putDouble(BILL_TOTAL, currentBillTotal);
            outState.putInt(CUSTOM_PERCENT, currentCustomPercent);
        }

        private SeekBar.OnSeekBarChangeListener customSeekBarListener =
                new SeekBar.OnSeekBarChangeListener()
                {
                    @Override
                    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                        currentCustomPercent = seekBar.getProgress();
                        updateCustom();
                    }

                    @Override public void onStartTrackingTouch(SeekBar seekBar){}
                    @Override public void onStopTrackingTouch(SeekBar seekBar){}
                }
                ;

        private TextWatcher billEditTextWatcher =
                new TextWatcher()
                {
                    @Override
                    public void onTextChanged(CharSequence s, int start, int before, int count) {
                        try
                        {
                            currentBillTotal = extractDouble(s);
                        }
                        catch (NumberFormatException ex) // if we still didn't get a number
                        {
                            currentBillTotal = 0;
                        }

                        updateAll();
                    }
                    @Override public void beforeTextChanged(CharSequence s, int start, int count, int after){}
                    @Override public void afterTextChanged(Editable editable){}
                }
                ;

        /**
         * Attempts to extract the first double found. This ideally works with percents, currency
         * notation, and other formats where the double is surrounded by delimiters and text, but is
         * not interrupted by it.<br/>
         *<br/>
         * A double may look like any one of these, where {@code #} represents any number of digits 0
         * through 9:
         *
         * <ul>
         *     <li>{@code #}</li>
         *     <li>{@code .#}</li>
         *     <li>{@code #.#}</li>
         * </ul>
         *
         * @param possibleDouble a character sequence that might contain a double
         *
         * @return the extracted double
         *
         * @throws java.lang.NumberFormatException if a double could not be found
         */
        public static double extractDouble(CharSequence possibleDouble)
        {
            /**
             * Matches at least one digit, optionally preceded by a radix point, optionally preceded by
             * any number of digits
             */
            Matcher matcher = Pattern.compile("([0-9]*\\.)?[0-9]+").matcher(possibleDouble);
            matcher.find();
            return Double.parseDouble(matcher.group());
        }
    }
}

activity_tip_calculator.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".TipCalculator"
    tools:ignore="MergeRootFrame" >

    <fragment
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:name="org.bh.tipcalculator2.TipCalculator$PlaceholderFragment"
        android:id="@+id/fragmentTipCalculator"
        android:layout_gravity="center"
        tools:layout="@layout/fragment_tip_calculator" />
</FrameLayout>

fragment_tip_calculator.xml

<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".TipCalculator$PlaceholderFragment"
    android:id="@+id/tableLayout"
    android:stretchColumns="@string/tableLayoutStretchColumns">

    <TableRow
        android:layout_width="match_parent"
        android:layout_height="fill_parent"
        android:id="@+id/tableRow0"
        android:gravity="center_vertical|right">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/billTotalLabel"
            android:id="@+id/billTextView"
            android:textColor="@android:color/secondary_text_dark" />

        <EditText
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:id="@+id/billEditText"
            android:inputType="numberDecimal"
            android:layout_span="3"
            android:text="@string/zeroCurrency"
            android:selectAllOnFocus="false"
            android:focusable="true"
            android:focusableInTouchMode="true"
            android:editable="true"
            android:textIsSelectable="false"
            android:textColor="@android:color/primary_text_dark"
            android:hint="@string/billTotalHint"
            android:enabled="true" />

        <!--NumberPicker
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:id="@+id/billNumberPicker"
            android:layout_span="3" /-->
    </TableRow>

    <TableRow
        android:layout_width="match_parent"
        android:layout_height="fill_parent"
        android:id="@+id/tableRow2" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/tipTextLabel"
            android:id="@+id/tipLabelTextView"
            android:gravity="center_vertical|right"
            android:textColor="@android:color/secondary_text_dark" />

        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:inputType="number"
            android:id="@+id/tip10EditText"
            android:layout_weight="0"
            android:focusable="@bool/outputEditable"
            android:enabled="@bool/outputEditable"
            android:editable="@bool/outputEditable"
            android:longClickable="@bool/outputEditable"
            android:focusableInTouchMode="@bool/outputEditable"
            android:clickable="@bool/outputEditable"
            android:textColor="@android:color/primary_text_dark"
            android:text="@string/zeroCurrency" />

        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:inputType="number"
            android:id="@+id/tip15EditText"
            android:layout_weight="0"
            android:focusable="@bool/outputEditable"
            android:enabled="@bool/outputEditable"
            android:editable="@bool/outputEditable"
            android:longClickable="@bool/outputEditable"
            android:focusableInTouchMode="@bool/outputEditable"
            android:clickable="@bool/outputEditable"
            android:textColor="@android:color/primary_text_dark"
            android:text="@string/zeroCurrency" />

        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:inputType="number"
            android:id="@+id/tip20EditText"
            android:layout_weight="0"
            android:focusable="@bool/outputEditable"
            android:enabled="@bool/outputEditable"
            android:editable="@bool/outputEditable"
            android:longClickable="@bool/outputEditable"
            android:focusableInTouchMode="@bool/outputEditable"
            android:clickable="@bool/outputEditable"
            android:textColor="@android:color/primary_text_dark"
            android:text="@string/zeroCurrency" />
    </TableRow>

    <TableRow
        android:layout_width="match_parent"
        android:layout_height="fill_parent"
        android:id="@+id/tableRow1">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/tenPercent"
            android:id="@+id/tenTextView"
            android:layout_column="1"
            android:gravity="center_horizontal|bottom"
            android:textColor="@android:color/secondary_text_dark" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/fifteenPercent"
            android:id="@+id/fifteenTextView"
            android:gravity="center_horizontal|bottom"
            android:textColor="@android:color/secondary_text_dark" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/twentyPercent"
            android:id="@+id/twentyTextView2"
            android:gravity="center_horizontal|bottom"
            android:textColor="@android:color/secondary_text_dark" />
    </TableRow>

    <TableRow
        android:layout_width="match_parent"
        android:layout_height="fill_parent"
        android:id="@+id/tableRow3" >

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/totalTextLabel"
            android:id="@+id/textView"
            android:gravity="center_vertical|right"
            android:textColor="@android:color/secondary_text_dark" />

        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:inputType="number"
            android:id="@+id/total10EditText"
            android:layout_weight="0"
            android:text="@string/zeroCurrency"
            android:focusable="@bool/outputEditable"
            android:enabled="@bool/outputEditable"
            android:editable="@bool/outputEditable"
            android:longClickable="@bool/outputEditable"
            android:focusableInTouchMode="@bool/outputEditable"
            android:clickable="@bool/outputEditable"
            android:textColor="@android:color/primary_text_dark" />

        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:inputType="number"
            android:id="@+id/total15EditText"
            android:layout_weight="0"
            android:text="@string/zeroCurrency"
            android:focusable="@bool/outputEditable"
            android:enabled="@bool/outputEditable"
            android:editable="@bool/outputEditable"
            android:longClickable="@bool/outputEditable"
            android:focusableInTouchMode="@bool/outputEditable"
            android:clickable="@bool/outputEditable"
            android:textColor="@android:color/primary_text_dark" />

        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:inputType="number"
            android:id="@+id/total20EditText"
            android:layout_weight="0"
            android:text="@string/zeroCurrency"
            android:focusable="@bool/outputEditable"
            android:enabled="@bool/outputEditable"
            android:editable="@bool/outputEditable"
            android:longClickable="@bool/outputEditable"
            android:focusableInTouchMode="@bool/outputEditable"
            android:clickable="@bool/outputEditable"
            android:textColor="@android:color/primary_text_dark" />
    </TableRow>

    <TableRow
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:id="@+id/spacerTableRow"
        android:layout_weight="1">
    </TableRow>

    <TableRow
        android:layout_width="match_parent"
        android:layout_height="fill_parent"
        android:id="@+id/tableRow4"
        android:layout_gravity="bottom">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:text="@string/customTextLabel"
            android:id="@+id/customTextView"
            android:gravity="center_vertical|right"
            android:textColor="@android:color/secondary_text_dark" />

        <SeekBar
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/customSeekBar"
            android:indeterminate="false"
            android:indeterminateOnly="false"
            android:layout_span="2"
            android:max="200"
            android:progress="18" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:text="@string/customTipReadoutPlaceholder"
            android:id="@+id/customTipTextView"
            android:gravity="center_vertical|left" />
    </TableRow>

    <TableRow
        android:layout_width="match_parent"
        android:layout_height="fill_parent"
        android:id="@+id/tableRow5"
        android:layout_gravity="bottom">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textAppearance="?android:attr/textAppearanceSmall"
            android:text="@string/tipTextLabel"
            android:id="@+id/tipCustomTextView"
            android:gravity="center_vertical|right"
            android:textColor="@android:color/secondary_text_dark" />

        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:inputType="number"
            android:id="@+id/tipCustomEditText"
            android:layout_weight="0"
            android:focusable="@bool/outputEditable"
            android:enabled="@bool/outputEditable"
            android:editable="@bool/outputEditable"
            android:longClickable="@bool/outputEditable"
            android:focusableInTouchMode="@bool/outputEditable"
            android:clickable="@bool/outputEditable"
            android:textColor="@android:color/primary_text_dark"
            android:text="@string/zeroCurrency" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/totalTextLabel"
            android:id="@+id/totalCustomTextView"
            android:gravity="center_vertical|right"
            android:textColor="@android:color/secondary_text_dark" />

        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:inputType="number"
            android:id="@+id/totalCustomEditText"
            android:layout_weight="0"
            android:text="@string/zeroCurrency"
            android:focusable="@bool/outputEditable"
            android:enabled="@bool/outputEditable"
            android:editable="@bool/outputEditable"
            android:longClickable="@bool/outputEditable"
            android:focusableInTouchMode="@bool/outputEditable"
            android:clickable="@bool/outputEditable"
            android:textColor="@android:color/primary_text_dark" />
    </TableRow>

</TableLayout>

1 个答案:

答案 0 :(得分:3)

问题出在这里:

 public static class PlaceholderFragment extends Fragment {

    ...

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        if (savedInstanceState == null)
        {
            getFragmentManager().beginTransaction()
                    .add(R.id.container, new PlaceholderFragment())
                    .commit();
            currentBillTotal = 0;
            currentCustomPercent = 18;
        }

当您为PlaceholderFragment创建视图时,您实际上正在创建另一个 PlaceholderFragment并添加它。这将继续运行和消耗内存,直到它完全耗尽(并崩溃)。

简而言之,您应该删除该部分。该片段已被添加。