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.
- 009 Android programming 3rd Activity生命周期以及debug处理
- 010 Android programming 3rd 第二个activity android sdk
- 008 Android programming 3rd 学习写android程序以及MVC模型
- Android Activity生命周期以及LoCat的使用
- Android中Activity生命周期以及启动模式
- Android Activity的生命周期以及用法建议
- Android的activity以及其生命周期
- Android插件化之Activity生命周期处理
- Android Activity生命周期以及Fragment生命周期的区别与分析
- Android Activity生命周期以及Fragment生命周期的区别与分析
- Android Activity生命周期以及Fragment生命周期的区别与分析
- Android Activity生命周期以及Fragment生命周期的区别与分析
- Android重启当前Activity以及Activity生命周期的变化
- 【Android】【Activity生命周期】Activity生命周期
- Android 屏幕旋转生命周期以及处理方法
- Beginning Linux Programming, 3rd Edition
- C++ Programming Language, The (3rd Edition)
- Programming ASP.NET, 3rd Edition
- 32 《奇特的一生》 -豆瓣评分8.5
- easyui Multiline TextBox 获取值
- 算法概论课后习题 8.14
- 编程娱乐之俄罗斯方块
- 如何编译wxWidgets示例程序(samples目录下的程序)
- 009 Android programming 3rd Activity生命周期以及debug处理
- hdu2686
- CentOS7 彻底清除MySQL
- poj1068括号加密
- 软件中的数学计算引起的一些简单思考
- python浅拷贝和深拷贝 copy()和deepcopy()
- kotlin 基本语法(一)
- request获取路径
- 线程状态