Android 代碼用來返回上一個activity 調用onKeyDown()時發生java.lang.NullPointerException.
很多人想從一個Activity返回到上一級Activity時,考慮通過在點擊事件里調用OnKeyDown事件來返回上一級,如下:
toolbarBack.setOnClickListener(newOnClickListener(){@Overridepublicvoid onClick(View v){OnKeyDown(KeyEvent.KEYCODE_BACK,null);}});
會發現報空指針錯誤,具體原因看下源碼,你沒傳入的參數(即null)在OnKeyDown方法中使用到了,所以空指針。
其實返回上一級,不用考慮如此復雜,我們可以使用如下:直接結束當前Activity不就行了。測試可用
toolbarBack.setOnClickListener(newOnClickListener()
{@Overridepublicvoid onClick(View v){
ReaderActivity.this.finish();
}
});
注意:
要在第一個activity向第二個activity跳轉的時候將第一個activity finish(),這樣在第二個activity返回第一個activity時,就會執行第一個activity的onCreate()方法。
我嘗試着在第一種方法中使用如下:
toolbarBack.setOnClickListener(newOnClickListener(){@Overridepublicvoid onClick(View v){OnKeyDown(KeyEvent.KEYCODE_BACK,newKeyEvent(KeyEvent.KEYCODE_BACK,KeyEvent.ACTION_DOWN));}});
雖說無空指針錯誤,但是沒任何效果。我也不解,望知情的兄弟告知一聲哈!
下面我再貼一些其他的 方法
Android實戰總結之返回鍵返回上一級Activity(Intent的一種用法)
實現功能: 有兩個Activity,一個為tabActivity,一個為EditActivity,tabActivity進入EditActivity后,在EditActivity中單擊返回鍵返回tabActivity.
其實很簡單,這其中涉及到onKeyDown(),和Intent。
只要在EditActivity中重寫onKeyDown()實現捕獲返回鍵,再加一Intent實現Activity的跳轉。
具體實現:
1
2
3
4
5
6
7
8
9
10
11
|
@Override
public
boolean
onKeyDown(
int
keyCode, KeyEvent event)
{
if
(keyCode == KeyEvent.KEYCODE_BACK){
Intent myIntent =
new
Intent();
myIntent =
new
Intent(EditActivity.
this
, tabActivity.
class
);
startActivity(myIntent);
this
.finish();
}
return
super
.onKeyDown(keyCode, event);
}
|
3.在A中用startActivityForResult(Intent intent,int requestcode)啟動B,值得注意的是requestcode里的值在多個Activity時使用Reuest_OK,無法從B返回到a的onActivityResult。
重寫A的onActivityResult(int requestCode, int resultCode, Intent data),B在返回前使用setResult(int resultCode,Intent data)設置返回的數據,最后調用b的finish后會返回A的onActivityResult方法。
看例子
3.11 返回數據到前一個Activity
startActivityForResult方法
范例說明
上一個范例中,好不容易將數據從Activity1傳遞至Activity2,如果要再回到Activity1,數據該不會要再封裝一次吧?而且前一個Activity1早就被程序destroy了,倘若在Activity1最后以finish() 結束程序,再通過Activity2將數據采用Bundle的方式通過新打開Activity1傳遞參數,這樣的做法雖然也可以恢復User輸入的數據,但是並不符合我們的期待,尤其是User曾經輸入過的數據,如果不小心點擊回到上一頁,數據就消失不見,這就不妙了。
有鑒於科技始終來自於人性,如果要在次頁面加上一個"回上頁"的按鈕,而非通過模擬器的回復鍵,且回上頁后又能保留之前輸入的相關信息,那么就必須使用startActivityForResult()來喚起一個Activity。利用這個方法,前一個Activity1便會有一個等待次Activity2的返回,而返回的數據就可以達到我們想要的結果。
運行結果
范例程序
- src/irdc.ex03_11/EX03_11.java
在Activity1主程序中調用Activity的方法更改成startActivityForResult(intent,0),其中0為下一個Activity要返回值的依據,可指定為自行定義的參考標識符(Identifier)。程序覆蓋了onActivityResult() 這個方法,令程序在收到result后,再重新加載寫回原本輸入的值。
- package irdc.ex03_11;
- /* import相關class */
- import android.app.Activity;
- import android.content.Intent;
- import android.os.Bundle;
- import android.view.View;
- import android.widget.Button;
- import android.widget.EditText;
10. import android.widget.RadioButton;
- 11.
12. public class EX03_11 extends Activity
13. {
- 14. private EditText et;
- 15. private RadioButton rb1;
- 16. private RadioButton rb2;
- 17.
- 18. /** Called when the activity is first created. */
- 19. @Override
- 20. public void onCreate(Bundle savedInstanceState)
- 21. {
- 22. super.onCreate(savedInstanceState);
- 23. /* 載入main.xml Layout */
- 24. setContentView(R.layout.main);
- 25.
- 26. /* 以findViewById()取得Button對象,並添加onClickListener */
- 27. Button b1 = (Button) findViewById(R.id.button1);
- 28. b1.setOnClickListener(new Button.OnClickListener()
- 29. {
- 30. public void onClick(View v)
- 31. {
- 32. /*取得輸入的身高*/
- 33. et = (EditText) findViewById(R.id.height);
- 34. double height=Double.parseDouble(et.getText().toString());
- 35. /*取得選擇的性別*/
- 36. String sex="";
- 37. rb1 = (RadioButton) findViewById(R.id.sex1);
- 38. rb2 = (RadioButton) findViewById(R.id.sex2);
- 39. if(rb1.isChecked())
- 40. {
- 41. sex="M";
- 42. }
- 43. else
- 44. {
- 45. sex="F";
- 46. }
- 47.
- 48. /*new一個Intent對象,並指定class*/
- 49. Intent intent = new Intent();
- 50. intent.setClass(EX03_11.this,EX03_11_1.class);
- 51.
- 52. /*new一個Bundle對象,並將要傳遞的數據傳入*/
- 53. Bundle bundle = new Bundle();
- 54. bundle.putDouble("height",height);
- 55. bundle.putString("sex",sex);
- 56.
- 57. /*將Bundle對象assign給Intent*/
- 58. intent.putExtras(bundle);
- 59.
- 60. /*調用Activity EX03_11_1*/
- 61. startActivityForResult(intent,0);
- 62. }
- 63. });
- 64. }
- 65.
- 66. /* 覆蓋 onActivityResult()*/
- 67. @Override
- 68. protected void onActivityResult(int requestCode, int resultCode,
- 69. Intent data)
- 70. {
- 71. switch (resultCode)
- 72. {
- 73. case RESULT_OK:
- 74. /* 取得來自Activity2的數據,並顯示於畫面上 */
- 75. Bundle bunde = data.getExtras();
- 76. String sex = bunde.getString("sex");
- 77. double height = bunde.getDouble("height");
- 78.
- 79. et.setText(""+height);
- 80. if(sex.equals("M"))
- 81. {
- 82. rb1.setChecked(true);
- 83. }
- 84. else
- 85. {
- 86. rb2.setChecked(true);
- 87. }
- 88. break;
- 89. default:
- 90. break;
- 91. }
- 92. }
93. }
src/irdc.ex03_11/EX03_11_1.java
在Activity2的主程序中,設計當Button被點擊時,將Bundle對象與結果返回給前一個Activity1。
- package irdc.ex03_11;
- /* import相關class */
- import java.text.DecimalFormat;
- import java.text.NumberFormat;
- import android.app.Activity;
- import android.content.Intent;
- import android.os.Bundle;
- import android.view.View;
10. import android.widget.Button;
11. import android.widget.TextView;
- 12.
13. public class EX03_11_1 extends Activity
14. {
- 15. Bundle bunde;
- 16. Intent intent;
- 17. /** Called when the activity is first created. */
- 18. @Override
- 19. public void onCreate(Bundle savedInstanceState)
- 20. {
- 21. super.onCreate(savedInstanceState);
- 22. /* 載入mylayout.xml Layout */
- 23. setContentView(R.layout.myalyout);
- 24.
- 25. /* 取得Intent中的Bundle對象 */
- 26. intent=this.getIntent();
- 27. bunde = intent.getExtras();
- 28.
- 29. /* 取得Bundle對象中的數據 */
- 30. String sex = bunde.getString("sex");
- 31. double height = bunde.getDouble("height");
- 32.
- 33. /* 判斷性別 */
- 34. String sexText="";
- 35. if(sex.equals("M"))
- 36. {
- 37. sexText="男性";
- 38. }
- 39. else
- 40. {
- 41. sexText="女性";
- 42. }
- 43.
- 44. /* 取得標准體重 */
- 45. String weight=this.getWeight(sex, height);
- 46.
- 47. /* 設置輸出文字 */
- 48. TextView tv1=(TextView) findViewById(R.id.text1);
- 49. tv1.setText("你是一位"+sexText+"\n你的身高是"+height+
- 50. "厘米\n你的標准體重是"+weight+"公斤");
- 51.
- 52. /* 以findViewById()取得Button對象,並添加onClickListener */
- 53. Button b1 = (Button) findViewById(R.id.button1);
- 54. b1.setOnClickListener(new Button.OnClickListener()
- 55. {
- 56. public void onClick(View v)
- 57. {
- 58. /* 返回result回上一個activity */
- 59. EX03_11_1.this.setResult(RESULT_OK, intent);
- 60.
- 61. /* 結束這個activity */
- 62. EX03_11_1.this.finish();
- 63. }
- 64. });
- 65. }
- 66.
- 67. /* 四舍五入的method */
- 68. private String format(double num)
- 69. {
- 70. NumberFormat formatter = new DecimalFormat("0.00");
- 71. String s=formatter.format(num);
- 72. return s;
- 73. }
- 74.
- 75. /* 以findViewById()取得Button對象,並添加onClickListener */
- 76. private String getWeight(String sex,double height)
- 77. {
- 78. String weight="";
- 79. if(sex.equals("M"))
- 80. {
- 81. weight=format((height-80)*0.7);
- 82. }
- 83. else
- 84. {
- 85. weight=format((height-70)*0.6);
- 86. }
- 87. return weight;
- 88. }
89. }
res/layout/mylayout.xml
mylayout.xml為Activity2(EX03_11_1)的Layout,其中定義了顯示計算結果的TextView與回上一頁的Button按鈕。
- <?xml version="1.0" encoding="utf-8"?>
- <AbsoluteLayout
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- xmlns:android="http://schemas.android.com/apk/res/android"
- >
- <TextView
- android:id="@+id/text1"
- android:layout_width="wrap_content"
- 10. android:layout_height="wrap_content"
- 11. android:textSize="20sp"
- 12. android:layout_x="50px"
- 13. android:layout_y="72px"
- 14. >
- 15. </TextView>
- 16. <Button
- 17. android:id="@+id/button1"
- 18. android:layout_width="100px"
- 19. android:layout_height="48px"
- 20. android:text="回上一頁"
- 21. android:layout_x="110px"
- 22. android:layout_y="180px"
- 23. >
- 24. </Button>
25. </AbsoluteLayout>
AndroidManifest.xml
范例中有兩個Activity,所以AndroidManifest.xml里必須有這兩個activity的聲明,否則系統將無法運行。
- <?xml version="1.0" encoding="utf-8"?>
- <manifest
- xmlns:android="http://schemas.android.com/apk/res/android"
- package="irdc.ex03_11"
- android:versionCode="1"
- android:versionName="1.0.0">
- <application
- android:icon="@drawable/icon"
- android:label="@string/app_name">
- 10. <activity
- 11. android:name=".EX03_11"
- 12. android:label="@string/app_name">
- 13. <intent-filter>
- 14. <action android:name="android.intent.action.MAIN" />
- 15. <category android:name="android.intent.category.LAUNCHER" />
- 16. </intent-filter>
- 17. </activity>
- 18. <activity android:name="EX03_11_1"></activity>
- 19. </application>
20. </manifest>
擴展學習
范例中為了在回到上一頁時,能夠顯示之前所輸入的數據,故將原本傳遞次Activity的Intent(里面包含了有數據的Bundle對象)再重新返回給主Activity1。如果要在次Activity2中返回其它的數據,例如,經過計算后的結果、數據,此時只需將要返回的數據再放入Bundle對象中即可達成。
此外,以本范例而言,其實使用startActivity()也可達成同樣的結果,僅需在主Activity被create時去判斷Intent內有沒有數據,有的話,就將數據帶入;沒有的話,就帶入空值(null)。但程序還需要再做有無值的比較,較為繁瑣,既然Android API中有提供更好用的方法,何來不用的道理?更何況如果系統不是只有幾行代碼,而是幾十行、幾百行代碼,那時頭可就大了!