009 Android programming 3rd Activity生命周期以及debug处理

来源:互联网 发布:omtp转ctia软件 编辑:程序博客网 时间:2024/06/08 07:38

第三章 Activity生命周期

在旋转屏幕的时候,每次都会跳到第一个问题中。

生命周期

其中onCreate具体应该做哪些工作

Typically, an activity overrides onCreate(Bundle) to prepare the
specifics of its UI:

1. inflating widgets and putting them on screen (in the call to (setContentView(int))

2. getting references to inflated widgets

3. setting listeners on widgets to handle user interaction

4. connecting to external model data


package com.audio.android.geoquiz;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.view.Gravity;import android.view.View;import android.widget.Button;import android.widget.TextView;import android.widget.Toast;public class QuizActivity extends AppCompatActivity {    private static final String TAG = "QuizActivity";    private Button mTrueButton;    private Button mFalseButton;    private Button mPrevButton;    private Button mNextButton;    private TextView mQuestionTextView;    private Question[] mQuestionBank = new Question[] {            new Question(R.string.question_australia, true),            new Question(R.string.question_oceans, true),            new Question(R.string.question_mideast,false),            new Question(R.string.question_africa, false),            new Question(R.string.question_americas, true),            new Question(R.string.question_asia, true),    };    private int mCurrentIndex = 0;    //Toast correctToast = Toast.makeText(QuizActivity.this, R.string.correct_toast, Toast.LENGTH_SHORT);    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        Log.d(TAG, "onCreate (Bundle) called");        setContentView(R.layout.activity_quiz);        mQuestionTextView = (TextView) findViewById(R.id.question_text_view);        updateQuestion();        mQuestionTextView.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                mCurrentIndex = (mCurrentIndex + 1) % mQuestionBank.length;                updateQuestion();            }        });        mTrueButton = (Button) findViewById(R.id.true_button);        mTrueButton.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                checkAnswer(true);            }        });        mFalseButton = (Button) findViewById(R.id.false_button);        mFalseButton.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                checkAnswer(false);            }        });        mPrevButton = (Button) findViewById(R.id.prev_button);        mPrevButton.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                mCurrentIndex = mCurrentIndex - 1 < 0 ? (mCurrentIndex - 1 + mQuestionBank.length) : mCurrentIndex - 1;                mCurrentIndex = mCurrentIndex % mQuestionBank.length;                updateQuestion();            }        });        mNextButton = (Button) findViewById(R.id.next_button);        mNextButton.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                mCurrentIndex = (mCurrentIndex + 1) % mQuestionBank.length;                updateQuestion();            }        });    }    private void updateQuestion() {        int question = mQuestionBank[mCurrentIndex].getTextResId();        mQuestionTextView.setText(question);    }    private void checkAnswer(boolean userPressedTrue) {        boolean answerIsTrue = mQuestionBank[mCurrentIndex].isAnswerTrue();        int messageResId = 0;        if (userPressedTrue == answerIsTrue) {            messageResId = R.string.correct_toast;        } else {            messageResId = R.string.incorrect_toast;        }        Toast.makeText(this, messageResId, Toast.LENGTH_SHORT).show();    }    @Override    protected void onStart() {        super.onStart();        Log.d(TAG, "onStart() called");    }    @Override    protected void onResume() {        super.onResume();        Log.d(TAG, "onResume() called");    }    @Override    protected void onPause() {        super.onPause();        Log.d(TAG, "onPause() called");    }    @Override    protected void onStop() {        super.onStop();        Log.d(TAG, "onStop() called");    }    @Override    protected void onDestroy() {        super.onDestroy();        Log.d(TAG, "onDestroy() called");    }}

点击开启,和返回键时的调用顺序。

06-25 15:05:25.638 30412-30412/com.audio.android.geoquiz D/QuizActivity: onCreate (Bundle) called
06-25 15:05:25.758 30412-30412/com.audio.android.geoquiz D/QuizActivity: onStart() called
06-25 15:05:25.761 30412-30412/com.audio.android.geoquiz D/QuizActivity: onResume() called

06-25 15:05:35.420 30412-30412/com.audio.android.geoquiz D/QuizActivity: onPause() called
06-25 15:05:35.831 30412-30412/com.audio.android.geoquiz D/QuizActivity: onStop() called
06-25 15:05:35.831 30412-30412/com.audio.android.geoquiz D/QuizActivity: onDestroy() called

可以很清楚地看到函数的调用情况。

开始回调之前先要调用父类的函数

These superclass calls are required. Calling the superclass implementation should be the first line of each callback method override implementation.

按home键有的效果

This means, after pressing Home, your instance of QuizActivity hangs out in the stopped state (in memory, not visible, and not active in the foreground).

最近使用的菜单中打开程序

A quick look at Logcat shows that your activity got calls to onStart() and onResume().

设备配置

Rotating the device changes the device configuration. The device configuration is a set of characteristics that describe the current state of an individual device. The characteristics that make up the configuration include screen orientation screen density, screen size, keyboard type, dock mode, language, and more.


创建一个横幅的画面

FrameLayout介绍

FrameLayout is the simplest ViewGroup and does not arrange its children in any particular manner. In this layout, child views will be arranged according to their

android:layout_gravity attributes.

横竖屏时数据会丢失,需要重写onSaveInstanceState(Bundle outState)方法。

Note that the types that you can save to and restore from a Bundle are primitive types and classes that implement the Serializable or Parcelable interface.

两个挑战,一个是enable/disable相应的按钮,完成。

打印得分,编写完成

<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent">    <TextView        android:id = "@+id/question_text_view"        android:layout_width = "wrap_content"        android:layout_height = "wrap_content"        android:layout_gravity = "center_horizontal"        android:padding = "24dp" />    <LinearLayout        android:layout_width = "wrap_content"        android:layout_height = "wrap_content"        android:layout_gravity = "center_vertical|center_horizontal"        android:padding = "20dp"        android:orientation = "horizontal" >        <Button            android:id = "@+id/true_button"            android:layout_width = "wrap_content"            android:layout_height = "wrap_content"            android:text = "@string/true_button" />        <Button            android:id = "@+id/false_button"            android:layout_width = "wrap_content"            android:layout_height = "wrap_content"            android:text = "@string/false_button"/>    </LinearLayout>    <LinearLayout        android:layout_width = "wrap_content"        android:layout_height = "wrap_content"        android:layout_gravity = "bottom|right"        android:orientation = "horizontal" >        <Button            android:id="@+id/prev_button"            android:layout_width = "wrap_content"            android:layout_height = "wrap_content"            android:text = "@string/prev_button"            android:drawableLeft = "@drawable/arrow_left"            android:drawablePadding = "4dp"/>        <Button            android:id="@+id/next_button"            android:layout_width = "wrap_content"            android:layout_height = "wrap_content"            android:text = "@string/next_button"            android:drawableRight = "@drawable/arrow_right"            android:drawablePadding = "4dp"/>        </LinearLayout>    <LinearLayout        android:layout_width = "wrap_content"        android:layout_height = "wrap_content"        android:orientation = "horizontal" >        <ImageButton            android:id="@+id/prev_img_button"            android:layout_width = "wrap_content"            android:layout_height = "wrap_content"            android:src = "@drawable/arrow_left"            android:contentDescription="@string/previous_question"/>        <ImageButton            android:id="@+id/next_img_button"            android:layout_width = "wrap_content"            android:layout_height = "wrap_content"            android:src = "@drawable/arrow_right"            android:contentDescription="@string/next_question"/>    </LinearLayout></FrameLayout>

package com.audio.android.geoquiz;import android.os.PersistableBundle;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.util.Log;import android.view.Gravity;import android.view.View;import android.widget.Button;import android.widget.TextView;import android.widget.Toast;public class QuizActivity extends AppCompatActivity {    private static final String TAG = "QuizActivity";    private static final String KEY_INDEX = "index";    private Button mTrueButton;    private Button mFalseButton;    private Button mPrevButton;    private Button mNextButton;    private TextView mQuestionTextView;    private Question[] mQuestionBank = new Question[] {            new Question(R.string.question_australia, true),            new Question(R.string.question_oceans, true),            new Question(R.string.question_mideast,false),            new Question(R.string.question_africa, false),            new Question(R.string.question_americas, true),            new Question(R.string.question_asia, true),    };    private int mCurrentIndex = 0;    private int isRight = 0;    private int isWrong = 0;    //Toast correctToast = Toast.makeText(QuizActivity.this, R.string.correct_toast, Toast.LENGTH_SHORT);    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        Log.d(TAG, "onCreate (Bundle) called");        setContentView(R.layout.activity_quiz);        if (savedInstanceState != null) {            mCurrentIndex = savedInstanceState.getInt(KEY_INDEX, 0);        }        mQuestionTextView = (TextView) findViewById(R.id.question_text_view);        int question = mQuestionBank[mCurrentIndex].getTextResId();        mQuestionTextView.setText(question);        mQuestionTextView.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                mCurrentIndex = (mCurrentIndex + 1) % mQuestionBank.length;                updateQuestion();            }        });        mTrueButton = (Button) findViewById(R.id.true_button);        mTrueButton.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                checkAnswer(true);            }        });        mFalseButton = (Button) findViewById(R.id.false_button);        mFalseButton.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                checkAnswer(false);            }        });        mPrevButton = (Button) findViewById(R.id.prev_button);        mPrevButton.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                mCurrentIndex = mCurrentIndex - 1 < 0 ? (mCurrentIndex - 1 + mQuestionBank.length) : mCurrentIndex - 1;                mCurrentIndex = mCurrentIndex % mQuestionBank.length;                updateQuestion();            }        });        mNextButton = (Button) findViewById(R.id.next_button);        mNextButton.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                mCurrentIndex = (mCurrentIndex + 1) % mQuestionBank.length;                updateQuestion();            }        });    }    private void updateQuestion() {        mTrueButton.setClickable(true);        mFalseButton.setClickable(true);        int question = mQuestionBank[mCurrentIndex].getTextResId();        mQuestionTextView.setText(question);    }    private void checkAnswer(boolean userPressedTrue) {        mTrueButton.setClickable(false);        mFalseButton.setClickable(false);        boolean answerIsTrue = mQuestionBank[mCurrentIndex].isAnswerTrue();        int messageResId = 0;        if (userPressedTrue == answerIsTrue) {            messageResId = R.string.correct_toast;            isRight++;        } else {            messageResId = R.string.incorrect_toast;            isWrong++;        }        Toast.makeText(this, messageResId, Toast.LENGTH_SHORT).show();        if ((isRight + isWrong) % mQuestionBank.length == 0)            Toast.makeText(this, "percentage score " + ((float)isRight)/(isRight + isWrong), Toast.LENGTH_SHORT).show();    }    @Override    protected void onStart() {        super.onStart();        Log.d(TAG, "onStart() called");    }    @Override    protected void onResume() {        super.onResume();        Log.d(TAG, "onResume() called");    }    @Override    protected void onPause() {        super.onPause();        Log.d(TAG, "onPause() called");    }    @Override    protected void onSaveInstanceState(Bundle outState) {        super.onSaveInstanceState(outState);        Log.i(TAG, "onSaveInstanceState");        outState.putInt(KEY_INDEX, mCurrentIndex);    }    @Override    protected void onStop() {        super.onStop();        Log.d(TAG, "onStop() called");    }    @Override    protected void onDestroy() {        super.onDestroy();        Log.d(TAG, "onDestroy() called");    }}

截图


第四章  Debugging Android Apps

FATAL EXCEPTION

FATAL EXCEPTION: main                                                                         Process: com.audio.android.geoquiz, PID: 2996                                                                         java.lang.RuntimeException: Unable to start activity ComponentInfo{com.audio.android.geoquiz/com.audio.android.geoquiz.QuizActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(int)' on a null object reference                                                                             at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2665)                                                                             at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)                                                                             at android.app.ActivityThread.-wrap12(ActivityThread.java)

技巧

When you encounter runtime exceptions, remember to look for the last exception in Logcat and the first line in its stack trace that refers to code that you have written.

错误的行为,程序的逻辑错误怎么解决。

Log.d(TAG, "Updating question text", new Exception());

在updateQuestion函数里加上上面的打印之后

01-01 09:04:13.796 7562-7562/com.audio.android.geoquiz D/QuizActivity: Updating question text                                                                       java.lang.Exception                                                                           at com.audio.android.geoquiz.QuizActivity.updateQuestion(QuizActivity.java:103)                                                                           at com.audio.android.geoquiz.QuizActivity.access$200(QuizActivity.java:13)                                                                           at com.audio.android.geoquiz.QuizActivity$5.onClick(QuizActivity.java:93)                                                                           at android.view.View.performClick(View.java:5618)                                                                           at android.view.View$PerformClick.run(View.java:22286)                                                                           at android.os.Handler.handleCallback(Handler.java:751)                                                                           at android.os.Handler.dispatchMessage(Handler.java:95)                                                                           at android.os.Looper.loop(Looper.java:154)                                                                           at android.app.ActivityThread.main(ActivityThread.java:6174)                                                                           at java.lang.reflect.Method.invoke(Native Method)                                                                           at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:865)                                                                           at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:755)


The Layout Inspector button

explore the properties of your layout.


Allocation Tracker

recording memory allocations as you interact with your app.



阅读全文
0 0
原创粉丝点击